Skip to content

Commit

Permalink
feat: add way to generate gateway side OpenAPI spec
Browse files Browse the repository at this point in the history
This commit gives users a way to generate the OpenAPI spec of the
endpoints created by the https://docs.livepeer.ai/ai/orchestrators/onchain
gateway. The difference is that at that entrypoint the `/health` route
does not exist and the `model_id` is required.
  • Loading branch information
rickstaa committed May 4, 2024
1 parent b8dc520 commit 792b620
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 42 deletions.
100 changes: 77 additions & 23 deletions runner/gen_openapi.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,64 @@
from fastapi.openapi.utils import get_openapi
from app.main import app, use_route_names_as_operation_ids
from app.routes import health, text_to_image, image_to_image, image_to_video
import argparse
import json

import yaml
import argparse
from app.main import app, use_route_names_as_operation_ids
from app.routes import health, image_to_image, image_to_video, text_to_image
from fastapi.openapi.utils import get_openapi

# Specify Endpoints for OpenAPI schema generation.
SERVERS = [
{"url": "http://gateway-endpoint.ai/", "description": "Example Gateway"},
{
"url": "https://dream-gateway.livepeer.cloud",
"description": "Livepeer Cloud Community Gateway",
},
]


def write_openapi(fname):
def translate_to_gateway(openapi):
"""Translate the OpenAPI schema from the 'runner' entrypoint to the 'gateway'
entrypoint created by the https://github.com/livepeer/go-livepeer package.
.. note::
Differences between 'runner' and 'gateway' entrypoints:
- 'health' endpoint is removed.
- 'model_id' is enforced in all endpoints.
Args:
openapi (dict): The OpenAPI schema to be translated.
Returns:
dict: The translated OpenAPI schema.
"""
# Remove 'health' endpoint
openapi["paths"].pop("/health")

# Enforce 'model_id' in all endpoints
for _, methods in openapi["paths"].items():
for _, details in methods.items():
if "requestBody" in details:
for _, content_details in details["requestBody"]["content"].items():
if (
"schema" in content_details
and "$ref" in content_details["schema"]
):
ref = content_details["schema"]["$ref"]
schema_name = ref.split("/")[-1]
schema = openapi["components"]["schemas"][schema_name]
if "model_id" in schema["properties"]:
schema["required"].append("model_id")

return openapi


def write_openapi(fname, entrypoint="runner"):
"""Write OpenAPI schema to file.
Args:
fname (str): The file name to write to. The file extension determines the file
type. Either 'json' or 'yaml'.
entrypoint (str): The entrypoint to generate the OpenAPI schema for, either
'gateway' or 'runner'. Default is 'runner'.
"""
app.include_router(health.router)
app.include_router(text_to_image.router)
Expand All @@ -25,32 +67,34 @@ def write_openapi(fname):

use_route_names_as_operation_ids(app)

print(f"Generating OpenAPI schema for '{entrypoint}' entrypoint...")
openapi = get_openapi(
title="Livepeer AI Runner",
version="0.1.0",
openapi_version=app.openapi_version,
description="An application to run AI pipelines",
routes=app.routes,
servers=SERVERS,
)

# Translate OpenAPI schema to 'gateway' side entrypoint if requested.
if entrypoint == "gateway":
print("Translating OpenAPI schema from 'runner' to 'gateway' entrypoint...")
openapi = translate_to_gateway(openapi)
fname = fname.replace(".yaml", "_gateway.yaml")

# Write OpenAPI schema to file.
with open(fname, "w") as f:
print(f"Writing OpenAPI schema to '{fname}'...")
if fname.endswith(".yaml"):
yaml.dump(
get_openapi(
title="Livepeer AI Runner",
version="0.1.0",
openapi_version=app.openapi_version,
description="An application to run AI pipelines",
routes=app.routes,
servers=SERVERS,
),
openapi,
f,
sort_keys=False,
)
else:
json.dump(
get_openapi(
title="Livepeer AI Runner",
version="0.1.0",
openapi_version=app.openapi_version,
description="An application to run AI pipelines",
routes=app.routes,
servers=SERVERS,
),
openapi,
f,
indent=4, # Make human readable.
)
Expand All @@ -66,6 +110,16 @@ def write_openapi(fname):
default="json",
help="File type to write to, either 'json' or 'yaml'. Default is 'json'",
)
parser.add_argument(
"--entrypoint",
type=str,
choices=["gateway", "runner"],
default="runner",
help=(
"The entrypoint to generate the OpenAPI schema for, either 'gateway' or "
"'runner'. Default is 'runner'",
),
)
args = parser.parse_args()

write_openapi(f"openapi.{args.type.lower()}")
write_openapi(f"openapi.{args.type.lower()}", args.entrypoint)
39 changes: 20 additions & 19 deletions worker/runner.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 792b620

Please sign in to comment.