showcase · tier 2 · builders
Model bench
The same question fanned to three local models in parallel; a jq fan-in tabulates measured latency and length: no judge model, facts only.
- 5tasksthe plan falls out of the bindings
- 3wavesparallel by construction
- 2verbs exercisedinfer · invoke
- T2the tierbuilders
The whole file
5 tasks · 3 wavesThe plan falls out of the bindings, nothing is scheduled by hand.
model-bench.nika.yamlsource
nika: v1workflow: id: model-bench description: "One question → three local models → a measured comparison table"model: ollama/qwen3.5:4b # the house default · contenders below pick their own seatsconst: question: # A TYPED constant is `{ type, value }` — both keys, exactly those two. # `{ type, default }` is not a declaration at all (01-envelope.md §const: # an object missing either key is a bare literal object), so the prompt # below would receive the whole `{type, default}` map instead of the # question. Measured: the model gets a JSON blob and the bench is junk. type: string value: "Explain, in five lines, why a workflow should be audited before it runs."permits: tools: ["nika:jq", "nika:write"] fs: { write: ["out/model-bench.md"] }tasks: ask_incumbent: infer: model: ollama/qwen2.5:14b # the quality bar · the seat to beat prompt: "${{ const.question }}" max_tokens: 600 ask_challenger: infer: model: ollama/llama3.2:3b # another family · same size class prompt: "${{ const.question }}" max_tokens: 600 ask_tiny: infer: model: ollama/qwen2.5:0.5b # the "is small enough?" probe prompt: "${{ const.question }}" max_tokens: 600 tabulate: with: ask_incumbent_duration_ms: ${{ tasks.ask_incumbent.duration_ms }} ask_incumbent: ${{ tasks.ask_incumbent.output }} ask_challenger_duration_ms: ${{ tasks.ask_challenger.duration_ms }} ask_challenger: ${{ tasks.ask_challenger.output }} ask_tiny_duration_ms: ${{ tasks.ask_tiny.duration_ms }} ask_tiny: ${{ tasks.ask_tiny.output }} invoke: tool: "nika:jq" args: input: - model: "ollama/qwen2.5:14b" ms: "${{ with.ask_incumbent_duration_ms }}" answer: "${{ with.ask_incumbent }}" - model: "ollama/llama3.2:3b" ms: "${{ with.ask_challenger_duration_ms }}" answer: "${{ with.ask_challenger }}" - model: "ollama/qwen2.5:0.5b" ms: "${{ with.ask_tiny_duration_ms }}" answer: "${{ with.ask_tiny }}" expression: >- "| model | latency | chars | answer (first 160) |\n|---|---|---|---|\n" + (map("| " + .model + " | " + (if .ms == null then "cached" else (.ms | tostring) + "ms" end) + " | " + (.answer | length | tostring) + " | " + (.answer | gsub("\n"; " ") | .[0:160]) + " |") | join("\n")) persist: with: tabulate: ${{ tasks.tabulate.output }} invoke: tool: "nika:write" args: path: out/model-bench.md create_dirs: true content: | # Model bench — same question, measured ${{ with.tabulate }} Facts only: latency from the run's clock, length in characters. The answers are side by side — the quality call is yours.outputs: table: value: ${{ tasks.tabulate.output }} description: "The measured comparison table · latency + length per seat"nika inspect · engine 0.106.1 · vendored graph, never re-derived
7 declared edges · 3 waves · the plan falls out of the bindings