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

XFEstudio/gpt4free

Remove Video and WeWordle provider

23fe8664
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

7 个文件 +81 -308
Deleted g4f/Provider/WeWordle.py +0 -82
@@ -1,82 +0,0 @@
1 from __future__ import annotations
2
3 import json
4 from typing import Any
5
6 from ..typing import AsyncResult, Messages
7 from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
8 from .helper import format_prompt
9 from ..requests import StreamSession
10 from ..providers.response import Reasoning
11
12 class WeWordle(AsyncGeneratorProvider, ProviderModelMixin):
13 label = "WeWordle"
14 url = "https://chat-gpt.com"
15 api_endpoint = "https://llmproxy.org/api/chat.php"
16
17 working = True
18 needs_auth = False
19 supports_stream = True
20 supports_system_message = True
21 supports_message_history = True
22
23 default_model = 'v3'
24 models = [default_model, 'gpt-4', 'gpt-4o', 'gpt-4o-mini', 'deepseek', 'deepseek-reasoner', 'deepseek-r1']
25
26 model_aliases = {
27 "deepseek": "v3",
28 "deepseek-reasoner": "v3",
29 "deepseek-r1": "v3"
30 }
31
32 @classmethod
33 async def create_async_generator(
34 cls,
35 model: str,
36 messages: Messages,
37 proxy: str | None = None,
38 **kwargs: Any
39 ) -> AsyncResult:
40 headers = {
41 "accept": "*/*",
42 "accept-language": "en-US,en;q=0.9",
43 "cache-control": "no-cache",
44 "content-type": "application/json",
45 "origin": "https://chat-gpt.com",
46 "referer": "https://chat-gpt.com/"
47 }
48
49 web_search = kwargs.get("web_search", False)
50
51 data_payload = {
52 "messages": messages,
53 "model": cls.get_model(model),
54 "cost": 1,
55 "stream": True,
56 "web_search": web_search
57 }
58
59 async with StreamSession(headers=headers, impersonate="chrome") as session:
60 async with session.post(cls.api_endpoint, json=data_payload, proxy=proxy) as response:
61 response.raise_for_status()
62
63 async for chunk in response.iter_lines():
64 if not chunk:
65 continue
66 chunk = chunk.decode("utf-8")
67 if chunk.startswith("data: "):
68 chunk = chunk[6:]
69 if chunk == "[DONE]":
70 break
71 try:
72 json_data = json.loads(chunk)
73 if "choices" in json_data and isinstance(json_data["choices"], list) and json_data["choices"]:
74 delta = json_data["choices"][0].get("delta", {})
75
76 if "reasoning" in delta and delta["reasoning"]:
77 yield Reasoning(status=delta["reasoning"])
78
79 if "content" in delta and delta["content"]:
80 yield delta["content"]
81 except json.JSONDecodeError:
82 pass
Modified g4f/Provider/__init__.py +0 -6
@@ -158,10 +158,6 @@ def _resolve_provider(name: str) -> ProviderType:
158 158 from g4f.Provider.needs_auth.ThebApi import ThebApi; return ThebApi
159 159 elif name == "Together":
160 160 from g4f.Provider.needs_auth.Together import Together; return Together
161 elif name == "Video":
162 from g4f.Provider.needs_auth.Video import Video; return Video
163 elif name == "WeWordle":
164 from g4f.Provider.WeWordle import WeWordle; return WeWordle
165 161 elif name == "WhiteRabbitNeo":
166 162 from g4f.Provider.needs_auth.WhiteRabbitNeo import WhiteRabbitNeo; return WhiteRabbitNeo
167 163 elif name == "You":
@@ -254,8 +250,6 @@ _provider_names = [
254 250 "TeachAnything",
255 251 "ThebApi",
256 252 "Together",
257 "Video",
258 "WeWordle",
259 253 "WhiteRabbitNeo",
260 254 "You",
261 255 "YouTube",
Modified g4f/Provider/needs_auth/Video.py +78 -209
@@ -1,259 +1,128 @@
1 1 from __future__ import annotations
2 2
3 import os
4 import asyncio
3 import json
5 4 from typing import Optional
6 5 from aiohttp import ClientSession, ClientTimeout
7
8 from urllib.parse import quote, quote_plus
9 from aiohttp import ClientSession
10
11 try:
12 import zendriver as nodriver
13 from zendriver.core.connection import ProtocolException
14 has_nodriver = True
15 except Exception:
16 has_nodriver = False
6 from urllib.parse import quote
7 from urllib.parse import quote
17 8
18 9 from ...typing import Messages, AsyncResult
19 from ...providers.response import VideoResponse, Reasoning, ContinueResponse, ProviderInfo
20 from ...requests import get_nodriver
10 from ...providers.response import VideoResponse, Reasoning, ProviderInfo
21 11 from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
22 12 from ..helper import format_media_prompt
23 13 from ... import debug
24 14
25 PUBLIC_URL = "https://g4f.space"
26 SEARCH_URL = f"{PUBLIC_URL}/search/video+"
15 FLIM_SEARCH_URL = "https://api.flim.ai/2.0.0/search"
16 TRANSLATE_URL = "https://g4f.space/ai/auto/Translate%20the%20given%20prompt%20into%20English%20and%20reply%20with%20only%20the%20translated%20text%E2%80%94no%20explanations,%20introductions,%20or%20additional%20content:%20{prompt}"
17 FLIM_HEADERS = {
18 "accept": "application/json",
19 "content-type": "application/json",
20 "origin": "https://app.flim.ai",
21 "referer": "https://app.flim.ai/",
22 "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
23 }
27 24
28 25 class RequestConfig:
29 26 urls: dict[str, list[str]] = {}
30 headers: dict = {}
31 27
32 28 @classmethod
33 29 async def get_response(cls, prompt: str, search: bool = False) -> Optional[VideoResponse]:
34 30 if prompt in cls.urls and cls.urls[prompt]:
35 31 unique_list = list(set(cls.urls[prompt]))[:10]
36 return VideoResponse(unique_list, prompt, {
37 "headers": {"authorization": cls.headers.get("authorization")} if cls.headers.get("authorization") else {},
38 })
32 return VideoResponse(unique_list, prompt)
39 33 if search:
34 found_urls = await cls.search_flim(prompt)
35 if found_urls:
36 return VideoResponse(found_urls, prompt)
37
38 @classmethod
39 async def translate_prompt(cls, prompt: str) -> str:
40 """Translate the prompt into English via the g4f.space auto endpoint."""
41 try:
42 url = TRANSLATE_URL.format(prompt=quote(prompt, safe=""))
40 43 async with ClientSession() as session:
41 found_urls = []
42 for skip in range(0, 9):
43 try:
44 async with session.get(SEARCH_URL + quote_plus(prompt) + f"?skip={skip}", timeout=ClientTimeout(total=10)) as response:
45 if response.ok:
46 found_urls.append(str(response.url))
47 else:
48 break
49 except Exception as e:
50 debug.error(f"Error fetching video URLs:", e)
51 break
52 if found_urls:
53 return VideoResponse(found_urls, prompt)
44 async with session.get(url, timeout=ClientTimeout(total=15)) as response:
45 if not response.ok:
46 debug.error(f"Translate prompt failed: {response.status}")
47 return prompt
48 text = (await response.text()).strip()
49 return text[:100] if text else prompt
50 except Exception as e:
51 debug.error(f"Error translating prompt:", e)
52 return prompt
53
54 @classmethod
55 async def search_flim(cls, prompt: str) -> list[str]:
56 payload = {
57 "search": {
58 "saved_images": False, "full_text": prompt,
59 "similar_picture_id": "", "movie_id": "", "dop": "", "director": "",
60 "brand": "", "agency": "", "production_company": "", "actor": "",
61 "creator": "", "artist": "", "collection_id": "", "board_id": "",
62 "filters": {
63 "genres": [], "colors": [], "number_of_persons": [], "years": [],
64 "shot_types": [], "movie_types": [], "aspect_ratio": [],
65 "safety_content": [], "has_video_cuts": True, "camera_motions": []
66 },
67 "negative_filters": {
68 "aspect_ratio": [], "genres": ["ANIMATION"], "movie_types": [],
69 "colors": [], "shot_types": [], "number_of_persons": [],
70 "years": [], "safety_content": ["nudity", "violence"]
71 }
72 },
73 "page": 0, "sort_by": "", "order_by": "", "number_per_pages": 100
74 }
75 urls = []
76 try:
77 async with ClientSession(headers=FLIM_HEADERS) as session:
78 async with session.post(FLIM_SEARCH_URL, json=payload, timeout=ClientTimeout(total=15)) as response:
79 if not response.ok:
80 debug.error(f"Flim search failed: {response.status}")
81 return urls
82 data = await response.json()
83 for img in data.get("query_response", {}).get("images", []):
84 if img.get("has_video_urls"):
85 video_urls = img.get("video_urls", {})
86 url = video_urls.get("url_thumbnail") or video_urls.get("url")
87 if url and url not in urls:
88 urls.append(url)
89 except Exception as e:
90 debug.error(f"Error fetching flim video URLs:", e)
91 return urls[:10]
54 92
55 93 class Video(AsyncGeneratorProvider, ProviderModelMixin):
56 94 urls = {
57 "search": "https://sora.chatgpt.com/explore?query={0}",
58 "sora": "https://sora.chatgpt.com/explore",
59 #"veo": "https://aistudio.google.com/generate-video"
95 "search": "https://app.flim.ai/?ft={0}",
60 96 }
61 api_path = f"?provider=Video&cache=true&prompt="
62 drive_url = "https://www.googleapis.com/drive/v3/"
63 97
64 98 active_by_default = True
65 99 default_model = "search"
66 100 models = list(urls.keys())
67 101 video_models = models
68 102
69 needs_auth = True
70 working = has_nodriver
71
72 browser = None
73 stop_browser = None
74 share_url: Optional[str] = None
103 needs_auth = False
104 working = True
75 105
76 106 @classmethod
77 107 async def create_async_generator(
78 108 cls,
79 109 model: str,
80 110 messages: Messages,
81 proxy: str = None,
82 111 prompt: str = None,
83 aspect_ratio: str = None,
84 112 **kwargs
85 113 ) -> AsyncResult:
86 if cls.share_url is None:
87 cls.share_url = os.getenv("G4F_SHARE_URL")
88 114 if not model:
89 115 model = cls.default_model
90 116 if model not in cls.video_models:
91 117 raise ValueError(f"Model '{model}' is not supported by {cls.__name__}. Supported models: {cls.models}")
92 yield ProviderInfo(**cls.get_dict(), model="sora")
118 yield ProviderInfo(**cls.get_dict(), model=model)
93 119 prompt = format_media_prompt(messages, prompt).encode()[:100].decode("utf-8", "ignore").strip()
94 120 if not prompt:
95 121 raise ValueError("Prompt cannot be empty.")
96 response = await RequestConfig.get_response(prompt, model=="search")
122 prompt = await RequestConfig.translate_prompt(prompt)
123 response = await RequestConfig.get_response(prompt, model == "search")
97 124 if response:
98 125 yield Reasoning(label=f"Found {len(response.urls)} Video(s)", status="")
99 126 yield response
100 127 return
101 try:
102 yield Reasoning(label="Open browser")
103 browser, stop_browser = await get_nodriver(proxy=proxy)
104 except Exception as e:
105 if cls.share_url is None:
106 raise
107 debug.error(f"Error getting nodriver:", e)
108 async with ClientSession() as session:
109 yield Reasoning(label="Generating")
110 async with session.get(f"{cls.share_url}{cls.api_path + quote(prompt)}") as response:
111 if not response.ok:
112 debug.error(f"Failed to generate Video: {response.status}")
113 else:
114 yield Reasoning(label="Finished", status="")
115 if response.headers.get("content-type", "text/plain").startswith("text/plain"):
116 data = (await response.text()).split("\n")
117 yield VideoResponse([f"{PUBLIC_URL}{url}" if url.startswith("/") else url for url in data], prompt)
118 return
119 yield VideoResponse(str(response.url), prompt)
120 return
121 raise
122 page = None
123 try:
124 yield ContinueResponse("Timeout waiting for Video URL")
125 page = await browser.get(cls.urls[model].format(quote(prompt)))
126 except Exception as e:
127 await stop_browser()
128 debug.error(f"Error opening page:", e)
129 if prompt not in RequestConfig.urls:
130 RequestConfig.urls[prompt] = []
131 def on_request(event: nodriver.cdp.network.RequestWillBeSent, page=None):
132 if not hasattr(event, "request"):
133 return
134 if event.request.url.startswith(cls.drive_url) or ".mp4" in event.request.url:
135 RequestConfig.headers = {}
136 for key, value in event.request.headers.items():
137 RequestConfig.headers[key.lower()] = value
138 for urls in RequestConfig.urls.values():
139 if event.request.url in urls:
140 return
141 debug.log(f"Adding URL: {event.request.url}")
142 RequestConfig.urls[prompt].append(event.request.url)
143 if not page:
144 raise RuntimeError("Failed to open page.")
145 for idx in range(300):
146 button = await page.find("User menu")
147 if button:
148 break
149 if idx == 299:
150 await stop_browser()
151 raise RuntimeError("Failed to wait for user menu.")
152 if model == "search" and page is not None:
153 await page.send(nodriver.cdp.network.enable())
154 page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request)
155 for _ in range(5):
156 await page.scroll_down(5)
157 await asyncio.sleep(1)
158 response = await RequestConfig.get_response(prompt, True)
159 if response:
160 await stop_browser()
161 yield Reasoning(label="Found", status="")
162 yield response
163 return
164 if page is None:
165 raise RuntimeError("Failed to open page or get response.")
166 try:
167 await asyncio.sleep(3)
168 await page.select("textarea", 240)
169 try:
170 button = await page.find("Image")
171 if button:
172 await button.click()
173 else:
174 debug.error("No 'Image' button found.")
175 button = await page.find("Video")
176 if button:
177 await button.click()
178 yield Reasoning(label=f"Clicked 'Video' button")
179 else:
180 debug.error("No 'Video' button found.")
181 except Exception as e:
182 debug.error(f"Error clicking button:", e)
183 try:
184 if aspect_ratio:
185 button = await page.find(":")
186 if button:
187 await button.click()
188 else:
189 debug.error("No 'x:x' button found.")
190 await asyncio.sleep(1)
191 button = await page.find(aspect_ratio)
192 if button:
193 await button.click()
194 yield Reasoning(label=f"Clicked '{aspect_ratio}' button")
195 else:
196 debug.error(f"No '{aspect_ratio}' button found.")
197 except Exception as e:
198 debug.error(f"Error clicking button:", e)
199 debug.log(f"Using prompt: {prompt}")
200 textarea = await page.select("textarea", 180)
201 await textarea.click()
202 await textarea.clear_input()
203 await textarea.send_keys(prompt)
204 await asyncio.sleep(1)
205 yield Reasoning(label=f"Sending prompt", token=prompt)
206 try:
207 button = await page.select('button[type="submit"]', 5)
208 if button:
209 await button.click()
210 except Exception as e:
211 debug.error(f"Error clicking submit button:", e)
212 try:
213 button = await page.find("Create video")
214 if button:
215 await button.click()
216 yield Reasoning(label=f"Clicked 'Create video' button")
217 except Exception as e:
218 debug.error(f"Error clicking 'Create video' button:", e)
219 try:
220 button = await page.find("Activity")
221 if button:
222 await button.click()
223 yield Reasoning(label=f"Clicked 'Activity' button")
224 except Exception as e:
225 debug.error(f"Error clicking 'Activity' button:", e)
226 for idx in range(60):
227 await asyncio.sleep(1)
228 try:
229 button = await page.find("New Video")
230 if button:
231 await button.click()
232 yield Reasoning(label=f"Clicked 'New Video' button")
233 break
234 except ProtocolException as e:
235 if idx == 59:
236 debug.error(e)
237 if idx == 59:
238 await stop_browser()
239 raise RuntimeError("Failed to click 'New Video' button")
240 await asyncio.sleep(3)
241 if model != "search" and page is not None:
242 await page.send(nodriver.cdp.network.enable())
243 page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request)
244 for idx in range(300):
245 yield Reasoning(label="Waiting for Video...", status=f"{idx+1}/300")
246 await asyncio.sleep(1)
247 if RequestConfig.urls[prompt]:
248 await asyncio.sleep(2)
249 response = await RequestConfig.get_response(prompt, model=="search")
250 if response:
251 await stop_browser()
252 yield Reasoning(label="Finished", status="")
253 yield response
254 return
255 if idx == 299:
256 await stop_browser()
257 raise RuntimeError("Failed to get Video URL")
258 finally:
259 await stop_browser()
128 raise RuntimeError("Failed to find any videos for the prompt.")
Modified g4f/Provider/needs_auth/__init__.py +0 -1
@@ -41,6 +41,5 @@ from .Replicate import Replicate
41 41 from .ThebApi import ThebApi
42 42 from .WhiteRabbitNeo import WhiteRabbitNeo
43 43 from .Together import Together
44 from .Video import Video
45 44 from .xAI import xAI
46 45 from .You import You
Modified g4f/models.py +1 -2
@@ -116,7 +116,6 @@ default = Model(
116 116 "Pollinations",
117 117 "Qwen",
118 118 "Together",
119 "WeWordle",
120 119 "TeachAnything",
121 120 "OpenaiChat",
122 121 ])
@@ -142,7 +141,7 @@ default_vision = VisionModel(
142 141 gpt_4 = Model(
143 142 name = 'gpt-4',
144 143 base_provider = 'OpenAI',
145 best_provider = IterListProvider(["CopilotApp", "Yqcloud", "WeWordle", "OpenaiChat"])
144 best_provider = IterListProvider(["CopilotApp", "Yqcloud", "OpenaiChat"])
146 145 )
147 146
148 147 # gpt-4o
Modified g4f/providers/any_model_map.py +0 -6
@@ -14,12 +14,10 @@ model_map = {
14 14 "GLM": "",
15 15 "Pollinations": "",
16 16 "TeachAnything": "",
17 "WeWordle": ""
18 17 },
19 18 "gpt-4": {
20 19 "CopilotApp": "chat",
21 20 "Yqcloud": "gpt-4",
22 "WeWordle": "gpt-4",
23 21 "OpenaiChat": "gpt-4",
24 22 "Airforce": "gpt-4",
25 23 "Copilot": "Copilot",
@@ -38,7 +36,6 @@ model_map = {
38 36 "GithubCopilot": "gpt-4o",
39 37 "OpenRouter": "openai/gpt-4o-2024-05-13",
40 38 "Puter": "openrouter:openai/gpt-4o-2024-11-20",
41 "WeWordle": "gpt-4o"
42 39 },
43 40 "gpt-4o-mini": {
44 41 "OpenaiChat": "gpt-4o-mini",
@@ -46,7 +43,6 @@ model_map = {
46 43 "GithubCopilot": "gpt-4o-mini",
47 44 "OpenRouter": "openai/gpt-4o-mini-2024-07-18",
48 45 "Puter": "openrouter:openai/gpt-4o-mini-2024-07-18",
49 "WeWordle": "gpt-4o-mini"
50 46 },
51 47 "gpt-4o-mini-tts": {
52 48 "OpenAIFM": "coral",
@@ -422,7 +418,6 @@ model_map = {
422 418 "openrouter:deepseek/deepseek-r1:free",
423 419 "openrouter:deepseek/deepseek-r1"
424 420 ],
425 "WeWordle": "v3"
426 421 },
427 422 "deepseek-r1-distill-llama-70b": {
428 423 "Together": "deepseek-r1-distill-llama-70b",
@@ -1171,7 +1166,6 @@ model_map = {
1171 1166 "HuggingChat": "deepseek-ai/DeepSeek-V3",
1172 1167 "PhindAi": "deepseek",
1173 1168 "Pollinations": "deepseek",
1174 "WeWordle": "v3"
1175 1169 },
1176 1170 "glm-4.5": {
1177 1171 "HuggingFace": "zai-org/GLM-4.5",
Modified g4f/tools/run_tools.py +2 -2
@@ -414,10 +414,10 @@ async def async_iter_run_tools(
414 414 usage_dict["saved_tokens"] = saved_tokens
415 415 prompt_tokens += saved_tokens
416 416 saved_percent = round(saved_tokens / prompt_tokens * 100) if prompt_tokens > 0 and saved_tokens > 0 else 0
417 debug.log(f"Token savings:", (f"{int(saved_tokens/1000)}k" if saved_tokens >= 1000 else str(saved_tokens)) + f"/{prompt_tokens} tokens ({saved_percent}%)")
417 debug.log(f"Saved tokens:", (f"{int(saved_tokens/1000)}k" if saved_tokens >= 1000 else str(saved_tokens)) + f"/{prompt_tokens} tokens ({saved_percent}%)")
418 418 cached_tokens = usage_dict.get("prompt_tokens_details", usage_dict).get("cached_tokens", 0)
419 419 if cached_tokens > 0:
420 debug.log(f"Cached tokens:", (f"{int(cached_tokens/1000)}k" if cached_tokens >= 1000 else str(cached_tokens)) + f"/{usage_dict.get('prompt_tokens', 0)} tokens ({round(cached_tokens / usage_dict.get('prompt_tokens', 1) * 100)}%)")
420 debug.log(f"Cached tokens:", (f"{int(cached_tokens/1000)}k" if cached_tokens >= 1000 else str(cached_tokens)) + f"/{prompt_tokens} tokens ({round(cached_tokens / prompt_tokens * 100)}%)")
421 421 usage = usage_dict
422 422 usage_dir = Path(get_cookies_dir()) / ".usage"
423 423 usage_file = usage_dir / f"{datetime.date.today()}.jsonl"