From 499dcc0154582aa00196bc7c47c37db70c810184 Mon Sep 17 00:00:00 2001
From: hlohaus <983577+hlohaus@users.noreply.github.com>
Date: Tue, 29 Jul 2025 19:57:13 +0200
Subject: [PATCH] refactor: replace see_stream with sse_stream and update
md2html output logic
- Replaced all imports and usages of `see_stream` with `sse_stream` across:
- `g4f/Provider/Kimi.py`
- `g4f/Provider/hf_space/BlackForestLabs_Flux1KontextDev.py`
- `g4f/Provider/needs_auth/PuterJS.py`
- `g4f/Provider/template/OpenaiTemplate.py`
- `g4f/requests/__init__.py` (renamed function `see_stream` to `sse_stream`)
- Modified `g4f/Provider/needs_auth/GeminiPro.py`:
- Updated `default_model` from `gemini-2.5-flash-preview-04-17` to `gemini-2.5-flash`
- Removed `gemini-2.5-flash-preview-04-17` from `fallback_models`
- Updated `etc/tool/md2html.py`:
- Added `re` import
- Changed `process_single_file_with_output` to check if output file exists
- If exists, uses regex to update `
` and `itemprop="text">` content instead of writing full template
- If not, generates HTML using the template as before
---
etc/tool/md2html.py | 18 ++++++++++++------
g4f/Provider/Kimi.py | 4 ++--
.../BlackForestLabs_Flux1KontextDev.py | 7 +++----
g4f/Provider/needs_auth/GeminiPro.py | 3 +--
g4f/Provider/needs_auth/PuterJS.py | 4 ++--
g4f/Provider/template/OpenaiTemplate.py | 6 +++---
g4f/requests/__init__.py | 2 +-
7 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/etc/tool/md2html.py b/etc/tool/md2html.py
index eb57f032..988b4282 100644
--- a/etc/tool/md2html.py
+++ b/etc/tool/md2html.py
@@ -44,6 +44,7 @@ License: MIT
"""
import os
+import re
import sys
import requests
import time
@@ -411,14 +412,19 @@ def process_single_file_with_output(file_path: Path, template: str, output_path:
# Create output directory if needed
output_path.parent.mkdir(parents=True, exist_ok=True)
-
- # Generate final HTML
- final_html = template.replace("{{ article }}", html).replace("{{ title }}", title)
-
+
+ # If output file exists, read and replace title and content
+ if output_path.is_file():
+ output = output_path.read_text()
+ output = re.sub(r"([\S\s]+?)", f"{title}", output)
+ output = re.sub(r'itemprop="text">[\S\s]+?', f'itemprop="text">{html}', output)
+ else:
+ # If output file does not exist, create it with template
+ output = template.replace("{{ article }}", html).replace("{{ title }}", title)
# Write output file
with open(output_path, 'w', encoding='utf-8') as f:
- f.write(final_html)
-
+ f.write(output)
+
print(f"✓ Created: {output_path}")
return True
diff --git a/g4f/Provider/Kimi.py b/g4f/Provider/Kimi.py
index e98ca79c..da4c9f5b 100644
--- a/g4f/Provider/Kimi.py
+++ b/g4f/Provider/Kimi.py
@@ -5,7 +5,7 @@ from typing import AsyncIterator
from .base_provider import AsyncAuthedProvider, ProviderModelMixin
from ..providers.helper import get_last_user_message
-from ..requests import StreamSession, see_stream, raise_for_status
+from ..requests import StreamSession, sse_stream, raise_for_status
from ..providers.response import AuthResult, TitleGeneration, JsonConversation, FinishReason
from ..typing import AsyncResult, Messages
@@ -90,7 +90,7 @@ class Kimi(AsyncAuthedProvider, ProviderModelMixin):
json=data
) as response:
await raise_for_status(response)
- async for line in see_stream(response):
+ async for line in sse_stream(response):
if line.get("event") == "cmpl":
yield line.get("text")
elif line.get("event") == "rename":
diff --git a/g4f/Provider/hf_space/BlackForestLabs_Flux1KontextDev.py b/g4f/Provider/hf_space/BlackForestLabs_Flux1KontextDev.py
index 9a0a58f5..a741ee6b 100644
--- a/g4f/Provider/hf_space/BlackForestLabs_Flux1KontextDev.py
+++ b/g4f/Provider/hf_space/BlackForestLabs_Flux1KontextDev.py
@@ -1,11 +1,10 @@
from __future__ import annotations
-import json
import uuid
from ...typing import AsyncResult, Messages, MediaListType
-from ...providers.response import ImageResponse, ImagePreview, JsonConversation, Reasoning
-from ...requests import StreamSession, FormData, see_stream
+from ...providers.response import ImageResponse, JsonConversation, Reasoning
+from ...requests import StreamSession, FormData, sse_stream
from ...tools.media import merge_media
from ...image import to_bytes, is_accepted_format
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
@@ -131,7 +130,7 @@ class BlackForestLabs_Flux1KontextDev(AsyncGeneratorProvider, ProviderModelMixin
# GET the event stream to receive updates and results asynchronously
async with cls.run("get", session, conversation) as event_response:
await raise_for_status(event_response)
- async for chunk in see_stream(event_response.iter_lines()):
+ async for chunk in sse_stream(event_response):
if chunk.get("msg") == "process_starts":
yield Reasoning(label="Processing started")
elif chunk.get("msg") == "progress":
diff --git a/g4f/Provider/needs_auth/GeminiPro.py b/g4f/Provider/needs_auth/GeminiPro.py
index 9d93e870..9140fd5f 100644
--- a/g4f/Provider/needs_auth/GeminiPro.py
+++ b/g4f/Provider/needs_auth/GeminiPro.py
@@ -28,14 +28,13 @@ class GeminiPro(AsyncGeneratorProvider, ProviderModelMixin):
supports_system_message = True
needs_auth = True
- default_model = "gemini-2.5-flash-preview-04-17"
+ default_model = "gemini-2.5-flash"
default_vision_model = default_model
fallback_models = [
"gemini-2.0-flash",
"gemini-2.0-flash-lite",
"gemini-2.0-flash-thinking-exp",
"gemini-2.5-flash",
- "gemini-2.5-flash-preview-04-17",
"gemma-3-1b-it",
"gemma-3-12b-it",
"gemma-3-27b-it",
diff --git a/g4f/Provider/needs_auth/PuterJS.py b/g4f/Provider/needs_auth/PuterJS.py
index e4157a10..09930e6d 100644
--- a/g4f/Provider/needs_auth/PuterJS.py
+++ b/g4f/Provider/needs_auth/PuterJS.py
@@ -9,7 +9,7 @@ from ...typing import AsyncResult, Messages, MediaListType
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
from ...providers.response import FinishReason, Usage, Reasoning, ToolCalls
from ...tools.media import render_messages
-from ...requests import see_stream, raise_for_status
+from ...requests import sse_stream, raise_for_status
from ...errors import ResponseError, ModelNotFoundError, MissingAuthError
from ..helper import format_media_prompt
from .. import debug
@@ -405,7 +405,7 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
return
elif mime_type.startswith("text/event-stream"):
reasoning = False
- async for result in see_stream(response.content):
+ async for result in sse_stream(response.content):
if "error" in result:
raise ResponseError(result["error"].get("message", result["error"]))
choices = result.get("choices", [{}])
diff --git a/g4f/Provider/template/OpenaiTemplate.py b/g4f/Provider/template/OpenaiTemplate.py
index 21ac3380..b7480a7f 100644
--- a/g4f/Provider/template/OpenaiTemplate.py
+++ b/g4f/Provider/template/OpenaiTemplate.py
@@ -5,12 +5,12 @@ import requests
from ..helper import filter_none, format_media_prompt
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
from ...typing import Union, AsyncResult, Messages, MediaListType
-from ...requests import StreamSession, StreamResponse, raise_for_status, see_stream
+from ...requests import StreamSession, StreamResponse, raise_for_status, sse_stream
from ...image import use_aspect_ratio
from ...image.copy_images import save_response_media
from ...providers.response import FinishReason, ToolCalls, Usage, ImageResponse, ProviderInfo, AudioResponse, Reasoning
from ...tools.media import render_messages
-from ...errors import MissingAuthError, ResponseError
+from ...errors import MissingAuthError
from ... import debug
class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin):
@@ -178,7 +178,7 @@ async def read_response(response: StreamResponse, stream: bool, prompt: str, pro
reasoning = False
first = True
model_returned = False
- async for data in see_stream(response):
+ async for data in sse_stream(response):
OpenaiTemplate.raise_error(data)
model = data.get("model")
if not model_returned and model:
diff --git a/g4f/requests/__init__.py b/g4f/requests/__init__.py
index d14d0578..9faf8c18 100644
--- a/g4f/requests/__init__.py
+++ b/g4f/requests/__init__.py
@@ -215,7 +215,7 @@ async def get_nodriver(
BrowserConfig.stop_browser = on_stop
return browser, on_stop
-async def see_stream(iter_lines: Iterator[bytes]) -> AsyncIterator[dict]:
+async def sse_stream(iter_lines: Iterator[bytes]) -> AsyncIterator[dict]:
if hasattr(iter_lines, "content"):
iter_lines = iter_lines.content
elif hasattr(iter_lines, "iter_lines"):