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

XFEstudio/gpt4free

Add cookies to HuggingChat provider

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

代码差异

3 个文件 +129 -153
Modified g4f/Provider/needs_auth/HuggingChat.py +122 -118
@@ -1,16 +1,17 @@
1 1 from __future__ import annotations
2 2
3 3 import json
4 import requests
5 4
6 5 try:
7 from curl_cffi.requests import Session
6 from curl_cffi.requests import Session, CurlMime
8 7 has_curl_cffi = True
9 8 except ImportError:
10 9 has_curl_cffi = False
11 from ...typing import CreateResult, Messages
10
11 from ...typing import CreateResult, Messages, Cookies
12 12 from ...errors import MissingRequirementsError
13 13 from ...requests.raise_for_status import raise_for_status
14 from ...cookies import get_cookies
14 15 from ..base_provider import ProviderModelMixin, AbstractProvider
15 16 from ..helper import format_prompt
16 17
@@ -53,127 +54,130 @@ class HuggingChat(AbstractProvider, ProviderModelMixin):
53 54 model: str,
54 55 messages: Messages,
55 56 stream: bool,
57 web_search: bool = False,
58 cookies: Cookies = None,
56 59 **kwargs
57 60 ) -> CreateResult:
58 61 if not has_curl_cffi:
59 62 raise MissingRequirementsError('Install "curl_cffi" package | pip install -U curl_cffi')
60 63 model = cls.get_model(model)
64 if cookies is None:
65 cookies = get_cookies("huggingface.co")
66
67 session = Session(cookies=cookies)
68 session.headers = {
69 'accept': '*/*',
70 'accept-language': 'en',
71 'cache-control': 'no-cache',
72 'origin': 'https://huggingface.co',
73 'pragma': 'no-cache',
74 'priority': 'u=1, i',
75 'referer': 'https://huggingface.co/chat/',
76 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
77 'sec-ch-ua-mobile': '?0',
78 'sec-ch-ua-platform': '"macOS"',
79 'sec-fetch-dest': 'empty',
80 'sec-fetch-mode': 'cors',
81 'sec-fetch-site': 'same-origin',
82 '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',
83 }
84 json_data = {
85 'model': model,
86 }
87 response = session.post('https://huggingface.co/chat/conversation', json=json_data)
88 raise_for_status(response)
89
90 conversationId = response.json().get('conversationId')
61 91
62 if model in cls.models:
63 session = Session()
64 session.headers = {
65 'accept': '*/*',
66 'accept-language': 'en',
67 'cache-control': 'no-cache',
68 'origin': 'https://huggingface.co',
69 'pragma': 'no-cache',
70 'priority': 'u=1, i',
71 'referer': 'https://huggingface.co/chat/',
72 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
73 'sec-ch-ua-mobile': '?0',
74 'sec-ch-ua-platform': '"macOS"',
75 'sec-fetch-dest': 'empty',
76 'sec-fetch-mode': 'cors',
77 'sec-fetch-site': 'same-origin',
78 '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',
79 }
80 json_data = {
81 'model': model,
82 }
83 response = session.post('https://huggingface.co/chat/conversation', json=json_data)
84 raise_for_status(response)
85
86 conversationId = response.json().get('conversationId')
87
88 # Get the data response and parse it properly
89 response = session.get(f'https://huggingface.co/chat/conversation/{conversationId}/__data.json?x-sveltekit-invalidated=11')
90 raise_for_status(response)
91
92 # Split the response content by newlines and parse each line as JSON
92 # Get the data response and parse it properly
93 response = session.get(f'https://huggingface.co/chat/conversation/{conversationId}/__data.json?x-sveltekit-invalidated=11')
94 raise_for_status(response)
95
96 # Split the response content by newlines and parse each line as JSON
97 try:
98 json_data = None
99 for line in response.text.split('\n'):
100 if line.strip():
101 try:
102 parsed = json.loads(line)
103 if isinstance(parsed, dict) and "nodes" in parsed:
104 json_data = parsed
105 break
106 except json.JSONDecodeError:
107 continue
108
109 if not json_data:
110 raise RuntimeError("Failed to parse response data")
111
112 data: list = json_data["nodes"][1]["data"]
113 keys: list[int] = data[data[0]["messages"]]
114 message_keys: dict = data[keys[0]]
115 messageId: str = data[message_keys["id"]]
116
117 except (KeyError, IndexError, TypeError) as e:
118 raise RuntimeError(f"Failed to extract message ID: {str(e)}")
119
120 settings = {
121 "inputs": format_prompt(messages),
122 "id": messageId,
123 "is_retry": False,
124 "is_continue": False,
125 "web_search": web_search,
126 "tools": []
127 }
128
129 headers = {
130 'accept': '*/*',
131 'accept-language': 'en',
132 'cache-control': 'no-cache',
133 'origin': 'https://huggingface.co',
134 'pragma': 'no-cache',
135 'priority': 'u=1, i',
136 'referer': f'https://huggingface.co/chat/conversation/{conversationId}',
137 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
138 'sec-ch-ua-mobile': '?0',
139 'sec-ch-ua-platform': '"macOS"',
140 'sec-fetch-dest': 'empty',
141 'sec-fetch-mode': 'cors',
142 'sec-fetch-site': 'same-origin',
143 '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',
144 }
145
146 data = CurlMime()
147 data.addpart('data', data=json.dumps(settings, separators=(',', ':')))
148
149 response = session.post(
150 f'https://huggingface.co/chat/conversation/{conversationId}',
151 cookies=session.cookies,
152 headers=headers,
153 multipart=data,
154 stream=True
155 )
156 raise_for_status(response)
157
158 full_response = ""
159 for line in response.iter_lines():
160 if not line:
161 continue
93 162 try:
94 json_data = None
95 for line in response.text.split('\n'):
96 if line.strip():
97 try:
98 parsed = json.loads(line)
99 if isinstance(parsed, dict) and "nodes" in parsed:
100 json_data = parsed
101 break
102 except json.JSONDecodeError:
103 continue
104
105 if not json_data:
106 raise RuntimeError("Failed to parse response data")
107
108 data: list = json_data["nodes"][1]["data"]
109 keys: list[int] = data[data[0]["messages"]]
110 message_keys: dict = data[keys[0]]
111 messageId: str = data[message_keys["id"]]
112
113 except (KeyError, IndexError, TypeError) as e:
114 raise RuntimeError(f"Failed to extract message ID: {str(e)}")
115
116 settings = {
117 "inputs": format_prompt(messages),
118 "id": messageId,
119 "is_retry": False,
120 "is_continue": False,
121 "web_search": False,
122 "tools": []
123 }
124
125 headers = {
126 'accept': '*/*',
127 'accept-language': 'en',
128 'cache-control': 'no-cache',
129 'origin': 'https://huggingface.co',
130 'pragma': 'no-cache',
131 'priority': 'u=1, i',
132 'referer': f'https://huggingface.co/chat/conversation/{conversationId}',
133 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
134 'sec-ch-ua-mobile': '?0',
135 'sec-ch-ua-platform': '"macOS"',
136 'sec-fetch-dest': 'empty',
137 'sec-fetch-mode': 'cors',
138 'sec-fetch-site': 'same-origin',
139 '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',
140 }
141
142 files = {
143 'data': (None, json.dumps(settings, separators=(',', ':'))),
144 }
145
146 response = requests.post(
147 f'https://huggingface.co/chat/conversation/{conversationId}',
148 cookies=session.cookies,
149 headers=headers,
150 files=files,
151 )
152 raise_for_status(response)
153
154 full_response = ""
155 for line in response.iter_lines():
156 if not line:
157 continue
158 try:
159 line = json.loads(line)
160 except json.JSONDecodeError as e:
161 print(f"Failed to decode JSON: {line}, error: {e}")
162 continue
163
164 if "type" not in line:
165 raise RuntimeError(f"Response: {line}")
166
167 elif line["type"] == "stream":
168 token = line["token"].replace('\u0000', '')
169 full_response += token
170 if stream:
171 yield token
172
173 elif line["type"] == "finalAnswer":
174 break
163 line = json.loads(line)
164 except json.JSONDecodeError as e:
165 print(f"Failed to decode JSON: {line}, error: {e}")
166 continue
175 167
176 full_response = full_response.replace('<|im_end|', '').replace('\u0000', '').strip()
168 if "type" not in line:
169 raise RuntimeError(f"Response: {line}")
170
171 elif line["type"] == "stream":
172 token = line["token"].replace('\u0000', '')
173 full_response += token
174 if stream:
175 yield token
176
177 elif line["type"] == "finalAnswer":
178 break
179
180 full_response = full_response.replace('<|im_end|', '').replace('\u0000', '').strip()
177 181
178 if not stream:
179 yield full_response
182 if not stream:
183 yield full_response
Modified g4f/gui/client/static/css/style.css +5 -7
@@ -92,6 +92,10 @@ body {
92 92 height: 100vh;
93 93 }
94 94
95 a:-webkit-any-link {
96 color: var(--accent);
97 }
98
95 99 .row {
96 100 display: flex;
97 101 gap: 10px;
@@ -124,7 +128,7 @@ body {
124 128
125 129 .new_version a {
126 130 color: var(--colour-4);
127 text-decoration: underline dotted;
131 text-decoration: underline;
128 132 }
129 133
130 134 .conversations {
@@ -975,11 +979,6 @@ ul {
975 979 display: flex;
976 980 }
977 981
978
979 a:-webkit-any-link {
980 color: var(--accent);
981 }
982
983 982 .conversation .user-input textarea {
984 983 font-size: 15px;
985 984 width: 100%;
@@ -1021,7 +1020,6 @@ a:-webkit-any-link {
1021 1020 background-image: url('data:image/svg+xml;utf-8,<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6 5C5.73478 5 5.48043 5.10536 5.29289 5.29289C5.10536 5.48043 5 5.73478 5 6V20C5 20.2652 5.10536 20.5196 5.29289 20.7071C5.48043 20.8946 5.73478 21 6 21H18C18.2652 21 18.5196 20.8946 18.7071 20.7071C18.8946 20.5196 19 20.2652 19 20V6C19 5.73478 18.8946 5.48043 18.7071 5.29289C18.5196 5.10536 18.2652 5 18 5H16C15.4477 5 15 4.55228 15 4C15 3.44772 15.4477 3 16 3H18C18.7956 3 19.5587 3.31607 20.1213 3.87868C20.6839 4.44129 21 5.20435 21 6V20C21 20.7957 20.6839 21.5587 20.1213 22.1213C19.5587 22.6839 18.7957 23 18 23H6C5.20435 23 4.44129 22.6839 3.87868 22.1213C3.31607 21.5587 3 20.7957 3 20V6C3 5.20435 3.31607 4.44129 3.87868 3.87868C4.44129 3.31607 5.20435 3 6 3H8C8.55228 3 9 3.44772 9 4C9 4.55228 8.55228 5 8 5H6Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7 3C7 1.89543 7.89543 1 9 1H15C16.1046 1 17 1.89543 17 3V5C17 6.10457 16.1046 7 15 7H9C7.89543 7 7 6.10457 7 5V3ZM15 3H9V5H15V3Z" fill="white"/></svg>');
1022 1021 background-repeat: no-repeat;
1023 1022 background-position: center;
1024 transition: background-color 200ms ease, transform 200ms ease-out
1025 1023 }
1026 1024
1027 1025 .hljs-copy-button:hover {
Modified g4f/gui/client/static/js/chat.v1.js +2 -28
@@ -1065,6 +1065,7 @@ async function hide_sidebar() {
1065 1065 sidebar_button.classList.remove("rotated");
1066 1066 settings.classList.add("hidden");
1067 1067 chat.classList.remove("hidden");
1068 log_storage.classList.add("hidden");
1068 1069 if (window.location.pathname == "/menu/" || window.location.pathname == "/settings/") {
1069 1070 history.back();
1070 1071 }
@@ -1182,31 +1183,6 @@ const say_hello = async () => {
1182 1183 }
1183 1184 }
1184 1185
1185 // Theme storage for recurring viewers
1186 const storeTheme = function (theme) {
1187 appStorage.setItem("theme", theme);
1188 };
1189
1190 // set theme when visitor returns
1191 const setTheme = function () {
1192 const activeTheme = appStorage.getItem("theme");
1193 colorThemes.forEach((themeOption) => {
1194 if (themeOption.id === activeTheme) {
1195 themeOption.checked = true;
1196 }
1197 });
1198 // fallback for no :has() support
1199 document.documentElement.className = activeTheme;
1200 };
1201
1202 colorThemes.forEach((themeOption) => {
1203 themeOption.addEventListener("click", () => {
1204 storeTheme(themeOption.id);
1205 // fallback for no :has() support
1206 document.documentElement.className = themeOption.id;
1207 });
1208 });
1209
1210 1186 function count_tokens(model, text) {
1211 1187 if (model) {
1212 1188 if (window.llamaTokenizer)
@@ -1273,7 +1249,6 @@ window.addEventListener('pywebviewready', async function() {
1273 1249 });
1274 1250
1275 1251 async function on_load() {
1276 setTheme();
1277 1252 count_input();
1278 1253
1279 1254 if (/\/chat\/.+/.test(window.location.href)) {
@@ -1290,8 +1265,7 @@ async function on_api() {
1290 1265 if (prompt_lock) return;
1291 1266
1292 1267 // If not mobile
1293 if (!window.matchMedia("(pointer:coarse)").matches)
1294 if (evt.keyCode === 13 && !evt.shiftKey) {
1268 if (!window.matchMedia("(pointer:coarse)").matches && evt.keyCode === 13 && !evt.shiftKey) {
1295 1269 evt.preventDefault();
1296 1270 console.log("pressed enter");
1297 1271 prompt_lock = true;