Support timeout in backend_api

This commit is contained in:
hlohaus
2025-06-19 11:29:54 +02:00
parent 90262b1f6a
commit c27f0c995e
4 changed files with 31 additions and 25 deletions

View File

@@ -50,6 +50,7 @@ class RequestConfig:
class Video(AsyncGeneratorProvider, ProviderModelMixin): class Video(AsyncGeneratorProvider, ProviderModelMixin):
urls = { urls = {
"search": "https://sora.chatgpt.com/explore?query={0}",
"sora": "https://sora.chatgpt.com/explore", "sora": "https://sora.chatgpt.com/explore",
#"veo": "https://aistudio.google.com/generate-video" #"veo": "https://aistudio.google.com/generate-video"
} }
@@ -57,7 +58,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
drive_url = "https://www.googleapis.com/drive/v3/" drive_url = "https://www.googleapis.com/drive/v3/"
active_by_default = True active_by_default = True
default_model = "sora" default_model = "search"
models = list(urls.keys()) models = list(urls.keys())
video_models = models video_models = models
@@ -82,7 +83,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
if model not in cls.video_models: if model not in cls.video_models:
raise ValueError(f"Model '{model}' is not supported by {cls.__name__}. Supported models: {cls.models}") raise ValueError(f"Model '{model}' is not supported by {cls.__name__}. Supported models: {cls.models}")
yield ProviderInfo(**cls.get_dict(), model="sora") yield ProviderInfo(**cls.get_dict(), model="sora")
prompt = format_media_prompt(messages, prompt) prompt = format_media_prompt(messages, prompt)[:100]
if not prompt: if not prompt:
raise ValueError("Prompt cannot be empty.") raise ValueError("Prompt cannot be empty.")
response = await RequestConfig.get_response(prompt) response = await RequestConfig.get_response(prompt)
@@ -111,9 +112,26 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
raise MissingRequirementsError("Video provider requires a browser to be installed.") raise MissingRequirementsError("Video provider requires a browser to be installed.")
try: try:
yield ContinueResponse("Timeout waiting for Video URL") yield ContinueResponse("Timeout waiting for Video URL")
cls.page = await browser.get(cls.urls[model]) cls.page = await browser.get(cls.urls[model].format(quote(prompt)))
except Exception as e: except Exception as e:
debug.error(f"Error opening page:", e) debug.error(f"Error opening page:", e)
if prompt not in RequestConfig.urls:
RequestConfig.urls[prompt] = []
def on_request(event: nodriver.cdp.network.RequestWillBeSent, page=None):
if ".mp4" in event.request.url:
RequestConfig.headers = {}
for key, value in event.request.headers.items():
RequestConfig.headers[key.lower()] = value
RequestConfig.urls[prompt].append(event.request.url)
elif event.request.url.startswith(cls.drive_url):
RequestConfig.headers = {}
for key, value in event.request.headers.items():
RequestConfig.headers[key.lower()] = value
RequestConfig.urls[prompt].append(event.request.url)
await page.send(nodriver.cdp.network.enable())
page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request)
if model == "search":
asyncio.sleep(5)
response = await RequestConfig.get_response(prompt) response = await RequestConfig.get_response(prompt)
if response: if response:
yield Reasoning(label="Found", status="") yield Reasoning(label="Found", status="")
@@ -186,22 +204,9 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
yield Reasoning(label=f"Clicked 'Queued' button") yield Reasoning(label=f"Clicked 'Queued' button")
break break
except ProtocolException as e: except ProtocolException as e:
pass if idx == 59:
if prompt not in RequestConfig.urls: debug.error(e)
RequestConfig.urls[prompt] = [] raise RuntimeError("Failed to click 'Queued' button")
def on_request(event: nodriver.cdp.network.RequestWillBeSent, page=None):
if ".mp4" in event.request.url:
RequestConfig.headers = {}
for key, value in event.request.headers.items():
RequestConfig.headers[key.lower()] = value
RequestConfig.urls[prompt].append(event.request.url)
elif event.request.url.startswith(cls.drive_url):
RequestConfig.headers = {}
for key, value in event.request.headers.items():
RequestConfig.headers[key.lower()] = value
RequestConfig.urls[prompt].append(event.request.url)
await page.send(nodriver.cdp.network.enable())
page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request)
for idx in range(600): for idx in range(600):
yield Reasoning(label="Waiting for Video...", status=f"{idx+1}/600") yield Reasoning(label="Waiting for Video...", status=f"{idx+1}/600")
await asyncio.sleep(1) await asyncio.sleep(1)

View File

@@ -122,7 +122,7 @@ def create_app():
if AppConfig.gui: if AppConfig.gui:
if not has_a2wsgi: if not has_a2wsgi:
raise MissingRequirementsError("a2wsgi is required for GUI. Install it with: pip install a2wsgi") raise MissingRequirementsError("a2wsgi is required for GUI. Install it with: pip install a2wsgi")
gui_app = WSGIMiddleware(get_gui_app(AppConfig.demo)) gui_app = WSGIMiddleware(get_gui_app(AppConfig.demo, AppConfig.timeout))
app.mount("/", gui_app) app.mount("/", gui_app)
if AppConfig.ignored_providers: if AppConfig.ignored_providers:

View File

@@ -8,12 +8,12 @@ try:
except ImportError as e: except ImportError as e:
import_error = e import_error = e
def get_gui_app(demo: bool = False, api: bool = False): def get_gui_app(demo: bool = False, timeout: int = None):
if import_error is not None: if import_error is not None:
raise MissingRequirementsError(f'Install "gui" requirements | pip install -U g4f[gui]\n{import_error}') raise MissingRequirementsError(f'Install "gui" requirements | pip install -U g4f[gui]\n{import_error}')
app = create_app() app = create_app()
app.demo = demo app.demo = demo
app.api = api app.timeout = timeout
site = Website(app) site = Website(app)
for route in site.routes: for route in site.routes:

View File

@@ -126,7 +126,8 @@ class Backend_Api(Api):
media.append((url, None)) media.append((url, None))
if media: if media:
json_data['media'] = media json_data['media'] = media
if app.timeout:
json_data['timeout'] = app.timeout
if app.demo and not json_data.get("provider"): if app.demo and not json_data.get("provider"):
model = json_data.get("model") model = json_data.get("model")
if model != "default" and model in models.demo_models: if model != "default" and model in models.demo_models:
@@ -138,12 +139,12 @@ class Backend_Api(Api):
debug.log("User:", request.headers.get("x_user", f"{user}:{ip}")) debug.log("User:", request.headers.get("x_user", f"{user}:{ip}"))
kwargs = self._prepare_conversation_kwargs(json_data) kwargs = self._prepare_conversation_kwargs(json_data)
return self.app.response_class( return self.app.response_class(
self._create_response_stream( safe_iter_generator(self._create_response_stream(
kwargs, kwargs,
json_data.get("provider"), json_data.get("provider"),
json_data.get("download_media", True), json_data.get("download_media", True),
tempfiles tempfiles
), )),
mimetype='text/event-stream' mimetype='text/event-stream'
) )