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

XFEstudio/gpt4free

Refactor PollinationsAI: simplify prompt encoding and improve whitespace handling; update Gemini imports and response handling; enhance usage tracking in run_tools

97a85d6b
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

3 个文件 +45 -29
Modified g4f/Provider/PollinationsAI.py +1 -1
@@ -334,7 +334,7 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
334 334 **params
335 335 }, "1:1" if aspect_ratio is None else aspect_ratio)
336 336 query = "&".join(f"{k}={quote(str(v))}" for k, v in params.items() if v is not None)
337 encoded_prompt = prompt.strip(". \n?")
337 encoded_prompt = prompt.strip()
338 338 if model == "gptimage" and aspect_ratio is not None:
339 339 encoded_prompt = f"{encoded_prompt} aspect-ratio: {aspect_ratio}"
340 340 encoded_prompt = quote_plus(encoded_prompt)[:4096 - len(cls.image_api_endpoint) - len(query) - 8].rstrip("%")
Modified g4f/Provider/needs_auth/Gemini.py +33 -20
@@ -20,12 +20,12 @@ except ImportError:
20 20
21 21 from ... import debug
22 22 from ...typing import Messages, Cookies, MediaListType, AsyncResult, AsyncIterator
23 from ...providers.response import JsonConversation, Reasoning, RequestLogin, ImageResponse, YouTubeResponse, AudioResponse, TitleGeneration
23 from ...providers.response import JsonConversation, Reasoning, RequestLogin, ImageResponse, YouTubeResponse, AudioResponse, TitleGeneration, JsonResponse
24 24 from ...requests.raise_for_status import raise_for_status
25 25 from ...requests.aiohttp import get_connector
26 26 from ...requests import get_nodriver
27 27 from ...image.copy_images import get_filename, get_media_dir, ensure_media_dir
28 from ...errors import MissingAuthError, ModelNotFoundError
28 from ...errors import MissingAuthError
29 29 from ...image import to_bytes
30 30 from ...cookies import get_cookies_dir
31 31 from ...tools.media import merge_media
@@ -83,6 +83,7 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
83 83
84 84 needs_auth = True
85 85 working = True
86 active_by_default = True
86 87 use_nodriver = True
87 88
88 89 default_model = ""
@@ -244,12 +245,14 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
244 245 continue
245 246 if not isinstance(line, list):
246 247 continue
247 if len(line[0]) < 3 or not line[0][2]:
248 yield JsonResponse(data=line, model=model)
249 if not line or len(line[0]) < 3 or not line[0][2]:
248 250 continue
249 251 response_part = json.loads(line[0][2])
250 if response_part[10]:
252 yield JsonResponse(data=response_part, model=model)
253 if len(response_part) > 11 and response_part[10]:
251 254 yield TitleGeneration(response_part[10][0].strip())
252 if not response_part[4]:
255 if len(response_part) < 5:
253 256 continue
254 257 if return_conversation:
255 258 yield Conversation(response_part[1][0], response_part[1][1], response_part[4][0][0], model)
@@ -270,20 +273,23 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
270 273 skip -= 1
271 274 continue
272 275 yield item
273 reasoning = "\n\n".join(find_str(response_part[4][0], 3))
274 reasoning = re.sub(r"<b>|</b>", "**", reasoning)
275 def replace_image(match):
276 return f"![](https:{match.group(0)})"
277 reasoning = re.sub(r"//yt3.(?:ggpht.com|googleusercontent.com/ytc)/[\w=-]+", replace_image, reasoning)
278 reasoning = re.sub(r"\nyoutube\n", "\n\n\n", reasoning)
279 reasoning = re.sub(r"\nyoutube_tool\n", "\n\n", reasoning)
280 reasoning = re.sub(r"\nYouTube\n", "\nYouTube ", reasoning)
281 reasoning = reasoning.replace('\nhttps://www.gstatic.com/images/branding/productlogos/youtube/v9/192px.svg', '<i class="fa-brands fa-youtube"></i>')
282 youtube_ids = list(find_youtube_ids(reasoning))
283 content = response_part[4][0][1][0]
284 if reasoning:
285 yield Reasoning(reasoning, status="🤔")
276 if response_part[4]:
277 reasoning = "\n\n".join(find_str(response_part[4][0], 3))
278 reasoning = re.sub(r"<b>|</b>", "**", reasoning)
279 def replace_image(match):
280 return f"![](https:{match.group(0)})"
281 reasoning = re.sub(r"//yt3.(?:ggpht.com|googleusercontent.com/ytc)/[\w=-]+", replace_image, reasoning)
282 reasoning = re.sub(r"\nyoutube\n", "\n\n\n", reasoning)
283 reasoning = re.sub(r"\nyoutube_tool\n", "\n\n", reasoning)
284 reasoning = re.sub(r"\nYouTube\n", "\nYouTube ", reasoning)
285 reasoning = reasoning.replace('\nhttps://www.gstatic.com/images/branding/productlogos/youtube/v9/192px.svg', '<i class="fa-brands fa-youtube"></i>')
286 youtube_ids = list(find_youtube_ids(reasoning))
287 content = response_part[4][0][1][0]
288 if reasoning:
289 yield Reasoning(reasoning, status="🤔")
286 290 except (ValueError, KeyError, TypeError, IndexError) as e:
291 if kwargs.get("debug_mode", False):
292 raise e
287 293 debug.error(f"{cls.__name__} {type(e).__name__}: {e}")
288 294 continue
289 295 match = re.search(r'\[Imagen of (.*?)\]', content)
@@ -413,15 +419,22 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
413 419
414 420 @classmethod
415 421 async def fetch_snlm0e(cls, session: ClientSession, cookies: Cookies):
422 response_text = ""
416 423 async with session.get(cls.url, cookies=cookies) as response:
417 await raise_for_status(response)
418 response_text = await response.text()
424 if response.ok:
425 response_text = await response.text()
419 426 match = re.search(r'SNlM0e\":\"(.*?)\"', response_text)
420 427 if match:
421 428 cls._snlm0e = match.group(1)
422 429 sid_match = re.search(r'"FdrFJe":"([\d-]+)"', response_text)
423 430 if sid_match:
424 431 cls._sid = sid_match.group(1)
432 cls.active_by_default = True
433 cls.live += 1
434 else:
435 cls.active_by_default = False
436 cls.live = 0
437 await raise_for_status(response)
425 438
426 439 class Conversation(JsonConversation):
427 440 def __init__(self,
Modified g4f/tools/run_tools.py +11 -8
@@ -257,16 +257,19 @@ async def async_iter_run_tools(
257 257 elif isinstance(chunk, Usage):
258 258 usage = chunk
259 259 yield chunk
260 if usage is None:
261 usage = get_usage(messages, completion_tokens)
262 yield usage
263 usage = {"user": kwargs.get("user"), "model": usage_model, "provider": usage_provider, **usage.get_dict()}
264 usage_dir = Path(get_cookies_dir()) / ".usage"
265 usage_file = usage_dir / f"{datetime.date.today()}.jsonl"
266 usage_dir.mkdir(parents=True, exist_ok=True)
260 267 if has_aiofile:
261 if usage is None:
262 usage = get_usage(messages, completion_tokens)
263 yield usage
264 usage = {"user": kwargs.get("user"), "model": usage_model, "provider": usage_provider, **usage.get_dict()}
265 usage_dir = Path(get_cookies_dir()) / ".usage"
266 usage_file = usage_dir / f"{datetime.date.today()}.jsonl"
267 usage_dir.mkdir(parents=True, exist_ok=True)
268 268 async with async_open(usage_file, "a") as f:
269 await f.write(f"{json.dumps(usage)}\n")
269 asyncio.create_task(f.write(f"{json.dumps(usage)}\n"))
270 else:
271 with usage_file.open("a") as f:
272 f.write(f"{json.dumps(usage)}\n")
270 273 if completion_tokens > 0:
271 274 provider.live += 1
272 275 except: