惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Engineering at Meta
Engineering at Meta
J
Java Code Geeks
I
InfoQ
腾讯CDC
Vercel News
Vercel News
IT之家
IT之家
V
Visual Studio Blog
P
Proofpoint News Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 叶小钗
有赞技术团队
有赞技术团队
月光博客
月光博客
Martin Fowler
Martin Fowler
量子位
L
LangChain Blog
B
Blog
Last Week in AI
Last Week in AI
博客园 - 司徒正美
Microsoft Security Blog
Microsoft Security Blog
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans

Hacker News: Show HN

PurrrrrFocus: Pomodoro Timer App - App Store Workflow Engine — Multi-Step Orchestration for Bun RapidPhoto: Pro Photo Editor App - App Store GitHub - DheerG/swarms: Achieve extraordinary results with claude code across a variety of tasks SPICE simulation → oscilloscope → verification with Claude Code — Lucas Gerads Show HN: VCoding – A 5 MB native Windows IDE with no dynamic dependencies Show HN: LLMs don't hallucinate because they're bad at math, it's the format GitHub - Agent-FM/agentfm-core: AgentFM is a peer-to-peer network that turns everyday computers into a decentralized AI supercomputer. AgentFM lets you run massive AI workloads directly across a global mesh of idle CPUs and GPUs. Show HN: Tracking Top US Science Olympiad Alumni over Last 25 Years GitHub - Potarix/agent-hub: One place to talk to all your agents Show HN: Runtime security for AI agents(injection,tool abuse, data exfiltration) GitHub - dubeyKartikay/lazyspotify: Terminal Spotify client for macOS and Linux GitHub - the-banana-tool/king-louie: Easy to use GUI Personal AI Assistant. Win/Linux/Mac. Show HN I made my vacation rental bookable by AI agents–no Airbnb, 0% commission GitHub - basteez/jsf-autoreload: maven plugin to enable hot reload on jsf projects uvm32/hosts/host-gdbstub at main · ringtailsoftware/uvm32 GitHub - labsai/EDDI: Config-driven engine that turns JSON into production-grade AI agents. Multi-agent orchestration, 12+ LLM providers, MCP/A2A protocols, RAG, persistent memory, and enterprise compliance (EU AI Act, GDPR, HIPAA). Built on Quarkus. GitHub - glitchnsec/fortyone-oss: AI Executive Assistant Platform Quickstart | Alien GitHub - muxshed/shed: One stream in, or many. Every destination, simultaneously. No cloud middleman, no per-channel fees, no limits. GitHub - ocrbase-hq/ocrbase: 📄 PDF/IMG ->.MD/JSON Document OCR API for PaddleOCR and GLMOCR. Self-hostable. GitHub - impactjo/home-memory: MCP server that lets your AI assistant remember everything about your home. GitHub - Sets88/dbcls: DbCls is a powerful terminal database client that supports various databases GitHub - neptun2000/heor-agent-mcp GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh RollQuation: Math Puzzles - Apps on Google Play GitHub - dropbox/witchcraft Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis GitHub - opentalon/opentalon: OpenTalon is an open-source platform built from the ground up in Go as a robust alternative to OpenClaw LinkedIn™ 职位抓取工具 - Chrome 应用商店
GitHub - shahar-dagan/openfusion: Combine the results fro...
shadag · 2026-06-18 · via Hacker News: Show HN

CI License: MIT Python 3.11+

An open-source, drop-in compound-model proxy. Point any OpenAI-compatible tool at it, set model: "openfusion", and your prompt is fanned out to a panel of LLMs in parallel — then a judge model reads every response (consensus, contradictions, blind spots) and streams back a single synthesized answer that aims to beat any one of them.

It's the open version of the mixture-of-agents idea behind OpenRouter's Fusion: better answers from models you already pay for, as a tunable, forkable recipe instead of a black box.

openfusion playground — panel fan-out to judge synthesis

Quick start · How it works · Playground · Routing & strategies · vs. OpenRouter Fusion · Benchmarks · Contributing

Project layout

New here? You only need the first two to run it; the rest is for tuning and contributing.

Path What it is
openfusion/ The proxy (FastAPI). Start with server.py; see docs/ARCHITECTURE.md for the module map.
web/ The playground UI source (React + shadcn). Built assets ship in openfusion/static/.
examples/ Copy-paste config recipes (preset, dev, panel, bench…). You don't need a config to start.
bench/ Reproducible head-to-head harness; bench/FINDINGS.md is where fusion does and doesn't pay off.
DESIGN.md · docs/ Design rationale, architecture, and security notes.

Status

