XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Add MetaAI Provider and some small improvments

932d3a3c
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

12 个文件 +221 -12
Modified g4f/Provider/BingCreateImages.py +1 -0
@@ -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
Modified g4f/Provider/Ecosia.py +4 -4
@@ -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():
Added g4f/Provider/MetaAI.py +199 -0
@@ -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]))
Modified g4f/Provider/__init__.py +1 -0
@@ -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
Modified g4f/Provider/base_provider.py +1 -1
@@ -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
Modified g4f/Provider/needs_auth/Groq.py +1 -1
@@ -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"
Modified g4f/Provider/needs_auth/OpenaiAccount.py +0 -1
@@ -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
Modified g4f/client/service.py +1 -0
@@ -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
Modified g4f/gui/client/static/css/style.css +1 -1
@@ -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 */
Modified g4f/gui/client/static/js/chat.v1.js +3 -2
@@ -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}
Modified g4f/gui/server/api.py +1 -1
@@ -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
Modified g4f/providers/types.py +8 -1
@@ -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