Skip to content

Releases: ruashots/open-h3-ir

0.4.1

Choose a tag to compare

@ruashots ruashots released this 23 Aug 17:22

The front page is rewritten, and the writer's settings say music rather than score.

No behaviour changes over 0.4.0. A README is baked into the wheel at build time, so this release is what puts the new one on PyPI.

0.4.0

Choose a tag to compare

@ruashots ruashots released this 23 Aug 12:50

The compiler stops being something you start.

The ComfyUI nodes moved out into their own repository, ComfyUI-OpenH3-IR, and they run this compiler inside ComfyUI's own Python rather than talking to a service. Installing that pack pip-installs this package. Nothing is vendored, so a fix here is a release here.

The compiler publishes its contract. GET /v1/contract, h3ir contract, or an import. It states every field name, every role, every refusal code, the seven directions, the camera table and the limits. A client reads it and checks itself before it sends anything, which is what makes a version mismatch between two separately installed halves loud instead of silent. CONTRACT_VERSION is 2 and it is not the package version.

An unknown field is refused by name, never dropped. pydantic's default is to ignore an extra key, and that default cost this project a real bug: a newer client sending replaces to an older build got a valid brief back with the swap bound to whoever the analyser happened to find, and nothing anywhere said so.

Put something into a clip, or swap what is already there. A picture can be added to a clip being edited, or take the place of something in it, carrying a line naming what it stands in for in your own words. A video card now records what the camera does, read from how the framing changes across the sampled frames and left at unknown when three frames cannot separate a push in from a zoom in.

It works against any OpenAI-compatible server, not only the one it grew up on. Liveness is tried on two paths and h3ir doctor names the one that answered. Model discovery counts by the checkpoint behind each id, so two names for one set of weights collapse into one, and where a real choice remains it refuses and prints the ids.

A refused request is not an answer about vision. A 400, a 415 or a 422 is the server judging your request. A 401, a 403, a 404 or a timeout means nothing was judged at all. Those need different words and a different fix.

Director profiles. Seven ship as examples, and you can write your own. A director fills what your prompt leaves open and never outranks it, and never decides how many shots there are or where they cut. The name never reaches the writing model, only the prose.

The word "score" is gone from everything a person reads. It is "music" now. Nothing narrowed in what the compiler matches, because people write all three of music, score and soundtrack.

990 tests, 17 planted defects with all 17 caught.

v0.2.0

Choose a tag to compare

@ruashots ruashots released this 16 Aug 21:59

v0.1.0 was a compiler you reached from a terminal or over HTTP. This release gives it somewhere to
stand: three nodes on a ComfyUI canvas, a service that no longer has to share a disk with them, and a
wheel on PyPI. The document it writes is the same document, and the rules that check it grew.

It lives on the canvas now

The ComfyUI node pack did not exist at v0.1.0. There are three nodes. Setup holds the service
address and the five H3 files, and it is a picker and nothing else: no search by name, no preferred
build, no option meaning work it out. Media is a tray where every picture, clip and sound says
what it is to the piece and carries a name. Main takes one plain sentence and hands the render
everything it needs, so a graph wants no loader boxes and no H3 conditioning node.

The sentence points at the tray with @. A mention becomes that file's own description inside the
document, bound to the file rather than guessed at from the words nearby, and @speaks("...") locks a
line that comes back spoken exactly as typed. In the box a mention now reads as one object that
carries its kind, shows the file it names when you hover it, and turns red when it names nothing that
is in the tray. A slot name is corrected while you type rather than refused when you queue.

The repo installs whole into custom_nodes and adds no packages to ComfyUI's Python. The nodes talk
to the service over HTTP using the standard library alone, so the compiler's dependencies cannot reach
a working ComfyUI install.

The service can sit somewhere else

Until this release the nodes handed the service a filesystem path, which works when both halves see
one disk and cannot work at all otherwise. The service now takes the bytes as well. Paths are still
tried first, because where they work nothing is copied and a long clip costs nothing to hand over, and
when no spelling of ComfyUI's folder opens, the bytes go over the same connection instead. There is
nothing to configure and no mechanism to choose. Each file is named by its own content, so a second
render of the same graph sends nothing.

Proven against a service that genuinely could not read the disk, and the brief that came back was the
same brief the path handoff produces from the same graph.

Two things a reference can lend without being in the video

A picture set to a style lends its look and nothing in it. A clip set to how it is shot lends its
camera and its cutting and carries none of its contents across. Both are held to that by named rules
rather than by asking the writer nicely, which is the difference between a role and a hint.

The shot count works the same way. Leave it on auto and the writer decides the edit. Pin anything
from 1 to 10 and it becomes a contract the document has to honour, with a refusal and the arithmetic
when the count cannot fit the length you asked for.

