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

XFEstudio/gpt4free

Add RequestLogin to HuggingChat

5651760c
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

2 个文件 +51 -49
Modified g4f/Provider/needs_auth/HuggingChat.py +45 -40
@@ -2,7 +2,9 @@ from __future__ import annotations
2 2
3 3 import json
4 4 import re
5 import os
5 6 import requests
7 from typing import AsyncIterator
6 8
7 9 try:
8 10 from curl_cffi.requests import Session, CurlMime
@@ -10,12 +12,13 @@ try:
10 12 except ImportError:
11 13 has_curl_cffi = False
12 14
13 from ..base_provider import ProviderModelMixin, AbstractProvider
15 from ..base_provider import ProviderModelMixin, AsyncAuthedProvider, AuthResult
14 16 from ..helper import format_prompt
15 from ...typing import CreateResult, Messages, Cookies
16 from ...errors import MissingRequirementsError
17 from ...typing import AsyncResult, Messages, Cookies
18 from ...errors import MissingRequirementsError, MissingAuthError, ResponseError
19 from ...requests import get_args_from_nodriver, DEFAULT_HEADERS
17 20 from ...requests.raise_for_status import raise_for_status
18 from ...providers.response import JsonConversation, ImageResponse, Sources, TitleGeneration, Reasoning
21 from ...providers.response import JsonConversation, ImageResponse, Sources, TitleGeneration, Reasoning, RequestLogin
19 22 from ...cookies import get_cookies
20 23 from ... import debug
21 24
@@ -23,7 +26,7 @@ class Conversation(JsonConversation):
23 26 def __init__(self, models: dict):
24 27 self.models: dict = models
25 28
26 class HuggingChat(AbstractProvider, ProviderModelMixin):
29 class HuggingChat(AsyncAuthedProvider, ProviderModelMixin):
27 30 url = "https://huggingface.co/chat"
28 31
29 32 working = True
@@ -85,41 +88,44 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
85 88 return cls.models
86 89
87 90 @classmethod
88 def create_completion(
91 async def on_auth_async(cls, cookies: Cookies = None, proxy: str = None, **kwargs) -> AsyncIterator:
92 if cookies is None:
93 cookies = get_cookies("huggingface.co")
94 if "hf-chat" in cookies:
95 yield AuthResult(
96 cookies=cookies,
97 impersonate="chrome",
98 headers=DEFAULT_HEADERS
99 )
100 return
101 login_url = os.environ.get("G4F_LOGIN_URL")
102 if login_url:
103 yield RequestLogin(cls.__name__, login_url)
104 yield AuthResult(
105 **await get_args_from_nodriver(
106 cls.url,
107 proxy=proxy,
108 wait_for='form[action="/chat/logout"]'
109 )
110 )
111
112 @classmethod
113 async def create_authed(
89 114 cls,
90 115 model: str,
91 116 messages: Messages,
92 stream: bool,
117 auth_result: AuthResult,
93 118 prompt: str = None,
94 119 return_conversation: bool = False,
95 120 conversation: Conversation = None,
96 121 web_search: bool = False,
97 cookies: Cookies = None,
98 122 **kwargs
99 ) -> CreateResult:
123 ) -> AsyncResult:
100 124 if not has_curl_cffi:
101 125 raise MissingRequirementsError('Install "curl_cffi" package | pip install -U curl_cffi')
102 126 model = cls.get_model(model)
103 if cookies is None:
104 cookies = get_cookies("huggingface.co")
105 127
106 session = Session(cookies=cookies)
107 session.headers = {
108 'accept': '*/*',
109 'accept-language': 'en',
110 'cache-control': 'no-cache',
111 'origin': 'https://huggingface.co',
112 'pragma': 'no-cache',
113 'priority': 'u=1, i',
114 'referer': 'https://huggingface.co/chat/',
115 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
116 'sec-ch-ua-mobile': '?0',
117 'sec-ch-ua-platform': '"macOS"',
118 'sec-fetch-dest': 'empty',
119 'sec-fetch-mode': 'cors',
120 'sec-fetch-site': 'same-origin',
121 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
122 }
128 session = Session(**auth_result.get_dict())
123 129
124 130 if conversation is None or not hasattr(conversation, "models"):
125 131 conversation = Conversation({})
@@ -133,14 +139,14 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
133 139 inputs = format_prompt(messages)
134 140 else:
135 141 conversationId = conversation.models[model]["conversationId"]
136 conversation.models[model]["message_id"] = cls.fetch_message_id(session, conversationId)
142 conversation.models[model]["messageId"] = cls.fetch_message_id(session, conversationId)
137 143 inputs = messages[-1]["content"]
138 144
139 debug.log(f"Use model {model}: {json.dumps(conversation.models[model])}")
145 debug.log(f"Use: {json.dumps(conversation.models[model])}")
140 146
141 147 settings = {
142 148 "inputs": inputs,
143 "id": conversation.models[model]["message_id"],
149 "id": conversation.models[model]["messageId"],
144 150 "is_retry": False,
145 151 "is_continue": False,
146 152 "web_search": web_search,
@@ -176,7 +182,6 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
176 182 )
177 183 raise_for_status(response)
178 184
179 full_response = ""
180 185 sources = None
181 186 for line in response.iter_lines():
182 187 if not line:
@@ -189,10 +194,7 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
189 194 if "type" not in line:
190 195 raise RuntimeError(f"Response: {line}")
191 196 elif line["type"] == "stream":
192 token = line["token"].replace('\u0000', '')
193 full_response += token
194 if stream:
195 yield token
197 yield line["token"].replace('\u0000', '')
196 198 elif line["type"] == "finalAnswer":
197 199 break
198 200 elif line["type"] == "file":
@@ -208,9 +210,6 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
208 210 else:
209 211 pass #print(line)
210 212
211 full_response = full_response.replace('<|im_end|', '').strip()
212 if not stream:
213 yield full_response
214 213 if sources is not None:
215 214 yield sources
216 215
@@ -222,8 +221,9 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
222 221 'model': model,
223 222 }
224 223 response = session.post('https://huggingface.co/chat/conversation', json=json_data)
224 if response.status_code == 401:
225 raise MissingAuthError(response.text)
225 226 raise_for_status(response)
226
227 227 return response.json().get('conversationId')
228 228
229 229 @classmethod
@@ -248,6 +248,11 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
248 248 if not json_data:
249 249 raise RuntimeError("Failed to parse response data")
250 250
251 if json_data["nodes"][-1]["type"] == "error":
252 if json_data["nodes"][-1]["status"] == 403:
253 raise MissingAuthError(json_data["nodes"][-1]["error"]["message"])
254 raise ResponseError(json.dumps(json_data["nodes"][-1]))
255
251 256 data = json_data["nodes"][1]["data"]
252 257 keys = data[data[0]["messages"]]
253 258 message_keys = data[keys[-1]]
Modified g4f/requests/__init__.py +6 -9
@@ -78,25 +78,22 @@ async def get_args_from_nodriver(
78 78 url: str,
79 79 proxy: str = None,
80 80 timeout: int = 120,
81 wait_for: str = None,
81 82 cookies: Cookies = None
82 83 ) -> dict:
83 if not has_nodriver:
84 raise MissingRequirementsError('Install "nodriver" package | pip install -U nodriver')
84 browser = await get_nodriver(proxy=proxy)
85 85 if debug.logging:
86 86 print(f"Open nodriver with url: {url}")
87 browser = await nodriver.start(
88 browser_args=None if proxy is None else [f"--proxy-server={proxy}"],
89 )
90 87 domain = urlparse(url).netloc
91 88 if cookies is None:
92 89 cookies = {}
93 90 else:
94 91 await browser.cookies.set_all(get_cookie_params_from_dict(cookies, url=url, domain=domain))
95 92 page = await browser.get(url)
96 for c in await page.send(nodriver.cdp.network.get_cookies([url])):
97 cookies[c.name] = c.value
98 93 user_agent = await page.evaluate("window.navigator.userAgent")
99 94 await page.wait_for("body:not(.no-js)", timeout=timeout)
95 if wait_for is not None:
96 await page.wait_for(wait_for, timeout=timeout)
100 97 for c in await page.send(nodriver.cdp.network.get_cookies([url])):
101 98 cookies[c.name] = c.value
102 99 await page.close()
@@ -120,13 +117,13 @@ def merge_cookies(cookies: Iterator[Morsel], response: Response) -> Cookies:
120 117
121 118 async def get_nodriver(proxy: str = None, user_data_dir = "nodriver", browser_executable_path=None, **kwargs)-> Browser:
122 119 if not has_nodriver:
123 raise MissingRequirementsError('Install "nodriver" package | pip install -U nodriver')
120 raise MissingRequirementsError('Install "nodriver" and "platformdirs" package | pip install -U nodriver platformdirs')
124 121 user_data_dir = user_config_dir(f"g4f-{user_data_dir}") if has_platformdirs else None
125 122 if browser_executable_path is None:
126 123 try:
127 124 browser_executable_path = find_chrome_executable()
128 125 except FileNotFoundError:
129 # Default to Edge if Chrome is not found
126 # Default to Edge if Chrome is not available.
130 127 browser_executable_path = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
131 128 if not os.path.exists(browser_executable_path):
132 129 browser_executable_path = None