# Can Different LLMs Be Used for the Generator and Critic in ADHD? A Complete Configuration Guide

> Discover if different LLMs can be used for generator and critic in ADHD. This guide explains how to configure separate models for divergence and convergence phases, ensuring mechanical isolation.

- Repository: [Udit Akhouri/adhd](https://github.com/UditAkhourii/adhd)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Yes.** The ADHD framework explicitly supports using **different LLMs for the generator and critic** through separate `model` and `criticModel` configuration options, with full mechanical isolation between the divergence and convergence phases.

ADHD (Automatic Divergence-Harmonized Deepening) is a structured reasoning framework that separates idea generation from evaluation. This architectural split naturally extends to model selection—allowing you to optimize each phase with purpose-built models, whether that means a creative generator paired with a rigorous critic or cost-efficient tiering across phases.

## How ADHD Separates Generator and Critic at the Architecture Level

The framework implements a **hard wall** between two distinct operational phases:

- **Generator (divergence)**: Produces branching idea trees via `divergeBranch()`
- **Critic (convergence)**: Scores, clusters, and refines via `scoreIdeas()` and `clusterIdeas()`

This separation is enforced mechanically in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts). The two phases never share KV-cache, conversation history, or model weights—guaranteeing true independence even when accidentally configured with the same model identifier.

### RunOptions Configuration Interface

The type definitions in [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts) (lines 61–64) declare explicit fields for dual-model configuration:

```typescript
type RunOptions = {
  model?: string;        // LLM for all generator calls (divergence)
  criticModel?: string;  // LLM for critic calls (score + cluster)
  // ... additional options
};

```

When `criticModel` is omitted, the critic falls back to the generator model for backward compatibility.

## Engine Implementation: Model Routing Mechanics

Inside [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts), the `run()` function resolves model selection with explicit fallback logic at lines 27–30:

```typescript
const critic = criticModel ?? model;  // src/engine.ts L27-30

```

This `critic` constant is then passed exclusively to convergence-phase operations. The divergence phase receives only the base `model` argument. Examining lines 58–70 reveals the complete routing:

- `divergeBranch(problem, model, ...)` — generator phase
- `scoreIdeas(ideas, critic, ...)` — critic phase
- `clusterIdeas(scored, critic, ...)` — critic phase

Each call routes through `callLLM()` independently, ensuring **zero cross-contamination** between generator and critic contexts.

## Programmatic Usage: Configure Different LLMs in Code

Pass distinct model identifiers to `run()` for精细化 phase-specific optimization:

```typescript
import { run } from "./engine.js";

await run({
  problem: "Design a low-latency cache for a high-throughput service",
  // Generator: Anthropic Claude for creative architectural exploration
  model: "anthropic/claude-2",
  // Critic: Google Gemini for structured evaluation and clustering
  criticModel: "google/gemini-1.5-flash",
  framesPerRun: 5,
  ideasPerFrame: 6,
  topK: 3,
});

```

This configuration routes all divergence calls to Claude-2 while scoring and clustering execute on Gemini-1.5-flash—enabling you to pair models with complementary strengths.

## CLI Support: Command-Line Model Overrides

The command-line interface in [`src/cli.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/cli.ts) (lines 64–66 and 41–44) exposes the same dual-model configuration:

| Flag | Scope |
|------|-------|
| `--model NAME` | Overrides default SDK model for **both** phases |
| `--critic-model NAME` | Overrides model **only** for critic passes (score + cluster) |

Example invocation with generator-critic model split:

```bash

# Generator on Claude, critic on Groq-hosted Llama 3

adhd "Refactor the authentication layer for zero-trust" \
  --model claude-2 \
  --critic-model llama3-8b \
  --frames 6 \
  --ideas 8 \
  --top 4 \
  --json > result.json

```

The divergence phase invokes `claude-2` while scoring and clustering phases route to `llama3-8b`.

## Design Rationale: Why Separate Generator and Critic Models

The architectural documentation in [`documentation/how-it-works.md`](https://github.com/UditAkhourii/adhd/blob/main/documentation/how-it-works.md) and [`documentation/vs-cot-and-tot.md`](https://github.com/UditAkhourii/adhd/blob/main/documentation/vs-cot-and-tot.md) explains the motivations for mechanical separation:

1. **Error pattern decorrelation** — Different models exhibit distinct failure modes; separating them prevents correlated hallucinations from compounding
2. **Critic-strangulation prevention** — A dominant single model can prematurely converge; physical model separation enforces genuine multi-perspective evaluation
3. **Cost and latency optimization** — Use expensive, capable models for generation and lighter, faster models for structured scoring

This design intentionally contrasts with Chain-of-Thought and Tree-of-Thought approaches where a single model context handles both generation and evaluation.

## Supported Model Provider Patterns

The `callLLM()` abstraction (invoked identically for both phases) accepts any identifier your configured SDK recognizes. Common patterns include:

- **Same provider, different tiers**: `gpt-4` (generator) + `gpt-3.5-turbo` (critic)
- **Cross-provider specialization**: `anthropic/claude-3-opus` (generator) + `openai/gpt-4-turbo` (critic)
- **Local + cloud hybrid**: `ollama/llama2-70b` (generator) + `groq/llama3-70b` (critic)

The framework imposes no restrictions on provider mixing—only that both models are accessible through your runtime environment's LLM SDK configuration.

## Summary

- **Yes, different LLMs work**: ADHD's architecture mechanically separates generator and critic phases through independent `model` and `criticModel` parameters
- **Configure in code**: Pass `model` and `criticModel` to `run()` in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts)
- **Configure via CLI**: Use `--model` and `--critic-model` flags parsed in [`src/cli.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/cli.ts)
- **Mechanical guarantee**: Phases invoke `callLLM()` separately with no shared state
- **Design benefit**: Separating models decorrelates errors and prevents premature convergence

## Frequently Asked Questions

### What happens if I only specify `model` and omit `criticModel`?

The critic falls back to the generator model using nullish coalescing (`criticModel ?? model` at `src/engine.ts:27`). This ensures backward compatibility while preserving the option for separation.

### Can I use the same model provider with different temperature settings for each phase?

Not directly through `RunOptions`. The current interface accepts model identifiers only. Temperature and other inference parameters are controlled at the SDK level. For phase-specific sampling, you would need to wrap `callLLM()` or use provider-specific model aliases with preset configurations.

### Does using different models increase API costs?

Potentially, depending on your pricing structure. However, the framework enables **cost reduction strategies**: use an expensive, capable model for generation (where quality matters most) and a cheaper, faster model for scoring and clustering (which are more structured tasks). The [`documentation/vs-cot-and-tot.md`](https://github.com/UditAkhourii/adhd/blob/main/documentation/vs-cot-and-tot.md) analysis discusses this tradeoff explicitly.

### Are there any constraints on which models work together?

No hard constraints exist in the codebase. The abstraction layer in `callLLM()` treats all model identifiers uniformly. Practical constraints depend on your SDK configuration: both models must be routable through your provider setup, and output formats must be parseable by the downstream `scoreIdeas()` and `clusterIdeas()` functions (which expect specific JSON schemas).