diff --git a/g4f/Provider/Jmuz.py b/g4f/Provider/Jmuz.py
index 0615310e..95ea2b89 100644
--- a/g4f/Provider/Jmuz.py
+++ b/g4f/Provider/Jmuz.py
@@ -5,6 +5,7 @@ from .needs_auth.OpenaiAPI import OpenaiAPI
class Jmuz(OpenaiAPI):
label = "Jmuz"
+ login_url = None
api_base = "https://jmuz.me/gpt/api/v2"
api_key = "prod"
@@ -33,6 +34,8 @@ class Jmuz(OpenaiAPI):
model: str,
messages: Messages,
stream: bool = False,
+ aoi_key: str = None,
+ api_base: str = None,
**kwargs
) -> AsyncResult:
model = cls.get_model(model)
diff --git a/g4f/Provider/PollinationsAI.py b/g4f/Provider/PollinationsAI.py
index 4990a869..d4b46ea0 100644
--- a/g4f/Provider/PollinationsAI.py
+++ b/g4f/Provider/PollinationsAI.py
@@ -170,13 +170,13 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
params = {k: v for k, v in params.items() if v is not None}
async with ClientSession(headers=headers) as session:
- prompt = quote(messages[-1]["content"] if prompt is None else prompt)
+ prompt = messages[-1]["content"] if prompt is None else prompt
param_string = "&".join(f"{k}={v}" for k, v in params.items())
- url = f"{cls.image_api_endpoint}/prompt/{prompt}?{param_string}"
+ url = f"{cls.image_api_endpoint}/prompt/{quote(prompt)}?{param_string}"
async with session.head(url, proxy=proxy) as response:
if response.status == 200:
- image_response = ImageResponse(images=url, alt=messages[-1]["content"] if prompt is None else prompt)
+ image_response = ImageResponse(images=url, alt=prompt)
yield image_response
@classmethod
@@ -225,4 +225,4 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
content = json_response['choices'][0]['message']['content']
yield content
except json.JSONDecodeError:
- yield decoded_chunk
+ pass
diff --git a/g4f/Provider/hf_space/Qwen_QVQ_72B.py b/g4f/Provider/hf_space/Qwen_QVQ_72B.py
new file mode 100644
index 00000000..853b9770
--- /dev/null
+++ b/g4f/Provider/hf_space/Qwen_QVQ_72B.py
@@ -0,0 +1,70 @@
+from __future__ import annotations
+
+import json
+from aiohttp import ClientSession, FormData
+
+from ...typing import AsyncResult, Messages, ImagesType
+from ...requests import raise_for_status
+from ...errors import ResponseError
+from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
+from ..helper import format_prompt, get_random_string
+from ...image import to_bytes, is_accepted_format
+
+class Qwen_QVQ_72B(AsyncGeneratorProvider, ProviderModelMixin):
+ url = "https://qwen-qvq-72b-preview.hf.space"
+ api_endpoint = "/gradio_api/call/generate"
+
+ working = True
+
+ default_model = "Qwen/QwQ-32B-Preview"
+ models = [default_model]
+
+ @classmethod
+ async def create_async_generator(
+ cls, model: str, messages: Messages,
+ images: ImagesType = None,
+ api_key: str = None,
+ proxy: str = None,
+ **kwargs
+ ) -> AsyncResult:
+ headers = {
+ "Accept": "application/json",
+ }
+ if api_key is not None:
+ headers["Authorization"] = f"Bearer {api_key}"
+ async with ClientSession(headers=headers) as session:
+ if images:
+ data = FormData()
+ data_bytes = to_bytes(images[0][0])
+ data.add_field("files", data_bytes, content_type=is_accepted_format(data_bytes), filename=images[0][1])
+ url = f"https://qwen-qvq-72b-preview.hf.space/gradio_api/upload?upload_id={get_random_string()}"
+ async with session.post(url, data=data, proxy=proxy) as response:
+ await raise_for_status(response)
+ image = await response.json()
+ data = {"data": [{"path": image[0]}, format_prompt(messages)]}
+ else:
+ data = {"data": [None, format_prompt(messages)]}
+ async with session.post(f"{cls.url}{cls.api_endpoint}", json=data, proxy=proxy) as response:
+ await raise_for_status(response)
+ event_id = (await response.json()).get("event_id")
+ async with session.get(f"{cls.url}{cls.api_endpoint}/{event_id}") as event_response:
+ await raise_for_status(event_response)
+ event = None
+ text_position = 0
+ async for chunk in event_response.content:
+ if chunk.startswith(b"event: "):
+ event = chunk[7:].decode(errors="replace").strip()
+ if chunk.startswith(b"data: "):
+ if event == "error":
+ raise ResponseError(f"GPU token limit exceeded: {chunk.decode(errors='replace')}")
+ if event in ("complete", "generating"):
+ try:
+ data = json.loads(chunk[6:])
+ except (json.JSONDecodeError, KeyError, TypeError) as e:
+ raise RuntimeError(f"Failed to read response: {chunk.decode(errors='replace')}", e)
+ if event == "generating":
+ if isinstance(data[0], str):
+ yield data[0][text_position:]
+ text_position = len(data[0])
+ else:
+ break
\ No newline at end of file
diff --git a/g4f/Provider/hf_space/StableDiffusion35Large.py b/g4f/Provider/hf_space/StableDiffusion35Large.py
new file mode 100644
index 00000000..445ce7ea
--- /dev/null
+++ b/g4f/Provider/hf_space/StableDiffusion35Large.py
@@ -0,0 +1,71 @@
+from __future__ import annotations
+
+import json
+from aiohttp import ClientSession
+
+from ...typing import AsyncResult, Messages
+from ...image import ImageResponse, ImagePreview
+from ...errors import ResponseError
+from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
+
+class StableDiffusion35Large(AsyncGeneratorProvider, ProviderModelMixin):
+ url = "https://stabilityai-stable-diffusion-3-5-large.hf.space"
+ api_endpoint = "/gradio_api/call/infer"
+
+ working = True
+
+ default_model = 'stable-diffusion-3.5-large'
+ models = [default_model]
+ image_models = [default_model]
+
+ @classmethod
+ async def create_async_generator(
+ cls, model: str, messages: Messages,
+ prompt: str = None,
+ negative_prompt: str = None,
+ api_key: str = None,
+ proxy: str = None,
+ width: int = 1024,
+ height: int = 1024,
+ guidance_scale: float = 4.5,
+ num_inference_steps: int = 50,
+ seed: int = 0,
+ randomize_seed: bool = True,
+ **kwargs
+ ) -> AsyncResult:
+ headers = {
+ "Content-Type": "application/json",
+ "Accept": "application/json",
+ }
+ if api_key is not None:
+ headers["Authorization"] = f"Bearer {api_key}"
+ async with ClientSession(headers=headers) as session:
+ prompt = messages[-1]["content"] if prompt is None else prompt
+ data = {
+ "data": [prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps]
+ }
+ async with session.post(f"{cls.url}{cls.api_endpoint}", json=data, proxy=proxy) as response:
+ response.raise_for_status()
+ event_id = (await response.json()).get("event_id")
+ async with session.get(f"{cls.url}{cls.api_endpoint}/{event_id}") as event_response:
+ event_response.raise_for_status()
+ event = None
+ async for chunk in event_response.content:
+ if chunk.startswith(b"event: "):
+ event = chunk[7:].decode(errors="replace").strip()
+ if chunk.startswith(b"data: "):
+ if event == "error":
+ raise ResponseError(f"GPU token limit exceeded: {chunk.decode(errors='replace')}")
+ if event in ("complete", "generating"):
+ try:
+ data = json.loads(chunk[6:])
+ if data is None:
+ continue
+ url = data[0]["url"]
+ except (json.JSONDecodeError, KeyError, TypeError) as e:
+ raise RuntimeError(f"Failed to parse image URL: {chunk.decode(errors='replace')}", e)
+ if event == "generating":
+ yield ImagePreview(url, prompt)
+ else:
+ yield ImageResponse(url, prompt)
+ break
diff --git a/g4f/Provider/hf_space/__init__.py b/g4f/Provider/hf_space/__init__.py
index 87dfb32b..5ab7ad22 100644
--- a/g4f/Provider/hf_space/__init__.py
+++ b/g4f/Provider/hf_space/__init__.py
@@ -1,18 +1,22 @@
from __future__ import annotations
-from ...typing import AsyncResult, Messages
+from ...typing import AsyncResult, Messages, ImagesType
from ...errors import ResponseError
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .BlackForestLabsFlux1Dev import BlackForestLabsFlux1Dev
from .BlackForestLabsFlux1Schnell import BlackForestLabsFlux1Schnell
from .VoodoohopFlux1Schnell import VoodoohopFlux1Schnell
+from .StableDiffusion35Large import StableDiffusion35Large
+from .Qwen_QVQ_72B import Qwen_QVQ_72B
class HuggingSpace(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://huggingface.co/spaces"
+ parent = "HuggingFace"
working = True
default_model = BlackForestLabsFlux1Dev.default_model
- providers = [BlackForestLabsFlux1Dev, BlackForestLabsFlux1Schnell, VoodoohopFlux1Schnell]
+ default_vision_model = Qwen_QVQ_72B.default_model
+ providers = [BlackForestLabsFlux1Dev, BlackForestLabsFlux1Schnell, VoodoohopFlux1Schnell, StableDiffusion35Large, Qwen_QVQ_72B]
@classmethod
def get_parameters(cls, **kwargs) -> dict:
@@ -33,8 +37,10 @@ class HuggingSpace(AsyncGeneratorProvider, ProviderModelMixin):
@classmethod
async def create_async_generator(
- cls, model: str, messages: Messages, **kwargs
+ cls, model: str, messages: Messages, images: ImagesType = None, **kwargs
) -> AsyncResult:
+ if not model and images is not None:
+ model = cls.default_vision_model
is_started = False
for provider in cls.providers:
if model in provider.model_aliases:
diff --git a/g4f/Provider/needs_auth/HuggingFace.py b/g4f/Provider/needs_auth/HuggingFace.py
index 80c0d97b..c15dc767 100644
--- a/g4f/Provider/needs_auth/HuggingFace.py
+++ b/g4f/Provider/needs_auth/HuggingFace.py
@@ -17,6 +17,7 @@ from .HuggingChat import HuggingChat
class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://huggingface.co"
+ login_url = "https://huggingface.co/settings/tokens"
working = True
supports_message_history = True
default_model = HuggingChat.default_model
@@ -149,14 +150,14 @@ class HuggingFace(AsyncGeneratorProvider, ProviderModelMixin):
def format_prompt_mistral(messages: Messages, do_continue: bool = False) -> str:
system_messages = [message["content"] for message in messages if message["role"] == "system"]
question = " ".join([messages[-1]["content"], *system_messages])
- history = "".join([
+ history = "\n".join([
f"[INST]{messages[idx-1]['content']} [/INST] {message['content']}"
for idx, message in enumerate(messages)
if message["role"] == "assistant"
])
if do_continue:
return history[:-len('')]
- return f"{history}[INST] {question} [/INST]"
+ return f"{history}\n[INST] {question} [/INST]"
def format_prompt_qwen(messages: Messages, do_continue: bool = False) -> str:
prompt = "".join([
@@ -185,7 +186,7 @@ def format_prompt_custom(messages: Messages, end_token: str = "", do_continu
def get_inputs(messages: Messages, model_data: dict, model_type: str, do_continue: bool = False) -> str:
if model_type in ("gpt2", "gpt_neo", "gemma", "gemma2"):
inputs = format_prompt(messages, do_continue=do_continue)
- elif model_type in ("mistral"):
+ elif model_type == "mistral" and model_data.get("author") == "mistralai":
inputs = format_prompt_mistral(messages, do_continue)
elif "config" in model_data and "tokenizer_config" in model_data["config"] and "eos_token" in model_data["config"]["tokenizer_config"]:
eos_token = model_data["config"]["tokenizer_config"]["eos_token"]
diff --git a/g4f/Provider/needs_auth/HuggingFaceAPI.py b/g4f/Provider/needs_auth/HuggingFaceAPI.py
index 521b2cc4..a3817b15 100644
--- a/g4f/Provider/needs_auth/HuggingFaceAPI.py
+++ b/g4f/Provider/needs_auth/HuggingFaceAPI.py
@@ -5,8 +5,8 @@ from .HuggingChat import HuggingChat
class HuggingFaceAPI(OpenaiAPI):
label = "HuggingFace (Inference API)"
- url = "https://api-inference.huggingface.co"
- login_url = "https://huggingface.co/settings/tokens"
+ parent = "HuggingFace"
+ url = "https://api-inference.huggingface.com"
api_base = "https://api-inference.huggingface.co/v1"
working = True
default_model = "meta-llama/Llama-3.2-11B-Vision-Instruct"
diff --git a/g4f/gui/client/home.html b/g4f/gui/client/home.html
index fa213061..5daa56b1 100644
--- a/g4f/gui/client/home.html
+++ b/g4f/gui/client/home.html
@@ -5,6 +5,10 @@
G4F GUI
+
+
+
+