From ab199f47a77d26a419be91a873670a85df931238 Mon Sep 17 00:00:00 2001 From: hannahblair Date: Wed, 5 Aug 2026 16:47:47 +0100 Subject: [PATCH 01/10] - tweak hardcoded params - add custom param ui - add image-text-to-video tag --- gradio/workflow.py | 48 ++- .../workflow/WorkflowNodeSF.svelte | 313 +++++++++++++++++- js/workflowcanvas/workflow/model-api.ts | 16 +- js/workflowcanvas/workflow/node-library.ts | 8 + .../workflow/workflow-executor.ts | 16 +- .../workflow/workflow-store.test.ts | 156 +++++++++ js/workflowcanvas/workflow/workflow-store.ts | 53 ++- js/workflowcanvas/workflow/workflow-types.ts | 1 + 8 files changed, 575 insertions(+), 36 deletions(-) diff --git a/gradio/workflow.py b/gradio/workflow.py index 65b8b48bfd1..4b4ad25ad80 100644 --- a/gradio/workflow.py +++ b/gradio/workflow.py @@ -885,17 +885,15 @@ def process_item(item): "text-to-video": "text_to_video", "image-to-image": "image_to_image", "image-to-video": "image_to_video", + "image-text-to-video": "image_to_video", "image-classification": "image_classification", "object-detection": "object_detection", "image-segmentation": "image_segmentation", - "image-to-text": "image_to_text", "automatic-speech-recognition": "automatic_speech_recognition", "audio-classification": "audio_classification", - "visual-question-answering": "visual_question_answering", - "document-question-answering": "document_question_answering", - # Not visual_question_answering: the Hub routes every image-text-to-text - # model as `conversational`, and no provider serves the VQA task at all, - # so a task-specific call fails for every model carrying this tag. + "image-to-text": "chat_completion", + "visual-question-answering": "chat_completion", + "document-question-answering": "chat_completion", "image-text-to-text": "chat_completion", } @@ -1006,6 +1004,20 @@ def _dispatch_model_endpoint(client, endpoint: str, kwargs: dict) -> str: f"{model_name} returned no text (finish_reason={finish_reason})." ) return json.dumps([text]) + try: + fn_params = set(inspect.signature(fn).parameters) + except (TypeError, ValueError): + fn_params = set() + if "extra_body" in fn_params: + known: dict = {} + extras: dict = {} + for k, v in clean.items(): + (known if k in fn_params else extras)[k] = v + if extras: + clean = { + **known, + "extra_body": {**(known.get("extra_body") or {}), **extras}, + } if endpoint == "text_generation": clean.setdefault("max_new_tokens", 512) try: @@ -1080,7 +1092,11 @@ def call_model( client = InferenceClient(model=model_id, token=hf_token, provider=provider) args = json.loads(args_json) if isinstance(args, dict): - endpoint = pipeline_tag or "" + endpoint = ( + _PIPELINE_TAG_TO_ENDPOINT.get(pipeline_tag or "") + or pipeline_tag + or "" + ) return _dispatch_model_endpoint(client, endpoint, args) task = pipeline_tag or "text-generation" @@ -1114,20 +1130,20 @@ def call_model( } return _dispatch_model_endpoint(client, endpoint, kwargs) - # Fallback for tasks not handled above: chat_completion (works for most - # text models across providers), then a raw POST as last resort. - try: - r = client.chat_completion( - [{"role": "user", "content": a0}], max_tokens=512 + def _resolve(v): + return ( + _img_url(v) + if isinstance(v, dict) and ("url" in v or "path" in v) + else v ) - return json.dumps([r.choices[0].message.content]) - except Exception: - pass + + a1_missing = a1 is None or a1 == "" + payload = _resolve(a0) if a1_missing else [_resolve(a0), _resolve(a1)] headers = {"Authorization": f"Bearer {hf_token}"} if hf_token else {} fallback_resp = httpx.post( f"https://api-inference.huggingface.co/models/{model_id}", headers=headers, - json={"inputs": a0 if not a1 else [a0, a1]}, + json={"inputs": payload}, timeout=60, ) fallback_resp.raise_for_status() diff --git a/js/workflowcanvas/workflow/WorkflowNodeSF.svelte b/js/workflowcanvas/workflow/WorkflowNodeSF.svelte index 40313a80201..84cc0b91ce1 100644 --- a/js/workflowcanvas/workflow/WorkflowNodeSF.svelte +++ b/js/workflowcanvas/workflow/WorkflowNodeSF.svelte @@ -1,6 +1,12 @@