| """ |
| Concept E — many subjects → many REST endpoints |
| =============================================== |
| |
| A workflow isn't just a canvas — it's an API. Each *disconnected* pipeline |
| (weakly-connected group of nodes ending in a subject) becomes ONE REST endpoint, |
| named after its first subject. Free references become the endpoint's parameters. |
| |
| This graph has two independent pipelines, so it exposes two endpoints: |
| /word_count (text → number) |
| /fahrenheit (number → number) |
| |
| Once launched: |
| curl http://127.0.0.1:7860/gradio_api/call/word_count -s \ |
| -H "Content-Type: application/json" -d '{"data": ["hello there friend"]}' |
| |
| This file also prints its endpoint schema at startup via `describe_workflow_api`. |
| |
| Run it: python concepts/e_multi_endpoint_api.py |
| """ |
|
|
| import json |
| import os |
|
|
| import gradio as gr |
|
|
|
|
| def word_count(text: str) -> int: |
| return len(text.split()) |
|
|
|
|
| def to_fahrenheit(celsius: float) -> float: |
| return round(celsius * 9 / 5 + 32, 1) |
|
|
|
|
| def _ref(nid, label, ptype, default, y): |
| return {"id": nid, "role": "reference", "label": label, "asset_type": ptype, |
| "inputs": [{"id": "in", "label": label, "type": ptype}], |
| "outputs": [{"id": "out", "label": label, "type": ptype}], |
| "data": {"out": default}, "x": 60, "y": y, "width": 200, "height": 90} |
|
|
|
|
| def _op(nid, fn, in_type, out_type, y): |
| return {"id": nid, "role": "operator", "kind": "fn", "fn": fn, "label": fn, |
| "inputs": [{"id": "in_0", "label": "input", "type": in_type, "required": True}], |
| "outputs": [{"id": "out_0", "label": "output", "type": out_type}], |
| "data": {}, "x": 320, "y": y, "width": 200, "height": 90} |
|
|
|
|
| def _sub(nid, label, ptype, y): |
| return {"id": nid, "role": "subject", "label": label, "asset_type": ptype, |
| "inputs": [{"id": "in", "label": label, "type": ptype}], |
| "outputs": [{"id": "out", "label": label, "type": ptype}], |
| "data": {}, "x": 580, "y": y, "width": 200, "height": 120} |
|
|
|
|
| def _edge(eid, s, sp, t, tp, ty): |
| return {"id": eid, "from_node_id": s, "from_port_id": sp, |
| "to_node_id": t, "to_port_id": tp, "type": ty} |
|
|
|
|
| GRAPH = { |
| "schema_version": "2", "name": "Two Endpoints", |
| "references": [_ref("ref_text", "Text", "text", "hello there friend", 60), |
| _ref("ref_c", "Celsius", "number", 20, 260)], |
| "operators": [_op("op_wc", "word_count", "text", "number", 60), |
| _op("op_f", "to_fahrenheit", "number", "number", 260)], |
| "subjects": [_sub("sub_wc", "Word count", "number", 60), |
| _sub("sub_f", "Fahrenheit", "number", 260)], |
| "edges": [_edge("e1", "ref_text", "out", "op_wc", "in_0", "text"), |
| _edge("e2", "op_wc", "out_0", "sub_wc", "in", "number"), |
| _edge("e3", "ref_c", "out", "op_f", "in_0", "number"), |
| _edge("e4", "op_f", "out_0", "sub_f", "in", "number")], |
| } |
|
|
| GRAPH_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "e_multi_endpoint_api.json") |
| with open(GRAPH_PATH, "w", encoding="utf-8") as f: |
| json.dump(GRAPH, f, indent=2) |
|
|
| demo = gr.Workflow(GRAPH_PATH, bind={"word_count": word_count, "to_fahrenheit": to_fahrenheit}) |
|
|
| if __name__ == "__main__": |
| from gradio.workflow_api import WorkflowGraph, describe_workflow_api |
| for ep in describe_workflow_api(WorkflowGraph.from_json(json.dumps(GRAPH))): |
| print(f" {ep['api_name']:14s} params={[p['type'] for p in ep['parameters']]} " |
| f"returns={[r['type'] for r in ep['returns']]}") |
| demo.launch() |
|
|