# Model Router

> App prompts converging on a router that picks a model for each one, then fanning out to a card of models, each with what it is picked for, its prompts, its share of traffic, and its average response time, counting up as pulses arrive.

Source: https://ui.cortexcn.dev/docs/cortex/model-router

## Installation

```bash
npx shadcn@latest add @cortexcn/model-router
```

## Usage

```tsx
import { ModelRouter } from "@/components/model-router";
```

```tsx
<ModelRouter
  title="Traffic by model"
  models={[
    { name: "Brisk 3", role: "Short answers", prompts: 18420, latencyMs: 340 },
    { name: "Sage 2", role: "Reasoning", prompts: 6910, latencyMs: 1840 },
    { name: "Prism", role: "Images and files", prompts: 2270, latencyMs: 920 },
  ]}
/>
```

Each model gets a row: its name, what the router picks it for, the prompts sent to it, and its average response time, with a bar showing its share of all prompts. Use it on the page for an AI product that routes between models, or to explain cost and speed tradeoffs in a model gateway.

## Examples

### Support routing

Four models for a support desk, with the source relabeled.

### Static

With `animated={false}`, nothing moves and the numbers stay as given.

## Behavior

- While the flow is on screen, pulses run from the left into the router, then on to each model. The prompt counts count up from zero, then each model adds its `perPulse` every time a pulse reaches it, and the shares follow the new counts.
- The count under the source label goes up as pulses reach the router.
- With reduced motion enabled, or off screen, nothing moves and every number shows its given value.
- The whole flow is one SVG that scales to its container. It lays out at `minWidth` or wider (560px by default); in a narrower container it scrolls sideways and takes keyboard focus.
- Screen readers hear one summary: each model, what it is for, its prompts, its share, and its average response time.
- The model names are made up, and the caption in the corner says the numbers are illustrative. Use your own models and numbers.

## Props

### ModelRouter

| Prop            | Type                 | Default                                  | Description                                         |
| --------------- | -------------------- | ---------------------------------------- | --------------------------------------------------- |
| `models`        | `ModelRouterModel[]` | Three sample models                      | The models the router picks between                 |
| `title`         | `string`             | `"Traffic by model"`                     | The card's title                                    |
| `routerName`    | `string`             | `"Router"`                               | The name in the middle node                         |
| `routerCaption` | `string`             | `"Picks a model for every prompt"`       | A line under the middle node                        |
| `sourceLabel`   | `string`             | `"App prompts"`                          | The label over the incoming lines                   |
| `promptsLabel`  | `string`             | `"prompts today"`                        | The words after the count under the source label    |
| `apiLabel`      | `string`             | `"Routing rules"`                        | The label on the lines into the card                |
| `note`          | `string`             | `"Hard prompts get the reasoning model."` | A note at the foot of the card                     |
| `caption`       | `string`             | `"Illustrative numbers"`                 | A small label in the bottom-left corner             |
| `locale`        | `string`             | `"en-US"`                                | The locale numbers are written in                   |
| `lines`         | `number`             | `22`                                     | How many lines of traffic come in from the left     |
| `segments`      | `number`             | `24`                                     | How many segments each share bar has                |
| `accent`        | `string`             | `"var(--foreground)"`                    | Color of the pulses, markers, and share segments    |
| `animated`      | `boolean`            | `true`                                   | Run the pulses and count up while on screen         |
| `minWidth`      | `number`             | `560`                                    | Narrowest layout width in pixels; below it, scroll  |
| `ariaLabel`     | `string`             | `"Model router"`                         | Names the flow for screen readers                   |
| `className`     | `string`             | -                                        | Extra classes on the frame                          |

### ModelRouterModel

| Prop        | Type     | Default | Description                                            |
| ----------- | -------- | ------- | ------------------------------------------------------ |
| `name`      | `string` | -       | The model's name                                       |
| `role`      | `string` | -       | What it is picked for, such as `"Reasoning"`           |
| `prompts`   | `number` | -       | Prompts routed to it so far                            |
| `latencyMs` | `number` | -       | Its average response time, in milliseconds             |
| `perPulse`  | `number` | `2`     | Prompts added each time a pulse reaches it while live  |