Self-hosted service
ml-tooling/opyrator avatar
ml-tooling/opyrator

Opyrator: Pydantic-typed Python functions as FastAPI services and Streamlit UIs

🪄 Turns your machine learning code into microservices with web API, interactive GUI, and more.

3,134 stars168 forksPythonMIT

At a glance

What is it?
Opyrator wraps a single Python function whose input and output are Pydantic models, then serves it two ways: an auto-generated FastAPI HTTP API and an auto-generated Streamlit web UI. It is an alpha-stage tool, last released as v0.0.11 in May 2021, and the README itself says it is only suggested for experimental usage.
Who is it for?
Adopt Opyrator for internal demos, notebooks-to-service handoffs, and any case where one function with Pydantic input and output models needs a browser form and an OpenAPI endpoint in the same afternoon. Do not adopt it as the serving layer for a high-traffic production model, and do not adopt it if your inference path cannot be expressed as a single synchronous function with a Pydantic return type.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap Opyrator fills: a typed function with no interface

Most machine learning code reaches a usable state as a function in a file. Someone writes generate_text(prompt), it works on their machine, and the next step is a week of plumbing: an HTTP handler, request validation, a JSON schema, a form so a non-engineer can try it. Opyrator targets exactly that gap. The README describes it as turning Python functions into microservices with a web API and an interactive GUI, and the unit of work it accepts is narrow on purpose: one function with an input parameter and a return value, both based on Pydantic models, with the models declared through type hints. The README's own hello_world example is a two-field contract, an Input model with a message string and an Output model with a message string. That narrowness is the design. Opyrator is for the person who has the function and does not want to write the interface, not for a team that has already decided on a service framework and needs a code generator inside it.

How the type hints become an API and a form

The mechanism is inference from the signature. Opyrator reads the Pydantic input and output models attached to the function, and those models are the single source that both surfaces are built from. The README states that Opyrator builds on OpenAPI, JSON Schema, and Python type hints, and that it is powered by FastAPI, Streamlit, and Pydantic. So the data flow is: your Pydantic model produces a JSON Schema, the JSON Schema produces an OpenAPI document for the HTTP side and a set of form fields for the Streamlit side, and your function sits behind both. Because the two surfaces share one schema, a field you add to Input appears in the API and in the UI without a second edit. The repository's examples follow this pattern, with the text generation demo and the question answering demo each linked to a published OpenAPI spec under docs/openapi-demo-specs/, which is the clearest evidence that the generated spec is treated as an output artifact rather than an internal detail. What the material does not show is how Opyrator handles inputs that JSON Schema cannot express well, such as file uploads or large binary payloads; the examples given are text-oriented.

Getting a function running: install and the two launch commands

Installation is a single command, pip install opyrator, with Python 3.6 or later as the stated requirement. The README's walkthrough is three steps. Put the function in a file, for instance my_opyrator.py, then run opyrator launch-ui my_opyrator:hello_world for the Streamlit interface, or opyrator launch-api my_opyrator:hello_world for the FastAPI service. The argument is a module path followed by a colon and the function name, the same convention used by uvicorn and gunicorn. The README notes that the process prints the address it is serving on. Ports are configurable: the bundled example runs opyrator launch-ui app:generate_text --port 8051, and the README says to substitute launch-api for launch-ui to get the HTTP server instead. For the demo playground as a whole, the README gives docker run -p 8080:8080 mltooling/opyrator-playground:latest. The examples themselves need their own dependencies, installed from a per-example requirements.txt before the launch command will work.

Packaging: a file or an image, and what that buys you

The feature list includes saving and sharing a service as a self-contained executable file or a Docker image, described in the README as portable, shareable, and executable. This is the part that distinguishes Opyrator from writing a FastAPI app by hand. A hand-written service is a repository plus a deployment story; an Opyrator bundle is meant to be handed to someone who does not have your environment. The README also lists reuse of pre-defined components and combination with existing Opyrators, which implies the packaging format is composable rather than a single frozen artifact. Treat these as claims from the README, not as verified behaviour: the material describes the capability and shows the playground image on Docker Hub, but it does not document the bundle format, the CLI subcommand that produces a bundle, or how component reuse is expressed in code. If packaging is the reason you are considering Opyrator, that is the first thing to confirm against the repository, because the README describes the outcome without showing the command.

The alpha label is not boilerplate

The README carries an explicit note: alpha version, only suggested for experimental usage. The release history supports taking that seriously. The two most recent releases listed are v0.0.11 and v0.0.10, both dated 2021-05-01, an hour apart. The version number is still 0.0.x. The repository's last push is dated 2026-09-08, so the code has been touched more recently than the last release, but the material does not say what changed, whether a release is planned, or whether the packaging and reuse features described in the README are complete. The practical consequence is that you are adopting a tool whose interface you may have to patch yourself, and whose version pin matters: with releases this sparse, a minor-version bump is not a reliable signal of a small change. A second limitation is structural rather than temporal. The input contract is one Pydantic model and the output is one Pydantic model, and the function is called synchronously. Anything with streaming output, multiple endpoints, background jobs, or a model too large to reload per request does not fit the shape, and forcing it in means fighting the abstraction instead of using it.

Opyrator against a hand-written FastAPI service

The obvious alternative is FastAPI on its own, and the difference is where the schema lives. With FastAPI you write the Pydantic models and the route decorators, and you choose the response model, the status codes, the dependencies, and the middleware. You get the same OpenAPI document and the same generated docs page, but you also get every knob. Opyrator removes the decorators and the routing decisions by deriving them from the function signature, and it adds a Streamlit UI that plain FastAPI does not give you. That trade is the whole comparison. If your service is one function with one input model, Opyrator is less code and you get the form for free. If you need a second endpoint, custom authentication, or control over how the model is loaded, FastAPI alone is the smaller total effort, because you would be adding back the parts Opyrator deliberately hides. Streamlit alone covers the UI half but gives you no HTTP API, so the two tools are not substitutes for the combined output.

Maintenance, licensing, and what to pin

Opyrator is MIT licensed, which permits commercial use, modification, and redistribution provided the copyright notice and permission notice are retained. This is a statement about the licence text, not legal advice; if you redistribute a packaged service, have someone check that the notices for Opyrator and its dependencies survive the packaging step. On maintenance, the cost is mostly version drift. The README requires Python 3.6 or later, and the dependency chain runs through FastAPI, Streamlit, and Pydantic, all of which have moved since the v0.0.11 release in May 2021. Pydantic in particular has had breaking changes across major versions, and the README's model definitions are written against the older API. A team adopting Opyrator should pin opyrator and its transitive dependencies together rather than letting pip resolve freely, and should expect to either stay on the pinned set or carry the upgrade themselves. Because the project is at 0.0.x and the releases are sparse, there is no evidence in the material of a compatibility policy you can rely on.

Editorial conclusion

Adopt Opyrator for internal demos, notebooks-to-service handoffs, and any case where one function with Pydantic input and output models needs a browser form and an OpenAPI endpoint in the same afternoon. Do not adopt it as the serving layer for a high-traffic production model, and do not adopt it if your inference path cannot be expressed as a single synchronous function with a Pydantic return type. Before committing, run opyrator launch-api on your own function and read the generated OpenAPI document, because the shape of that document is the contract your callers will inherit, and check the repository's recent commit activity against the v0.0.11 release date to decide whether you are willing to carry the alpha label yourself.

Official sources

  1. License: MIT
  2. ml-tooling/opyrator on GitHub
  3. Project website
  4. README
  5. Releases
Community notes

Community notes