diff --git a/g4f/Provider/PollinationsAI.py b/g4f/Provider/PollinationsAI.py index 33043a5d..aea92c3d 100644 --- a/g4f/Provider/PollinationsAI.py +++ b/g4f/Provider/PollinationsAI.py @@ -3,6 +3,7 @@ from __future__ import annotations import json import random import requests +import asyncio from urllib.parse import quote_plus from typing import Optional from aiohttp import ClientSession @@ -148,6 +149,7 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin): private: bool = False, enhance: bool = False, safe: bool = False, + n: int = 1, # Text generation parameters media: MediaListType = None, temperature: float = None, @@ -187,7 +189,8 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin): nologo=nologo, private=private, enhance=enhance, - safe=safe + safe=safe, + n=n ): yield chunk else: @@ -223,12 +226,10 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin): nologo: bool, private: bool, enhance: bool, - safe: bool + safe: bool, + n: int ) -> AsyncResult: - if not cache and seed is None: - seed = random.randint(9999, 99999999) params = use_aspect_ratio({ - "seed": seed, "width": width, "height": height, "model": model, @@ -238,12 +239,27 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin): "safe": str(safe).lower() }, aspect_ratio) query = "&".join(f"{k}={quote_plus(str(v))}" for k, v in params.items() if v is not None) - prompt = quote_plus(prompt)[:8112] # Limit URL length + prompt = quote_plus(prompt)[:2048-256-len(query)] url = f"{cls.image_api_endpoint}prompt/{prompt}?{query}" + def get_image_url(i: int = 0, seed: Optional[int] = None): + if i == 0: + if not cache and seed is None: + seed = random.randint(0, 2**32) + else: + seed = random.randint(0, 2**32) + return f"{url}&seed={seed}" if seed else url async with ClientSession(headers=DEFAULT_HEADERS, connector=get_connector(proxy=proxy)) as session: - async with session.get(url, allow_redirects=False) as response: - await raise_for_status(response) - yield ImageResponse(str(response.url), prompt) + async def get_image(i: int = 0, seed: Optional[int] = None): + async with session.get(get_image_url(i, seed), allow_redirects=False) as response: + try: + await raise_for_status(response) + except Exception as e: + debug.error(f"Error fetching image: {e}") + return str(response.url) + return str(response.url) + yield ImageResponse(await asyncio.gather(*[ + get_image(i, seed) for i in range(int(n)) + ]), prompt) @classmethod async def _generate_text( diff --git a/g4f/Provider/PollinationsImage.py b/g4f/Provider/PollinationsImage.py index 3d920ac2..f0955a11 100644 --- a/g4f/Provider/PollinationsImage.py +++ b/g4f/Provider/PollinationsImage.py @@ -45,6 +45,7 @@ class PollinationsImage(PollinationsAI): private: bool = False, enhance: bool = False, safe: bool = False, + n: int = 4, **kwargs ) -> AsyncResult: # Calling model updates before creating a generator @@ -61,6 +62,7 @@ class PollinationsImage(PollinationsAI): nologo=nologo, private=private, enhance=enhance, - safe=safe + safe=safe, + n=n ): yield chunk diff --git a/g4f/gui/client/background.html b/g4f/gui/client/background.html index 6517c7d1..951ca779 100644 --- a/g4f/gui/client/background.html +++ b/g4f/gui/client/background.html @@ -28,7 +28,6 @@ .gradient { position: absolute; - z-index: -1; left: 50vw; border-radius: 50%; background: radial-gradient(circle at center, var(--accent), var(--gradient)); @@ -73,12 +72,6 @@ overflow: hidden; } - iframe { - background: transparent; - width: 100%; - border: none; - } - .hidden { display: none; } @@ -86,7 +79,6 @@ #background, #image-feed, #video-feed { height: 100%; position: absolute; - z-index: -1; object-fit: cover; object-position: center; width: 100%; @@ -100,29 +92,41 @@ -
+ diff --git a/g4f/gui/client/index.html b/g4f/gui/client/index.html index b85af2e5..30e696cd 100644 --- a/g4f/gui/client/index.html +++ b/g4f/gui/client/index.html @@ -63,7 +63,7 @@ diff --git a/g4f/gui/client/qrcode.html b/g4f/gui/client/qrcode.html index 30754771..d4abda85 100644 --- a/g4f/gui/client/qrcode.html +++ b/g4f/gui/client/qrcode.html @@ -74,15 +74,15 @@ }); document.getElementById('generateQRCode').addEventListener('click', async () => { - const chat_id = generate_uuid(); + const share_id = generate_uuid(); - const url = `${share_url}/backend-api/v2/chat/${encodeURI(chat_id)}`; + const url = `${share_url}/backend-api/v2/chat/${encodeURI(share_id)}`; const response = await fetch(url, { method: 'POST', headers: {'content-type': 'application/json'}, body: localStorage.getItem(`conversation:${conversation_id}`) }); - const share = `${share_url}/chat/${encodeURI(chat_id)}/${encodeURI(conversation_id)}`; + const share = `${share_url}/chat/${encodeURI(share_id)}/${encodeURI(conversation_id)}`; const qrcodeStatus = document.getElementById('qrcode-status'); if (response.status !== 200) { qrcodeStatus.innerText = 'Error generating QR code: ' + response.statusText; @@ -115,8 +115,8 @@ const constraints = { video: { - width: { ideal: 1280 }, - height: { ideal: 1280 }, + width: { ideal: 800 }, + height: { ideal: 800 }, facingMode: facingMode }, audio: false diff --git a/g4f/gui/client/static/js/chat.v1.js b/g4f/gui/client/static/js/chat.v1.js index e8a7cc58..6bbe0f65 100644 --- a/g4f/gui/client/static/js/chat.v1.js +++ b/g4f/gui/client/static/js/chat.v1.js @@ -298,8 +298,8 @@ const register_message_buttons = async () => { if (message_el) { if ("index" in message_el.dataset) { await remove_message(window.conversation_id, message_el.dataset.index); + chatBody.removeChild(message_el); } - message_el.remove(); } reloadConversation = true; await safe_load_conversation(window.conversation_id, false); @@ -842,7 +842,7 @@ async function add_message_chunk(message, message_id, provider, scroll, finish_m for (const [key, value] of Object.entries(message.conversation)) { conversation.data[key] = value; } - await save_conversation(conversation_id, conversation); + await save_conversation(conversation_id, get_conversation_data(conversation)); } else if (message.type == "auth") { error_storage[message_id] = message.message content_map.inner.innerHTML += markdown_render(`**An error occured:** ${message.message}`); @@ -1227,7 +1227,6 @@ function sanitize(input, replacement) { } async function set_conversation_title(conversation_id, title) { - window.chat_id = null; conversation = await get_conversation(conversation_id) conversation.new_title = title; const new_id = sanitize(title, " "); @@ -1319,7 +1318,6 @@ const set_conversation = async (conversation_id) => { const new_conversation = async () => { history.pushState({}, null, `/chat/`); - window.chat_id = null; window.conversation_id = uuid(); document.title = window.title || document.title; document.querySelector(".chat-header").innerText = "New Conversation - G4F"; @@ -1391,7 +1389,7 @@ const load_conversation = async (conversation, scroll=true) => { document.title = title; } const chatHeader = document.querySelector(".chat-header"); - if (window.chat_id) { + if (window.share_id && conversation.id == window.start_id) { chatHeader.innerHTML = ' ' + escapeHtml(title); } else { chatHeader.innerText = title; @@ -1581,16 +1579,16 @@ async function get_conversation(conversation_id) { return conversation; } -async function save_conversation(conversation_id, conversation) { +function get_conversation_data(conversation) { conversation.updated = Date.now(); - const data = JSON.stringify(conversation) + return JSON.stringify(conversation); +} + +async function save_conversation(conversation_id, data) { appStorage.setItem( `conversation:${conversation_id}`, data ); - if (conversation_id != window.start_id) { - window.chat_id = null; - } } async function get_messages(conversation_id) { @@ -1600,13 +1598,13 @@ async function get_messages(conversation_id) { async function add_conversation(conversation_id) { if (appStorage.getItem(`conversation:${conversation_id}`) == null) { - await save_conversation(conversation_id, { + await save_conversation(conversation_id, get_conversation_data({ id: conversation_id, title: "", added: Date.now(), system: chatPrompt?.value, items: [], - }); + })); } try { add_url_to_history(`/chat/${conversation_id}`); @@ -1622,7 +1620,7 @@ async function save_system_message() { const conversation = await get_conversation(window.conversation_id); if (conversation) { conversation.system = chatPrompt?.value; - await save_conversation(window.conversation_id, conversation); + await save_conversation(window.conversation_id, get_conversation_data(conversation)); } } @@ -1640,9 +1638,10 @@ const remove_message = async (conversation_id, index) => { } } conversation.items = new_items; - await save_conversation(conversation_id, conversation); - if (window.chat_id && window.conversation_id == window.start_id) { - const url = `${window.share_url}/backend-api/v2/chat/${window.chat_id}`; + const data = get_conversation_data(conversation); + await save_conversation(conversation_id, data); + if (window.share_id && window.conversation_id == window.start_id) { + const url = `${window.share_url}/backend-api/v2/chat/${window.share_id}`; await fetch(url, { method: 'POST', headers: {'content-type': 'application/json'}, @@ -1716,13 +1715,14 @@ const add_message = async ( }); conversation.items = new_messages; } - await save_conversation(conversation_id, conversation); - if (window.chat_id && conversation_id == window.start_id) { - const url = `${window.share_url}/backend-api/v2/chat/${window.chat_id}`; + data = get_conversation_data(conversation); + await save_conversation(conversation_id, data); + if (window.share_id && conversation_id == window.start_id) { + const url = `${window.share_url}/backend-api/v2/chat/${window.share_id}`; fetch(url, { method: 'POST', headers: {'content-type': 'application/json'}, - body: JSON.stringify(conversation), + body: data }); } return conversation.items.length - 1; @@ -1758,7 +1758,7 @@ const load_conversations = async () => { // appStorage.removeItem(`conversation:${conversation.id}`); // return; // } - const shareIcon = (conversation.id == window.start_id && window.chat_id) ? '': ''; + const shareIcon = (conversation.id == window.start_id && window.share_id) ? '': ''; html.push(`