返回提交历史
Modified
g4f/Provider/BingCreateImages.py
+1
-0
Modified
g4f/Provider/Ecosia.py
+4
-4
Added
g4f/Provider/MetaAI.py
+199
-0
Modified
g4f/Provider/__init__.py
+1
-0
Modified
g4f/Provider/base_provider.py
+1
-1
Modified
g4f/Provider/needs_auth/Groq.py
+1
-1
Modified
g4f/Provider/needs_auth/OpenaiAccount.py
+0
-1
Modified
g4f/client/service.py
+1
-0
Modified
g4f/gui/client/static/css/style.css
+1
-1
Modified
g4f/gui/client/static/js/chat.v1.js
+3
-2
Modified
g4f/gui/server/api.py
+1
-1
Modified
g4f/providers/types.py
+8
-1
XFEstudio/gpt4free
Add MetaAI Provider and some small improvments
932d3a3c
代码差异
12 个文件
+221
-12
@@ -15,6 +15,7 @@ class BingCreateImages(AsyncGeneratorProvider, ProviderModelMixin):
15
15
label = "Microsoft Designer"
16
16
url = "https://www.bing.com/images/create"
17
17
working = True
18
needs_auth = True
18
19
19
20
def __init__(self, cookies: Cookies = None, proxy: str = None) -> None:
20
21
self.cookies: Cookies = cookies
@@ -15,7 +15,8 @@ class Ecosia(AsyncGeneratorProvider, ProviderModelMixin):
15
15
working = True
16
16
supports_gpt_35_turbo = True
17
17
default_model = "gpt-3.5-turbo-0125"
18
model_aliases = {"gpt-3.5-turbo": "gpt-3.5-turbo-0125"}
18
models = [default_model, "green"]
19
model_aliases = {"gpt-3.5-turbo": default_model}
19
20
20
21
@classmethod
21
22
async def create_async_generator(
@@ -23,11 +24,10 @@ class Ecosia(AsyncGeneratorProvider, ProviderModelMixin):
23
24
model: str,
24
25
messages: Messages,
25
26
connector: BaseConnector = None,
26
green: bool = False,
27
27
proxy: str = None,
28
28
**kwargs
29
29
) -> AsyncResult:
30
cls.get_model(model)
30
model = cls.get_model(model)
31
31
headers = {
32
32
"authority": "api.ecosia.org",
33
33
"accept": "*/*",
@@ -39,7 +39,7 @@ class Ecosia(AsyncGeneratorProvider, ProviderModelMixin):
39
39
data = {
40
40
"messages": base64.b64encode(json.dumps(messages).encode()).decode()
41
41
}
42
api_url = f"https://api.ecosia.org/v2/chat/?sp={'eco' if green else 'productivity'}"
42
api_url = f"https://api.ecosia.org/v2/chat/?sp={'eco' if model == 'green' else 'productivity'}"
43
43
async with session.post(api_url, json=data) as response:
44
44
await raise_for_status(response)
45
45
async for chunk in response.content.iter_any():
@@ -0,0 +1,199 @@
1
import json
2
import uuid
3
import random
4
import time
5
import uuid
6
from typing import Dict, List
7
8
from aiohttp import ClientSession, BaseConnector
9
10
from ..typing import AsyncResult, Messages, Cookies
11
from ..requests import raise_for_status, DEFAULT_HEADERS
12
from ..image import ImageResponse
13
from .base_provider import AsyncGeneratorProvider
14
from .helper import format_prompt, get_connector, get_cookies
15
16
class MetaAI(AsyncGeneratorProvider):
17
url = "https://www.meta.ai"
18
working = True
19
20
def __init__(self, proxy: str = None, connector: BaseConnector = None):
21
self.session = ClientSession(connector=get_connector(connector, proxy), headers=DEFAULT_HEADERS)
22
23
@classmethod
24
async def create_async_generator(
25
cls,
26
model: str,
27
messages: Messages,
28
proxy: str = None,
29
**kwargs
30
) -> AsyncResult:
31
#cookies = get_cookies(".meta.ai", False, True)
32
async for chunk in cls(proxy).prompt(format_prompt(messages)):
33
yield chunk
34
35
async def get_access_token(self, cookies: Cookies, birthday: str = "1999-01-01") -> str:
36
url = "https://www.meta.ai/api/graphql/"
37
38
payload = {
39
"lsd": cookies["lsd"],
40
"fb_api_caller_class": "RelayModern",
41
"fb_api_req_friendly_name": "useAbraAcceptTOSForTempUserMutation",
42
"variables": json.dumps({
43
"dob": birthday,
44
"icebreaker_type": "TEXT",
45
"__relay_internal__pv__WebPixelRatiorelayprovider": 1,
46
}),
47
"doc_id": "7604648749596940",
48
}
49
headers = {
50
"x-fb-friendly-name": "useAbraAcceptTOSForTempUserMutation",
51
"x-fb-lsd": cookies["lsd"],
52
"x-asbd-id": "129477",
53
"alt-used": "www.meta.ai",
54
"sec-fetch-site": "same-origin"
55
}
56
async with self.session.post(url, headers=headers, cookies=cookies, data=payload) as response:
57
await raise_for_status(response, "Fetch access_token failed")
58
auth_json = await response.json(content_type=None)
59
access_token = auth_json["data"]["xab_abra_accept_terms_of_service"]["new_temp_user_auth"]["access_token"]
60
return access_token
61
62
async def prompt(self, message: str, cookies: Cookies = None) -> AsyncResult:
63
access_token = None
64
if cookies is None:
65
cookies = await self.get_cookies()
66
access_token = await self.get_access_token(cookies)
67
else:
68
cookies = await self.get_cookies(cookies)
69
70
url = "https://graph.meta.ai/graphql?locale=user"
71
#url = "https://www.meta.ai/api/graphql/"
72
payload = {
73
"access_token": access_token,
74
#"lsd": cookies["lsd"],
75
"fb_api_caller_class": "RelayModern",
76
"fb_api_req_friendly_name": "useAbraSendMessageMutation",
77
"variables": json.dumps({
78
"message": {"sensitive_string_value": message},
79
"externalConversationId": str(uuid.uuid4()),
80
"offlineThreadingId": generate_offline_threading_id(),
81
"suggestedPromptIndex": None,
82
"flashVideoRecapInput": {"images": []},
83
"flashPreviewInput": None,
84
"promptPrefix": None,
85
"entrypoint": "ABRA__CHAT__TEXT",
86
"icebreaker_type": "TEXT",
87
"__relay_internal__pv__AbraDebugDevOnlyrelayprovider": False,
88
"__relay_internal__pv__WebPixelRatiorelayprovider": 1,
89
}),
90
"server_timestamps": "true",
91
"doc_id": "7783822248314888",
92
}
93
headers = {
94
"x-asbd-id": "129477",
95
"x-fb-friendly-name": "useAbraSendMessageMutation",
96
#"x-fb-lsd": cookies["lsd"],
97
}
98
async with self.session.post(url, headers=headers, cookies=cookies, data=payload) as response:
99
await raise_for_status(response, "Fetch response failed")
100
last_snippet_len = 0
101
fetch_id = None
102
async for line in response.content:
103
try:
104
json_line = json.loads(line)
105
except json.JSONDecodeError:
106
continue
107
bot_response_message = json_line.get("data", {}).get("node", {}).get("bot_response_message", {})
108
streaming_state = bot_response_message.get("streaming_state")
109
fetch_id = bot_response_message.get("fetch_id")
110
if streaming_state in ("STREAMING", "OVERALL_DONE"):
111
#imagine_card = bot_response_message["imagine_card"]
112
snippet = bot_response_message["snippet"]
113
yield snippet[last_snippet_len:]
114
last_snippet_len = len(snippet)
115
elif streaming_state == "OVERALL_DONE":
116
break
117
#if last_streamed_response is None:
118
# if attempts > 3:
119
# raise Exception("MetaAI is having issues and was not able to respond (Server Error)")
120
# access_token = await self.get_access_token()
121
# return await self.prompt(message=message, attempts=attempts + 1)
122
if fetch_id is not None:
123
sources = await self.fetch_sources(fetch_id, cookies, access_token)
124
if sources is not None:
125
yield sources
126
127
async def get_cookies(self, cookies: Cookies = None) -> dict:
128
async with self.session.get("https://www.meta.ai/", cookies=cookies) as response:
129
await raise_for_status(response, "Fetch home failed")
130
text = await response.text()
131
if cookies is None:
132
cookies = {
133
"_js_datr": self.extract_value(text, "_js_datr"),
134
"abra_csrf": self.extract_value(text, "abra_csrf"),
135
"datr": self.extract_value(text, "datr"),
136
}
137
cookies["lsd"] = self.extract_value(text, start_str='"LSD",[],{"token":"', end_str='"}')
138
return cookies
139
140
async def fetch_sources(self, fetch_id: str, cookies: Cookies, access_token: str) -> List[Dict]:
141
url = "https://graph.meta.ai/graphql?locale=user"
142
payload = {
143
"access_token": access_token,
144
"fb_api_caller_class": "RelayModern",
145
"fb_api_req_friendly_name": "AbraSearchPluginDialogQuery",
146
"variables": json.dumps({"abraMessageFetchID": fetch_id}),
147
"server_timestamps": "true",
148
"doc_id": "6946734308765963",
149
}
150
headers = {
151
"authority": "graph.meta.ai",
152
"x-fb-friendly-name": "AbraSearchPluginDialogQuery",
153
}
154
async with self.session.post(url, headers=headers, cookies=cookies, data=payload) as response:
155
await raise_for_status(response)
156
response_json = await response.json()
157
try:
158
message = response_json["data"]["message"]
159
if message is not None:
160
searchResults = message["searchResults"]
161
if searchResults is not None:
162
return Sources(searchResults["references"])
163
except (KeyError, TypeError):
164
raise RuntimeError(f"Response: {response_json}")
165
166
@staticmethod
167
def extract_value(text: str, key: str = None, start_str = None, end_str = '",') -> str:
168
if start_str is None:
169
start_str = f'{key}":{{"value":"'
170
start = text.find(start_str)
171
if start >= 0:
172
start+= len(start_str)
173
end = text.find(end_str, start)
174
return text[start:end]
175
176
def generate_offline_threading_id() -> str:
177
"""
178
Generates an offline threading ID.
179
180
Returns:
181
str: The generated offline threading ID.
182
"""
183
# Generate a random 64-bit integer
184
random_value = random.getrandbits(64)
185
186
# Get the current timestamp in milliseconds
187
timestamp = int(time.time() * 1000)
188
189
# Combine timestamp and random value
190
threading_id = (timestamp << 22) | (random_value & ((1 << 22) - 1))
191
192
return str(threading_id)
193
194
class Sources():
195
def __init__(self, list: List[Dict[str, str]]) -> None:
196
self.list = list
197
198
def __str__(self) -> str:
199
return "\n\n" + ("\n".join([f"[{link['title']}]({link['link']})" for link in self.list]))
@@ -42,6 +42,7 @@ from .Koala import Koala
42
42
from .Liaobots import Liaobots
43
43
from .Llama import Llama
44
44
from .Local import Local
45
from .MetaAI import MetaAI
45
46
from .PerplexityLabs import PerplexityLabs
46
47
from .Pi import Pi
47
48
from .ReplicateImage import ReplicateImage
@@ -1,3 +1,3 @@
1
1
from ..providers.base_provider import *
2
from ..providers.types import FinishReason
2
from ..providers.types import FinishReason, Streaming
3
3
from .helper import get_cookies, format_prompt
@@ -4,7 +4,7 @@ from .Openai import Openai
4
4
from ...typing import AsyncResult, Messages
5
5
6
6
class Groq(Openai):
7
lebel = "Groq"
7
label = "Groq"
8
8
url = "https://console.groq.com/playground"
9
9
working = True
10
10
default_model = "mixtral-8x7b-32768"
@@ -3,5 +3,4 @@ from __future__ import annotations
3
3
from .OpenaiChat import OpenaiChat
4
4
5
5
class OpenaiAccount(OpenaiChat):
6
label = "OpenAI ChatGPT with Account"
7
6
needs_auth = True
@@ -111,5 +111,6 @@ def get_last_provider(as_dict: bool = False) -> Union[ProviderType, dict[str, st
111
111
"name": last.__name__,
112
112
"url": last.url,
113
113
"model": debug.last_model,
114
"label": last.label if hasattr(last, "label") else None
114
115
}
115
116
return last
@@ -890,7 +890,7 @@ a:-webkit-any-link {
890
890
891
891
resize: vertical;
892
892
max-height: 200px;
893
min-height: 80px;
893
min-height: 100px;
894
894
}
895
895
896
896
/* style for hljs copy */
@@ -302,7 +302,7 @@ async function add_message_chunk(message) {
302
302
window.provider_result = message.provider;
303
303
content.querySelector('.provider').innerHTML = `
304
304
<a href="${message.provider.url}" target="_blank">
305
${message.provider.name}
305
${message.provider.label ? message.provider.label : message.provider.name}
306
306
</a>
307
307
${message.provider.model ? ' with ' + message.provider.model : ''}
308
308
`
@@ -545,7 +545,8 @@ const load_conversation = async (conversation_id, scroll=true) => {
545
545
last_model = item.provider?.model;
546
546
let next_i = parseInt(i) + 1;
547
547
let next_provider = item.provider ? item.provider : (messages.length > next_i ? messages[next_i].provider : null);
548
let provider_link = item.provider?.name ? `<a href="${item.provider.url}" target="_blank">${item.provider.name}</a>` : "";
548
let provider_label = item.provider?.label ? item.provider?.label : item.provider?.name;
549
let provider_link = item.provider?.name ? `<a href="${item.provider.url}" target="_blank">${provider_label}</a>` : "";
549
550
let provider = provider_link ? `
550
551
<div class="provider">
551
552
${provider_link}
@@ -99,7 +99,7 @@ class Api():
99
99
if api_key is not None:
100
100
kwargs["api_key"] = api_key
101
101
if json_data.get('web_search'):
102
if provider == "Bing":
102
if provider in ("Bing", "HuggingChat"):
103
103
kwargs['web_search'] = True
104
104
else:
105
105
from .internet import get_search_message
@@ -102,4 +102,11 @@ ProviderType = Union[Type[BaseProvider], BaseRetryProvider]
102
102
103
103
class FinishReason():
104
104
def __init__(self, reason: str):
105
self.reason = reason
105
self.reason = reason
106
107
class Streaming():
108
def __init__(self, data: str) -> None:
109
self.data = data
110
111
def __str__(self) -> str:
112
return self.data