pip install open-h3-ir

The wheel gives you the compiler, the h3ir command and the service, with its prompt templates,
reference briefs and tokenizer data inside it. The ComfyUI half still comes from the repo, because a
node pack has to be a folder inside custom_nodes and no wheel can put one there.

pip install open-h3-ir
export H3IR_LLM_URL=http://your-endpoint:8000/v1
h3ir doctor

Still any OpenAI-compatible endpoint, still no GPU for the compiler itself, and still nothing here
calling MiniMax.

What holds it up

1024 tests and 22 controls pass, all of it runnable with no model, no GPU and no network. At v0.1.0
that was 370 tests and 20 controls.

109 named rules check the document. The controls prove them in both directions, which is the part
worth trusting: MiniMax's own published examples sit in the test set and have to pass clean, because a
rule that fires on the spec's own artifact is a wrong rule, and deliberately broken copies of one of
those examples each have to fail on the rule that defect earns.

Known gaps, still

  • The style-LoRA registry still does not survive a compile. Reading it works: h3ir loras prints
    every trigger, bound, variant and conflict it finds in a folder, and GET /v1/loras hands a caller
    the same thing. Passing --lora into a compile is the part that breaks, and AGENTS.md names the
    errors rather than hiding them.
  • Nothing here makes a video. No sampler, no graph submitted, no GPU asked for. The output is the
    brief, and the render is somebody else's step.
  • The clips in the README cannot be reproduced by running something. Two boxes on different
    weights or drivers do not return the same frames, so those files are evidence of a run rather than
    fixtures a test could hold anything to.

Expect changes

The reason is unchanged: this exists because another application of mine needs it, so it is shaped to
that job rather than to being a general framework for prompts. What is different is how much of it is
load-bearing now, and that cuts both ways. Pin v0.2.0 if you build on it.

v0.1.0

Choose a tag to compare

@ruashots ruashots released this 13 Aug 07:45

First tagged release.

MiniMax H3 does not want a prompt. It wants a structured document: six named sections in a fixed
order, every subject bound to a numbered picture label, cut times landing on a legal frame grid.
MiniMax open-sourced the model but not the stage that writes that document. This is an open one, it
runs on your own machine, and it has a dial on top of it.

What you get

h3ir compile "one sentence" returns a validated H3 brief. The input mode (text only, first frame,
last frame, first and last, or reference images) is inferred from what you passed rather than picked
from a menu. Cut times snap to H3's real frame grid, which has 15 legal lengths and exactly one whole
second in the whole range.

A creativity dial sets how much the writer may introduce that you never asked for: restrained,
balanced (the default), bold, extreme. The README has both halves of that comparison as video.

h3ir doctor checks your endpoint before you rely on it. h3ir eval measures what a different
endpoint does to brief quality instead of leaving you to guess. h3ir serve exposes the same
compiler over HTTP. h3ir controls runs 20 correctness controls with no model and no GPU, so you can
verify an install offline.

It runs on the endpoint you already have

Any OpenAI-compatible endpoint. Ollama, llama.cpp's server, LM Studio and vLLM all speak that API, so
if you already run local models there is nothing new to stand up. The compiler itself needs no GPU,
because the weights live at the endpoint. Nothing here ever calls MiniMax.

Reference images need a vision-capable model behind that endpoint. Text-only prompts never attach an
image, so they work against a plain chat model.

git clone https://github.com/ruashots/open-h3-ir.git
cd open-h3-ir
python3 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"

export H3IR_LLM_URL=http://your-endpoint:8000/v1
h3ir doctor

What this is proven against

Qwen3.6 27B, 4-bit, served by vLLM at 262K context on two RTX 3090s, with H3 rendering the videos
from the resulting briefs. Every sample in the README came out of that setup. A 27B-class local model
with a vision tower is enough. Size your own box against that, and use h3ir eval to see what your
endpoint actually does to brief quality.

370 tests and 20 controls, green in CI.

Known gaps, said plainly

  • The style-LoRA registry is read but not usable end to end. The registry loads a folder
    correctly, h3ir loras reports triggers, strength bounds, variants, conflicts and the author
    prose, and GET /v1/loras serves all of it. But --lora does not survive a compile yet. Details
    and the exact errors are in AGENTS.md.
  • It does not render. No sampler, no graph submission, no GPU. It writes the brief; something
    else makes the video.
  • The committed sample videos are not regenerable by a script. Renders are not identical across
    model or driver versions, so the clips in the README are artifacts rather than fixtures.

Expect changes

I am building this because I need it for another application I am making, which is why it is shaped
the way it is. It does what that application needs, correctly, rather than being a general framework
for writing prompts. Pin v0.1.0 if you build on it.