Beta — panel fan-out, judge synthesis, SSE streaming, web-tool fusion, an Auto Router, debate/ vote/ranked aggregators, production limits, and an interactive playground. See DESIGN.md and docs/ARCHITECTURE.md for architecture and security notes.

Quick start

openfusion has two front ends — an interactive terminal chat and a web playground. No clone, no config, no env vars needed to start.

Chat in your terminal

uvx --from git+https://github.com/shahar-dagan/openfusion openfusion   # ephemeral, needs uv
# …or: pip install git+https://github.com/shahar-dagan/openfusion && openfusion

Bare openfusion drops you into a Rich-rendered chat with the model panel — a banner, a live panel-progress spinner, Markdown answers with syntax-highlighted code, and slash commands (/preset, /tokens, /models, /key, /clear). On first run it asks for your OpenRouter key and saves it (~/.config/openfusion/credentials), so later runs don't re-prompt; use /key to change it. Pipe for one-shots: echo "…" | openfusion.

Web playground

openfusion web                                  # opens the playground in your browser
# …or: docker run -p 8000:8000 ghcr.io/shahar-dagan/openfusion

openfusion web pops the playground open at http://localhost:8000 once the server is ready (pass --no-open, or it's skipped automatically in non-interactive/headless/Docker contexts). Paste your key (kept only in server memory) and fuse. With nothing configured it boots the Budget preset (a diverse panel + judge with web search) so the first run lands where fusion actually wins.

Install the command everywhere (no venv to activate)

uv tool install .     # from a clone — or: pipx install . && pipx ensurepath

For active development, pip install -e . inside an activated venv (the command then works only while that venv is active). A bare pip install -e . does not put openfusion on your global PATH — see Troubleshooting.

For a fixed recipe, write an openfusion.yaml (start from examples/preset.yaml.examplepreset: quality | budget, or examples/default.yaml.example for a fully spelled-out panel/judge). A preset expands to a diverse OpenRouter panel + judge with web tools on, mirroring OpenRouter Fusion's Quality/Budget switch:

Preset Panel Judge Tools
quality Claude Sonnet 4 · Gemini 3 Pro · DeepSeek V4 Pro Claude Sonnet 4 web search + fetch
budget GPT-4o-mini · DeepSeek V4 Pro · Kimi K2.6 DeepSeek V4 Pro web search + fetch

Use as a drop-in API from the OpenAI SDK (with openfusion web running):

from openai import OpenAI

