返回提交历史
Modified
g4f/Provider/PerplexityLabs.py
+1
-1
Modified
g4f/client/__init__.py
+13
-19
Modified
g4f/client/stubs.py
+6
-4
Modified
g4f/providers/response.py
+5
-5
XFEstudio/gpt4free
Enable PerplexityLabs provider Fix save audio response
686995e0
代码差异
4 个文件
+25
-29
@@ -14,7 +14,7 @@ WS_URL = "wss://www.perplexity.ai/socket.io/"
14
14
15
15
class PerplexityLabs(AsyncGeneratorProvider, ProviderModelMixin):
16
16
url = "https://labs.perplexity.ai"
17
working = False
17
working = True
18
18
19
19
default_model = "r1-1776"
20
20
models = [
@@ -1,6 +1,5 @@
1
1
from __future__ import annotations
2
2
3
import os
4
3
import time
5
4
import random
6
5
import string
@@ -37,6 +36,14 @@ except NameError:
37
36
except StopAsyncIteration:
38
37
raise StopIteration
39
38
39
def add_chunk(content, chunk):
40
if content == "":
41
content = chunk
42
else:
43
chunk = str(chunk)
44
content += chunk
45
return content
46
40
47
# Synchronous iter_response function
41
48
def iter_response(
42
49
response: Union[Iterator[Union[str, ResponseType]]],
@@ -77,20 +84,10 @@ def iter_response(
77
84
elif isinstance(chunk, Exception):
78
85
continue
79
86
80
if isinstance(chunk, list):
81
chunk = "".join(map(str, chunk))
82
else:
83
temp = chunk.__str__()
84
if not isinstance(temp, str):
85
if isinstance(temp, list):
86
temp = "".join(map(str, temp))
87
else:
88
temp = repr(chunk)
89
chunk = temp
90
if not chunk:
87
content = add_chunk(content, chunk)
88
if not content:
91
89
continue
92
93
content += chunk
90
idx += 1
94
91
95
92
if max_tokens is not None and idx + 1 >= max_tokens:
96
93
finish_reason = "length"
@@ -110,8 +107,6 @@ def iter_response(
110
107
if finish_reason is not None:
111
108
break
112
109
113
idx += 1
114
115
110
if usage is None:
116
111
usage = UsageModel.model_construct(completion_tokens=idx, total_tokens=idx)
117
112
else:
@@ -186,10 +181,9 @@ async def async_iter_response(
186
181
elif isinstance(chunk, Exception):
187
182
continue
188
183
189
chunk = str(chunk)
190
if not chunk:
184
content = add_chunk(content, chunk)
185
if not content:
191
186
continue
192
content += chunk
193
187
idx += 1
194
188
195
189
if max_tokens is not None and idx >= max_tokens:
@@ -1,14 +1,16 @@
1
1
from __future__ import annotations
2
2
3
import os
3
4
from typing import Optional, List
4
5
from time import time
5
6
6
7
from ..image import extract_data_uri
8
from ..image.copy_images import images_dir
7
9
from ..client.helper import filter_markdown
8
10
from .helper import filter_none
9
11
10
12
try:
11
from pydantic import BaseModel, Field
13
from pydantic import BaseModel
12
14
except ImportError:
13
15
class BaseModel():
14
16
@classmethod
@@ -17,9 +19,6 @@ except ImportError:
17
19
for key, value in data.items():
18
20
setattr(new, key, value)
19
21
return new
20
class Field():
21
def __init__(self, **config):
22
pass
23
22
24
23
class BaseModel(BaseModel):
25
24
@classmethod
@@ -106,6 +105,9 @@ class ChatCompletionMessage(BaseModel):
106
105
return super().model_construct(role="assistant", content=content, **filter_none(tool_calls=tool_calls))
107
106
108
107
def save(self, filepath: str, allowd_types = None):
108
if hasattr(self.content, "data"):
109
os.rename(self.content.data.replace("/media", images_dir), filepath)
110
return
109
111
if self.content.startswith("data:"):
110
112
with open(filepath, "wb") as f:
111
113
f.write(extract_data_uri(self.content))
@@ -19,18 +19,18 @@ def quote_url(url: str) -> str:
19
19
# Only unquote if needed to avoid double-unquoting
20
20
if '%' in url:
21
21
url = unquote_plus(url)
22
22
23
23
url_parts = url.split("//", maxsplit=1)
24
24
# If there is no "//" in the URL, then it is a relative URL
25
25
if len(url_parts) == 1:
26
26
return quote_plus(url_parts[0], '/?&=#')
27
27
28
28
protocol, rest = url_parts
29
29
domain_parts = rest.split("/", maxsplit=1)
30
30
# If there is no "/" after the domain, then it is a domain URL
31
31
if len(domain_parts) == 1:
32
32
return f"{protocol}//{domain_parts[0]}"
33
33
34
34
domain, path = domain_parts
35
35
return f"{protocol}//{domain}/{quote_plus(path, '/?&=#')}"
36
36
@@ -95,7 +95,7 @@ def format_images_markdown(images: Union[str, List[str]], alt: str,
95
95
"""
96
96
if isinstance(images, list) and len(images) == 1:
97
97
images = images[0]
98
98
99
99
if isinstance(images, str):
100
100
result = format_image(images, alt, preview)
101
101
else:
@@ -107,7 +107,7 @@ def format_images_markdown(images: Union[str, List[str]], alt: str,
107
107
)
108
108
for idx, image in enumerate(images)
109
109
)
110
110
111
111
start_flag = "<!-- generated images start -->\n"
112
112
end_flag = "<!-- generated images end -->\n"
113
113
return f"\n{start_flag}{result}\n{end_flag}\n"