Skip to main content

LLM Benchmark

megane can build a pipeline from a natural-language request. bench/llm/ is how that gets measured: a fixed set of prompts, a rubric per prompt, and — for every one of them — a reference pipeline and the picture it draws.

Why a picture

The scorer grades the shape of a generated pipeline: which node types exist, how they are wired, what their parameters say. It never draws anything, so on its own it cannot tell an answer from its opposite. Two examples it could not see:

  • A bare filter selects; it does not change what is drawn. Selecting 8 carbons and selecting 1006 oxygens+nitrogens produce pictures that differ from each other by 0.002 % of pixels — the same view, both scoring full marks.
  • Atoms and bonds are independent viewport streams. A pipeline that fades a molecule's atoms and leaves its bonds at full opacity looks, to a shape-only rubric, exactly like one that fades both.

So each case carries a rendered reference, and each reference carries at least one counterexample: a named wrong pipeline that must not draw the same picture. A comparison that accepts everything is indistinguishable from one that works.

What a case is made of

Every case is a prompt, a pipeline, and an image, stored together:

bench/llm/dataset.ts                              the prompt and its rubric
bench/llm/golden/<case id>/pipeline.megane.json a pipeline that answers it
bench/llm/golden/<case id>/expected.png what that pipeline draws
bench/llm/golden/<case id>/meta.json fixture, expectation, capture source

The folder name is the case id. Nothing registers a case: the loader discovers the directory and fails loudly if a folder names a prompt that does not exist, and the unit tests fail if any of the three files is missing.

The pipelines are captured, not written. Each one is store.serialize() taken from a graph built in the editor, from a fresh boot. Hand-authoring them is how the first attempt shipped a bond query megane rejects (resname is not a bond field), a bondSource no fixture loads, and a parameter that lives on a different node type — each of which scored full marks against the rubric while drawing nothing.

What the images do and do not prove

A picture is ground truth only if the same pipeline draws it again, so each case records what repeated renders actually produced:

  • asserted — the reference reproduced byte-for-byte across independent boots, and the runner compares against it pixel-for-pixel.
  • recorded, not asserted — the same pipeline produced one of two renders depending on the session. Across independent boots the store's viewport state is bit-identical (same atom count, same position checksums, same bond count, same mesh vertex and coordinate checksums), the camera returns the same position, target and zoom to the last float, and the visible subsystems agree — so what flips is below the scene, in how coincident geometry rasterises. The image is kept for review; widening the pixel budget until it passed would make the suite green without making it true. The counterexamples are still checked, against a reference rendered in the same page.
  • rubric only — no pipeline can draw a different picture for this prompt. A SerializedPipeline does not carry trajectory frames or loaded force vectors, and applying one clears them, so load_trajectory and load_vector draw nothing after the round trip. The product behaves the same way, so grading against a picture it cannot produce would be grading the wrong thing.

Running it

npm run build:app            # the runner renders the built webapp
npx playwright test --project=bench-golden

The runner renders whatever ground truth it finds and asserts both directions: the reference draws its picture, and the counterexamples do not. Scoring a real model against the rubrics is separate and opt-in — the llm-eval label runs .github/workflows/llm-prompt-eval.yml, which makes real, paid API calls and posts a before/after comparison on the pull request.

The cases

casepromptfixtureimage
molecule-basicShow a molecule with its chemical bonds.caffeine_water.pdbasserted
molecule-no-bondsJust display the atoms of my structure, no bonds at all.caffeine_water.pdbasserted
molecule-trajectoryLoad a protein and play its MD trajectory with bonds.caffeine_water.pdbrubric only
crystal-polyhedraVisualize a perovskite crystal with coordination polyhedra around the metal atoms.perovskite_srtio3_3x3x3.xyzrecorded, not asserted
crystal-distance-bondsI have a crystal XYZ file without bond records. Show it with distance-based bonds and the unit cell.perovskite_srtio3_3x3x3.xyzrecorded, not asserted
crystal-polyhedra-excludeShow coordination polyhedra for an oxide but skip titanium (Z=22) as a center, keep only the others.perovskite_srtio3_3x3x3.xyzrubric only
filter-carbonDisplay only the carbon atoms of my structure.caffeine_water.pdbasserted
filter-residueShow only the alanine residues (resname ALA).1ubq.pdbrecorded, not asserted
filter-oxygen-nitrogenHighlight just the oxygen and nitrogen atoms.caffeine_water.pdbasserted
modify-scaleShow the molecule with the atoms drawn at half their normal size.caffeine_water.pdbasserted
modify-transparentMake the structure semi-transparent so I can see through it.caffeine_water.pdbasserted
labels-elementDisplay the structure and label every atom with its element symbol.caffeine_water.pdbasserted
vectors-forcesLoad forces from a file and draw them as arrows on each atom.caffeine_water.pdbrubric only
multistep-filter-bondsShow my structure with bonds, but only the carbon atoms, and label them with their element.caffeine_water.pdbasserted
multistep-water-transparentI have a caffeine molecule dissolved in water, where the water residues are named HOH. Keep the caffeine fully visible, but make the water molecules semi-transparent.caffeine_water.pdbasserted
representation-water-lineI have a caffeine molecule dissolved in water, where the water residues are named HOH. Render the water molecules as a line representation, but leave the caffeine in its normal style.caffeine_water.pdbasserted
hide-waterI have a caffeine molecule dissolved in water, where the water residues are named HOH. Hide the water so only the caffeine is shown.caffeine_water.pdbasserted
molecule-basic-ja分子を結合付きで表示してください。caffeine_water.pdbasserted
filter-carbon-ja炭素原子だけを表示して。caffeine_water.pdbasserted
solid-supercellShow a 2x2x2 supercell of my crystal structure.perovskite_srtio3_3x3x3.xyzrecorded, not asserted
color-by-elementColor the atoms by their element.caffeine_water.pdbasserted
representation-cartoonShow my protein as a cartoon.1ubq.pdbrecorded, not asserted
surface-molecularShow the molecular surface of my structure.quartz_sio2_2x2x2.xyzrecorded, not asserted
volumetric-isosurfaceLoad a cube file and render its isosurface.caffeine.sdfrubric only