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

XFEstudio/gpt4free

Add Clarity Token to Copilot, (#2482)

* Add Clarity Token to Copilot, Ignore disabled providers in gui, Read cookie files after upload * Add more chat templates to HuggingFace

a591c5d4
H Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

11 个文件 +113 -43
Modified g4f/Provider/Airforce.py +1 -4
@@ -32,8 +32,7 @@ class Airforce(AsyncGeneratorProvider, ProviderModelMixin):
32 32 api_endpoint_imagine2 = "https://api.airforce/imagine2"
33 33
34 34 working = True
35 needs_auth = True
36 supports_stream = True
35 supports_stream = False
37 36 supports_system_message = True
38 37 supports_message_history = True
39 38
@@ -41,9 +40,7 @@ class Airforce(AsyncGeneratorProvider, ProviderModelMixin):
41 40 default_image_model = "flux"
42 41
43 42 hidden_models = {"Flux-1.1-Pro"}
44
45 43 additional_models_imagine = ["flux-1.1-pro", "midjourney", "dall-e-3"]
46
47 44 model_aliases = {
48 45 # Alias mappings for models
49 46 "gpt-4": "gpt-4o",
Modified g4f/Provider/AmigoChat.py +2 -3
@@ -13,7 +13,7 @@ MODELS = {
13 13 'chat': {
14 14 'gpt-4o-2024-11-20': {'persona_id': "gpt"},
15 15 'gpt-4o': {'persona_id': "summarizer"},
16 'gpt-4o-mini': {'persona_id': "gemini-1-5-flash"},
16 'gpt-4o-mini': {'persona_id': "amigo"},
17 17
18 18 'o1-preview-': {'persona_id': "openai-o-one"}, # Amigo, your balance is not enough to make the request, wait until 12 UTC or upgrade your plan
19 19 'o1-preview-2024-09-12-': {'persona_id': "orion"}, # Amigo, your balance is not enough to make the request, wait until 12 UTC or upgrade your plan
@@ -24,7 +24,7 @@ MODELS = {
24 24 'codellama/CodeLlama-34b-Instruct-hf': {'persona_id': "codellama-CodeLlama-34b-Instruct-hf"},
25 25
26 26 'gemini-1.5-pro': {'persona_id': "gemini-1-5-pro"}, # Amigo, your balance is not enough to make the request, wait until 12 UTC or upgrade your plan
27 'gemini-1.5-flash': {'persona_id': "amigo"},
27 'gemini-1.5-flash': {'persona_id': "gemini-1.5-flash"},
28 28
29 29 'claude-3-5-sonnet-20240620': {'persona_id': "claude"},
30 30 'claude-3-5-sonnet-20241022': {'persona_id': "clude-claude-3-5-sonnet-20241022"},
@@ -200,7 +200,6 @@ class AmigoChat(AsyncGeneratorProvider, ProviderModelMixin):
200 200 "temperature": temperature,
201 201 "top_p": top_p
202 202 }
203 print(data)
204 203 async with session.post(cls.chat_api_endpoint, json=data, timeout=timeout) as response:
205 204 await raise_for_status(response)
206 205 async for line in response.iter_lines():
Modified g4f/Provider/Copilot.py +27 -1
@@ -2,6 +2,7 @@ from __future__ import annotations
2 2
3 3 import json
4 4 import asyncio
5 import base64
5 6 from http.cookiejar import CookieJar
6 7 from urllib.parse import quote
7 8
@@ -93,6 +94,20 @@ class Copilot(AbstractProvider, ProviderModelMixin):
93 94 ) as session:
94 95 if cls._access_token is not None:
95 96 cls._cookies = session.cookies.jar
97 if cls._access_token is None:
98 try:
99 url = "https://copilot.microsoft.com/cl/eus-sc/collect"
100 headers = {
101 "Accept": "application/x-clarity-gzip",
102 "referrer": "https://copilot.microsoft.com/onboarding"
103 }
104 response = session.post(url, headers=headers, data=get_clarity())
105 clarity_token = json.loads(response.text.split(" ", maxsplit=1)[-1])[0]["value"]
106 debug.log(f"Copilot: Clarity Token: ...{clarity_token[-12:]}")
107 except Exception as e:
108 debug.log(f"Copilot: {e}")
109 else:
110 clarity_token = None
96 111 response = session.get("https://copilot.microsoft.com/c/api/user")
97 112 raise_for_status(response)
98 113 user = response.json().get('firstName')
@@ -125,6 +140,12 @@ class Copilot(AbstractProvider, ProviderModelMixin):
125 140 uploaded_images.append({"type":"image", "url": response.json().get("url")})
126 141
127 142 wss = session.ws_connect(cls.websocket_url)
143 if clarity_token is not None:
144 wss.send(json.dumps({
145 "event": "challengeResponse",
146 "token": clarity_token,
147 "method":"clarity"
148 }).encode(), CurlWsFlag.TEXT)
128 149 wss.send(json.dumps({
129 150 "event": "send",
130 151 "conversationId": conversation_id,
@@ -209,4 +230,9 @@ def readHAR(url: str):
209 230 if api_key is None:
210 231 raise NoValidHarFileError("No access token found in .har files")
211 232
212 return api_key, cookies
233 return api_key, cookies
234
235 def get_clarity() -> bytes:
236 #{"e":["0.7.58",5,7284,4779,"n59ae4ieqq","aln5en","1upufhz",1,0,0],"a":[[7323,12,65,217,324],[7344,12,65,214,329],[7385,12,65,211,334],[7407,12,65,210,337],[7428,12,65,209,338],[7461,12,65,209,339],[7497,12,65,209,339],[7531,12,65,208,340],[7545,12,65,208,342],[11654,13,65,208,342],[11728,14,65,208,342],[11728,9,65,208,342,17535,19455,0,0,0,"Annehmen",null,"52w7wqv1r.8ovjfyrpu",1],[7284,4,1,393,968,393,968,0,0,231,310,939,0],[12063,0,2,147,3,4,4,18,5,1,10,79,25,15],[12063,36,6,[11938,0]]]}
237 body = base64.b64decode("H4sIAAAAAAAAA23RwU7DMAwG4HfJ2aqS2E5ibjxH1cMOnQYqYZvUTQPx7vyJRGGAemj01XWcP+9udg+j80MetDhSyrEISc5GrqrtZnmaTydHbrdUnSsWYT2u+8Obo0Ce/IQvaDBmjkwhUlKKIRNHmQgosqEArWPRDQMx90rxeUMPzB1j+UJvwNIxhTvsPcXyX1T+rizE4juK3mEEhpAUg/JvzW1/+U/tB1LATmhqotoiweMea50PLy2vui4LOY3XfD1dwnkor5fn/e18XBFgm6fHjSzZmCyV7d3aRByAEYextaTHEH3i5pgKGVP/s+DScE5PuLKIpW6FnCi1gY3Rbpqmj0/DI/+L7QEAAA==")
238 return body
Modified g4f/Provider/DDG.py +3 -5
@@ -77,9 +77,7 @@ class DDG(AsyncGeneratorProvider, ProviderModelMixin):
77 77 if conversation is None:
78 78 conversation = Conversation(model)
79 79 is_new_conversation = True
80
81 debug.last_model = model
82
80
83 81 if conversation.vqd is None:
84 82 conversation.vqd = await cls.get_vqd(proxy, connector)
85 83 if not conversation.vqd:
@@ -91,7 +89,7 @@ class DDG(AsyncGeneratorProvider, ProviderModelMixin):
91 89 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
92 90 'x-vqd-4': conversation.vqd,
93 91 }
94
92
95 93 async with ClientSession(headers=headers, connector=get_connector(connector, proxy)) as session:
96 94 if is_new_conversation:
97 95 conversation.message_history = [{"role": "user", "content": format_prompt(messages)}]
@@ -119,7 +117,7 @@ class DDG(AsyncGeneratorProvider, ProviderModelMixin):
119 117 async with session.post(cls.api_endpoint, json=data) as response:
120 118 conversation.vqd = response.headers.get("x-vqd-4")
121 119 await raise_for_status(response)
122
120
123 121 async for line in response.content:
124 122 if line:
125 123 decoded_line = line.decode('utf-8')
Modified g4f/Provider/Mhystical.py +5 -11
@@ -4,6 +4,7 @@ import json
4 4 import logging
5 5 from aiohttp import ClientSession
6 6 from ..typing import AsyncResult, Messages
7 from ..requests.raise_for_status import raise_for_status
7 8 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
8 9 from .helper import format_prompt
9 10
@@ -67,17 +68,10 @@ class Mhystical(AsyncGeneratorProvider, ProviderModelMixin):
67 68 "messages": [{"role": "user", "content": format_prompt(messages)}]
68 69 }
69 70 async with session.post(cls.api_endpoint, json=data, headers=headers, proxy=proxy) as response:
70 if response.status == 400:
71 yield "Error: API key is missing"
72 elif response.status == 429:
73 yield "Error: Rate limit exceeded"
74 elif response.status == 500:
75 yield "Error: Internal server error"
76 else:
77 response.raise_for_status()
78 response_text = await response.text()
79 filtered_response = cls.filter_response(response_text)
80 yield filtered_response
71 await raise_for_status(response)
72 response_text = await response.text()
73 filtered_response = cls.filter_response(response_text)
74 yield filtered_response
81 75
82 76 @staticmethod
83 77 def filter_response(response_text: str) -> str:
Modified g4f/Provider/needs_auth/GithubCopilot.py +0 -1
@@ -62,7 +62,6 @@ class GithubCopilot(AsyncGeneratorProvider, ProviderModelMixin):
62 62 if conversation is not None:
63 63 conversation_id = conversation.conversation_id
64 64 if conversation_id is None:
65 print(headers)
66 65 async with session.post("https://api.individual.githubcopilot.com/github/chat/threads", headers=headers) as response:
67 66 await raise_for_status(response)
68 67 conversation_id = (await response.json()).get("thread_id")
Modified g4f/Provider/needs_auth/HuggingFace.py +53 -6
@@ -3,25 +3,37 @@ from __future__ import annotations
3 3 import json
4 4 import base64
5 5 import random
6 import requests
6 7
7 8 from ...typing import AsyncResult, Messages
8 9 from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
9 from ...errors import ModelNotFoundError
10 from ...errors import ModelNotFoundError, ModelNotSupportedError
10 11 from ...requests import StreamSession, raise_for_status
11 12 from ...image import ImageResponse
12 13
13 14 from .HuggingChat import HuggingChat
14 15
15 16 class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
16 url = "https://huggingface.co/chat"
17 url = "https://huggingface.co"
17 18 working = True
18 19 supports_message_history = True
19 20 default_model = HuggingChat.default_model
20 21 default_image_model = HuggingChat.default_image_model
21 models = HuggingChat.models
22 image_models = [default_image_model]
23 22 model_aliases = HuggingChat.model_aliases
24 23
24 @classmethod
25 def get_models(cls) -> list[str]:
26 if not cls.models:
27 url = "https://huggingface.co/api/models?inference=warm&pipeline_tag=text-generation"
28 cls.models = [model["id"] for model in requests.get(url).json()]
29 cls.models.append("meta-llama/Llama-3.2-11B-Vision-Instruct")
30 cls.models.append("nvidia/Llama-3.1-Nemotron-70B-Instruct-HF")
31 if not cls.image_models:
32 url = "https://huggingface.co/api/models?pipeline_tag=text-to-image"
33 cls.image_models = [model["id"] for model in requests.get(url).json() if model["trendingScore"] >= 20]
34 cls.models.extend(cls.image_models)
35 return cls.models
36
25 37 @classmethod
26 38 async def create_async_generator(
27 39 cls,
@@ -36,7 +48,10 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
36 48 prompt: str = None,
37 49 **kwargs
38 50 ) -> AsyncResult:
39 model = cls.get_model(model)
51 try:
52 model = cls.get_model(model)
53 except ModelNotSupportedError:
54 pass
40 55 headers = {
41 56 'accept': '*/*',
42 57 'accept-language': 'en',
@@ -55,6 +70,7 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
55 70 }
56 71 if api_key is not None:
57 72 headers["Authorization"] = f"Bearer {api_key}"
73 payload = None
58 74 if model in cls.image_models:
59 75 stream = False
60 76 prompt = messages[-1]["content"] if prompt is None else prompt
@@ -66,12 +82,28 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
66 82 "temperature": temperature,
67 83 **kwargs
68 84 }
69 payload = {"inputs": format_prompt(messages), "parameters": params, "stream": stream}
70 85 async with StreamSession(
71 86 headers=headers,
72 87 proxy=proxy,
73 88 timeout=600
74 89 ) as session:
90 if payload is None:
91 async with session.get(f"https://huggingface.co/api/models/{model}") as response:
92 model_data = await response.json()
93 if "config" in model_data and "tokenizer_config" in model_data["config"] and "eos_token" in model_data["config"]["tokenizer_config"]:
94 eos_token = model_data["config"]["tokenizer_config"]["eos_token"]
95 if eos_token == "</s>":
96 inputs = format_prompt_mistral(messages)
97 elif eos_token == "<|im_end|>":
98 inputs = format_prompt_qwen(messages)
99 elif eos_token == "<|eot_id|>":
100 inputs = format_prompt_llama(messages)
101 else:
102 inputs = format_prompt(messages)
103 else:
104 inputs = format_prompt(messages)
105 payload = {"inputs": inputs, "parameters": params, "stream": stream}
106
75 107 async with session.post(f"{api_base.rstrip('/')}/models/{model}", json=payload) as response:
76 108 if response.status == 404:
77 109 raise ModelNotFoundError(f"Model is not supported: {model}")
@@ -105,3 +137,18 @@ def format_prompt(messages: Messages) -> str:
105 137 if message["role"] == "assistant"
106 138 ])
107 139 return f"{history}<s>[INST] {question} [/INST]"
140
141 def format_prompt_qwen(messages: Messages) -> str:
142 return "".join([
143 f"<|im_start|>{message['role']}\n{message['content']}\n<|im_end|>\n" for message in messages
144 ]) + "<|im_start|>assistant\n"
145
146 def format_prompt_llama(messages: Messages) -> str:
147 return "<|begin_of_text|>" + "".join([
148 f"<|start_header_id|>{message['role']}<|end_header_id|>\n\n{message['content']}\n<|eot_id|>\n" for message in messages
149 ]) + "<|start_header_id|>assistant<|end_header_id|>\\n\\n"
150
151 def format_prompt_mistral(messages: Messages) -> str:
152 return "".join([
153 f"<|{message['role']}|>\n{message['content']}'</s>\n" for message in messages
154 ]) + "<|assistant|>\n"
Modified g4f/Provider/openai/new.py +0 -1
@@ -476,7 +476,6 @@ start_time = time.time()
476 476
477 477 def get_turnstile_token(dx: str, p: str) -> str:
478 478 decoded_bytes = base64.b64decode(dx)
479 # print(decoded_bytes.decode())
480 479 return process_turnstile_token(decoded_bytes.decode(), p)
481 480
482 481
Modified g4f/api/__init__.py +11 -9
@@ -470,15 +470,17 @@ class Api:
470 470 })
471 471 def upload_cookies(files: List[UploadFile]):
472 472 response_data = []
473 for file in files:
474 try:
475 if file and file.filename.endswith(".json") or file.filename.endswith(".har"):
476 filename = os.path.basename(file.filename)
477 with open(os.path.join(get_cookies_dir(), filename), 'wb') as f:
478 shutil.copyfileobj(file.file, f)
479 response_data.append({"filename": filename})
480 finally:
481 file.file.close()
473 if not AppConfig.ignore_cookie_files:
474 for file in files:
475 try:
476 if file and file.filename.endswith(".json") or file.filename.endswith(".har"):
477 filename = os.path.basename(file.filename)
478 with open(os.path.join(get_cookies_dir(), filename), 'wb') as f:
479 shutil.copyfileobj(file.file, f)
480 response_data.append({"filename": filename})
481 finally:
482 file.file.close()
483 read_cookie_files()
482 484 return response_data
483 485
484 486 @self.app.get("/v1/synthesize/{provider}", responses={
Modified g4f/gui/client/static/js/chat.v1.js +8 -2
@@ -610,6 +610,7 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi
610 610 const auto_continue = document.getElementById("auto_continue")?.checked;
611 611 const download_images = document.getElementById("download_images")?.checked;
612 612 let api_key = get_api_key_by_provider(provider);
613 const ignored = Array.from(settings.querySelectorAll("input.provider:not(:checked)")).map((el)=>el.value);
613 614 await api("conversation", {
614 615 id: message_id,
615 616 conversation_id: window.conversation_id,
@@ -620,6 +621,7 @@ const ask_gpt = async (message_id, message_index = -1, regenerate = false, provi
620 621 auto_continue: auto_continue,
621 622 download_images: download_images,
622 623 api_key: api_key,
624 ignored: ignored,
623 625 }, files, message_id);
624 626 if (!error_storage[message_id]) {
625 627 html = markdown_render(message_storage[message_id]);
@@ -1217,6 +1219,7 @@ function count_tokens(model, text) {
1217 1219 if (window.GPTTokenizer_cl100k_base) {
1218 1220 return GPTTokenizer_cl100k_base.encode(text).length;
1219 1221 }
1222 return 0;
1220 1223 }
1221 1224
1222 1225 function count_words(text) {
@@ -1256,6 +1259,10 @@ systemPrompt.addEventListener("input", function() {
1256 1259 });
1257 1260
1258 1261 window.addEventListener('load', async function() {
1262 await safe_load_conversation(window.conversation_id, false);
1263 });
1264
1265 window.addEventListener('DOMContentLoaded', async function() {
1259 1266 await on_load();
1260 1267 if (window.conversation_id == "{{chat_id}}") {
1261 1268 window.conversation_id = uuid();
@@ -1309,7 +1316,6 @@ async function on_api() {
1309 1316 let prompt_lock = false;
1310 1317 messageInput.addEventListener("keydown", async (evt) => {
1311 1318 if (prompt_lock) return;
1312
1313 1319 // If not mobile and not shift enter
1314 1320 if (!window.matchMedia("(pointer:coarse)").matches && evt.keyCode === 13 && !evt.shiftKey) {
1315 1321 evt.preventDefault();
@@ -1361,7 +1367,7 @@ async function on_api() {
1361 1367 option.innerHTML = `
1362 1368 <div class="field">
1363 1369 <span class="label">Enable ${provider.label}</span>
1364 <input id="Provider${provider.name}" type="checkbox" name="Provider${provider.name}" checked="">
1370 <input id="Provider${provider.name}" type="checkbox" name="Provider${provider.name}" value="${provider.name}" class="provider" checked="">
1365 1371 <label for="Provider${provider.name}" class="toogle" title="Remove provider from dropdown"></label>
1366 1372 </div>`;
1367 1373 option.querySelector("input").addEventListener("change", (event) => load_provider_option(event.target, provider.name));
Modified g4f/gui/server/api.py +3 -0
@@ -106,6 +106,9 @@ class Api:
106 106 if provider in conversations and conversation_id in conversations[provider]:
107 107 kwargs["conversation"] = conversations[provider][conversation_id]
108 108
109 if json_data.get("ignored"):
110 kwargs["ignored"] = json_data["ignored"]
111
109 112 return {
110 113 "model": model,
111 114 "provider": provider,