client = OpenAI(base_url="http://localhost:8000/v1", api_key="local-dev")
stream = client.chat.completions.create(
    model="openfusion",
    messages=[{"role": "user", "content": "Explain mixture-of-agents in one paragraph."}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")

Or straight from the terminal, no server needed:

openfusion ask "Compare Postgres and SQLite for a small SaaS." --max-tokens 800

ask runs one fusion against your configured panel and streams the synthesized answer to stdout (panel progress goes to stderr). --max-tokens caps every call — lower is faster and cheaper.

Speed & length. Fusion runs N panel calls plus a judge, so it's slower than one model — the panel runs in parallel and the judge streams as soon as the panel finishes. The judge is prompted to stay concise, and you cap length with --max-tokens (CLI), max_tokens (API), the response- length control in the playground Settings, or cost_controls in config.

Routing & strategies

Three knobs control whether and how a prompt is fused. All are optional and off/default.

  • Auto Router (router.enabled: true) — a per-prompt gate that answers simple prompts with a single pass-through call and reserves the panel for prompts that look like they benefit (long, analytical, or containing code). Default is a cheap heuristic (no extra model call); mode: model uses a small classifier model and falls back to the heuristic if it errors:

    router:
      enabled: true
      mode: heuristic     # heuristic | model | always | never
      min_chars: 280      # prompts at/over this length fuse
      # classifier:       # required for mode: model
      #   base_url: https://openrouter.ai/api/v1
      #   api_key: ${OPENROUTER_API_KEY}
      #   model: openai/gpt-4o-mini
  • Strategy (strategy:) — how the panel is produced: self_fusion (one model sampled N times), panel (a fixed diverse panel), or debate (a diverse panel where each member revises after seeing the others' answers, then the judge synthesizes). Debate trades extra cost/latency for cross-examination:

    strategy: debate
    debate:
      rounds: 1           # revision rounds before the judge
  • Aggregator (aggregator:) — how answers become one: judge (synthesis, default), vote (majority vote, cheaper, best for verifiable short-answer tasks), or ranked (one short judge call picks the single best answer — cheaper than synthesis, uses model judgment unlike vote).

  • Analysis transparency (analysis.emit: true) — surface the judge's structured reasoning (consensus / contradictions / partial coverage / unique insights / blind spots) as a separate SSE event: analysis (and an analysis field on non-streaming responses), without polluting the answer body.

  • Prompt caching (cache.enabled: true) — mark the shared prefix so self-fusion's N samples reuse a cached prompt on providers that support it (a no-op elsewhere).

Production limits

For public deployments, bound load and spend (both default to 0 = unlimited):

limits:
  max_in_flight: 64           # cap concurrent requests; over-limit returns 503
  rate_limit_per_minute: 60   # per gateway key (or per client when unauthenticated); over-limit returns 429

These are best-effort, single-process guards — pair them with provider-side budgets and, for multi-replica deployments, an edge rate limiter.

How it works

A request to model: "openfusion" is fanned out to a panel of models in parallel (each optionally doing its own web research), then a judge model reads every answer and synthesizes one — streamed back over SSE, with the structured analysis and cost alongside.

flowchart LR
    C["Client<br/>(Cursor · OpenAI SDK · anything)"] -->|"POST /v1/chat/completions<br/>model=openfusion"| R{"Router<br/><i>(optional)</i>"}
    R -->|simple prompt| S["Single model"] --> OUT
    R -->|worth fusing| P

    subgraph P ["Panel · parallel fan-out"]
        direction TB
        A["Model A 🔍"]
        B["Model B 🔍"]
        D["Model C 🔍"]
    end

    P --> J["Judge<br/>consensus · contradictions · blind spots"]
    J --> OUT["Streamed answer (SSE)<br/>+ analysis + token/cost"]
    C -.->|other model / client tools| S

    classDef accent fill:#eef2ff,stroke:#4f46e5,color:#3730a3;
    class J,R accent;
Loading
  • Drop-in. OpenAI-compatible POST /v1/chat/completions + /v1/models, real SSE streaming.
  • No lock-in. Each panel member + judge is {base_url, api_key, model}. OpenRouter is the default upstream; OpenAI, Together, local vLLM/Ollama all work.
  • Config-driven. Panel, judge, strategy, aggregator, router, and limits live in openfusion.yaml — or a one-word preset, or nothing at all (zero-config quick start).

openfusion vs. OpenRouter Fusion

openfusion is the open implementation of the same idea. The core mechanism is at parity; the differences are scale and a per-prompt router.

OpenRouter Fusion openfusion
Parallel panel → judge synthesis
Synthesis dimensions consensus · contradictions · partial coverage · unique insights · blind spots same
Web search + fetch on the panel ✅ (default) ✅ (on by default with preset:)
Quality / Budget presets ✅ (preset: quality | budget)
Override panel + judge ✅ (plugin fields) ✅ (any {base_url, api_key, model} in YAML)
Per-call cost breakdown ✅ (Activity) ✅ (SSE usage event + /metrics)
Self-hostable / forkable ❌ closed API ✅ MIT, any OpenAI-compatible provider
Per-prompt Auto Router ✅ heuristic or model classifier (router.enabled)
Structured analysis surfaced analysis.emit (SSE analysis event)
Multi-round debate strategy: debate
Concurrency cap + rate limiting limits (best-effort, single-process)
Interactive web playground ✅ embedded at /playground (zero-build)
Headline benchmark full DRACO (100 tasks) DRACO subset (10 tasks) — see bench/FINDINGS.md

Parameter precedence

Parameter Applies to Notes
temperature (client) Judge only indirectly via recipe Self-fusion varies panel temps from config, not client
max_tokens, stop, response_format Judge (visible output) Panel members use recipe defaults
stream, stream_options Judge path Panel always runs non-streamed internally
tools / tool_calls Fusion or pass-through Server-executable web tools (openrouter:web_search/web_fetch) are fused; client-side function tools and mid-conversation tool turns pass through

Environment variables

Variable Purpose
OPENROUTER_API_KEY Default upstream key (via ${OPENROUTER_API_KEY} in config)
OPENFUSION_CONFIG Path to config file (default: openfusion.yaml)
OPENFUSION_API_KEYS Comma-separated gateway allowlist (optional)
OPENFUSION_HOST / OPENFUSION_PORT Server bind address

Cost safety and live smoke tests

cost_controls in config caps max_tokens for pass-through, panel, and judge calls. Missing max_tokens values are filled from the configured ceiling; over-limit pass-through and judge requests return 400, while internal panel calls clamp to their ceiling.

Run the opt-in live OpenRouter smoke test only when you intend to spend a small number of credits:

export OPENROUTER_API_KEY=your-key
python scripts/openrouter_smoke.py --config examples/dev.yaml.example --yes-spend-credits

Benchmarks

Run the head-to-head benchmark (self-fusion vs solo model):

pip install -e ".[dev]"
python bench/run.py --config examples/default.yaml.example --tasks bench/tasks/sample.jsonl

Use --tasks bench/tasks/smoke.jsonl --max-tokens 32 before larger benchmark runs.

Each run reports accuracy plus the spend it took to get there — total_tokens and total_cost_usd per mode — so you can weigh any accuracy change against the extra cost of fanning out to a panel.

What we measure today

The bundled bench/tasks/sample.jsonl (20 short Q&A tasks) is saturated for a capable model — the solo baseline already scores ~100%, so there is no headroom for fusion to add accuracy. On a recent run with openai/gpt-4o-mini (self-fusion N=2, max_tokens=32):

Mode Accuracy Avg latency Tokens Cost
Solo 100% (20/20) 0.55s 536 $0.0001
Self-fusion 95% (19/20) 1.40s 4,669 $0.0008

So on easy tasks fusion does not beat a single call — it costs more (here ~9× the tokens) and can even regress, because the judge only has trivially-correct answers to choose between. This is expected: mixture-of-agents helps where a single model is unreliable, not where it is already right.

openfusion makes no "beats frontier" claim. Demonstrating where fusion earns its cost needs a harder eval (one the solo baseline does not already ace) scored on quality per dollar, not accuracy alone. That eval is in progress; this table will be updated to show where fusion does and doesn't pay off. Claim only what your own bench/run.py run proves on your model and tasks.

Observability

The proxy exposes Prometheus metrics at GET /metrics (no auth; scrape-only, bind accordingly):

  • openfusion_requests_total{route,outcome} — client-facing requests (fusion / pass_through).
  • openfusion_upstream_requests_total{phase,outcome} — upstream calls by panel / judge / pass_through.
  • openfusion_panel_members_total{outcome} — per-member success vs. degraded failures.
  • openfusion_tokens_total{phase,kind} and openfusion_cost_usd_total{phase} — token and cost spend.
  • openfusion_request_latency_ms / openfusion_upstream_latency_ms — latency summaries (_count + _sum).

Cost (usage.cost, when the upstream reports it) is also rolled into the per-request SSE event: usage payload and the non-streaming usage field, so a single fusion call shows what it spent across the panel and judge. Per-call structured logs remain on the openfusion.upstream logger.

Playground

The server hosts an interactive playground at GET /playground (and GET / redirects there). It's a React + Tailwind + shadcn UI whose built assets ship in the package (no Node needed to run); it talks only to the local /v1 API, so provider keys never reach the browser. You can:

  • paste your OpenRouter API key on first run (held only in server memory; enabled by allow_ui_api_key, on for the zero-config quick start),
  • pick a Quality / Budget / Custom panel and a "Fuse with" judge model,
  • toggle web search, send a prompt, and watch the panel → synthesis progress,
  • read the streamed answer plus the judge's structured analysis (consensus / contradictions / blind spots) and the token + cost breakdown.

The model selectors are editable when the server sets allow_request_overrides: true (on for the quick start), which enables the per-request openfusion: { preset | panel | judge | tools } field (mirroring OpenRouter Fusion's analysis_models/model plugin fields). Overrides reuse the server's upstream credentials — clients choose model ids, never keys — and stay bounded by gateway auth, cost ceilings, and rate limits. Read GET /v1/config for the active panel/judge and flags.

Developing the UI

The UI source lives in web/ (Vite + React + TypeScript + Tailwind v4 + shadcn-style components):

cd web
npm install
npm run dev      # dev server (proxy /v1 to a running openfusion on :8000)
npm run build    # writes built assets into openfusion/static/playground/ (commit them)

Troubleshooting

openfusion: command not found — the console script lives in the environment you installed it into. Either install it as a tool so it's always on PATH (uv tool install . or pipx install .), or activate the venv you used (source .venv/bin/activate). A bare pip install -e . does not put openfusion on your global PATH.

Playground says "Couldn't reach the server" — open the page at the URL the running server prints (default http://localhost:8000), not a dev-server port or a standalone file.

No upstream API key — set OPENROUTER_API_KEY, run openfusion setup, or paste your key into the playground.

Stack

Backend: Python 3.11+ / FastAPI / httpx / uvicorn. Frontend: React / Vite / Tailwind / shadcn.

Contributing

Contributions are welcome — openfusion is meant to be forked and tuned. See CONTRIBUTING.md for dev setup and the PR checklist, and CODE_OF_CONDUCT.md. Please report security issues privately per SECURITY.md rather than as a public issue.

License

MIT.