Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions backend/app/alembic/versions/064_completion_type_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""completion_type scalar to array

Revision ID: 064
Revises: 063
Create Date: 2026-05-26 00:00:00.000000

"""

from alembic import op

revision = "064"
down_revision = "063"
branch_labels = None
depends_on = None


def upgrade():
# Drop scalar index before altering column
op.execute("DROP INDEX IF EXISTS global.ix_model_config_provider_type_active")

# Convert scalar enum to array, wrapping existing values
op.execute(
"""
ALTER TABLE global.model_config
ALTER COLUMN completion_type TYPE global.completion_type_enum[]
USING ARRAY[completion_type]
"""
)

# GIN index for efficient array containment queries
op.execute(
"CREATE INDEX ix_model_config_completion_type ON global.model_config USING gin (completion_type)"
)


def downgrade():
op.execute("DROP INDEX IF EXISTS global.ix_model_config_completion_type")

op.execute(
"""
ALTER TABLE global.model_config
ALTER COLUMN completion_type TYPE global.completion_type_enum
USING completion_type[1]
"""
)

op.execute(
"CREATE INDEX ix_model_config_provider_type_active ON global.model_config (provider, completion_type, is_active)"
)
53 changes: 53 additions & 0 deletions backend/app/api/docs/model_config/create_models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Create one or more model configurations.

Accepts a single object or an array. Response is always an array.

**Required:** `provider`, `model_name`, `completion_type`, `config`
**Optional:** `input_modalities`, `output_modalities`, `pricing`, `is_active`

`(provider, model_name)` must be unique.

### Example (single)

```json
{
"provider": "google",
"model_name": "gemini-2.5-flash",
"completion_type": ["text", "stt"],
"config": { "temperature": { "type": "float", "default": 1.0, "min": 0.0, "max": 2.0 } },
"input_modalities": ["TEXT", "AUDIO"],
"output_modalities": ["TEXT"],
"pricing": {
"response": { "input_token_cost": 0.3, "output_token_cost": 2.5 }
},
"is_active": true
}
```

### Example (multiple)

```json
[
{
"provider": "sarvamai",
"model_name": "saaras:v3",
"completion_type": ["stt"],
"config": {},
"input_modalities": ["AUDIO"],
"output_modalities": ["TEXT"]
},
{
"provider": "elevenlabs",
"model_name": "scribe_v2",
"completion_type": ["stt"],
"config": {},
"input_modalities": ["AUDIO"],
"output_modalities": ["TEXT"]
}
]
```

### Errors

- `422` — Validation error.
- DB integrity error on duplicate `(provider, model_name)`.
7 changes: 7 additions & 0 deletions backend/app/api/docs/model_config/delete_model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Permanently delete a model configuration. Hard delete — cannot be undone.

To hide a model instead, use `PATCH` with `is_active: false`.

### Errors

- `404` — Model not found.
68 changes: 3 additions & 65 deletions backend/app/api/docs/model_config/get_model.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,5 @@
## Endpoint
Get a single model configuration by `provider` and `model_name`.

**GET** `/api/v1/models/{provider}/{model_name}`
### Errors

Retrieve a specific model configuration by provider and model name.

Returns model details including supported config parameters, input/output modalities, pricing, and active status.

### Path Parameters

- **`provider`** (required) — Provider name (e.g. `openai`, `google`)
- **`model_name`** (required) — Model name (e.g. `gpt-4o`, `gpt-4o-mini`)

### Example Response

```json
{
"success": true,
"data": {
"id": 2,
"provider": "openai",
"model_name": "gpt-4o",
"config": {
"temperature": {
"type": "float",
"default": 1.0,
"min": 0.0,
"max": 2.0,
"description": "Controls randomness. Lower = more deterministic."
},
"top_p": {
"type": "float",
"default": 1.0,
"min": 0.0,
"max": 1.0,
"description": "Nucleus sampling. Use either this or temperature, not both."
},
"max_output_tokens": {
"type": "int",
"default": 2048,
"min": 1,
"max": 32768,
"description": "Max tokens in the response."
}
},
"input_modalities": ["TEXT", "IMAGE"],
"output_modalities": ["TEXT"],
"pricing": {
"response": {
"input_token_cost": 2.5,
"output_token_cost": 10
},
"batch": {
"input_token_cost": 1.25,
"output_token_cost": 5
}
},
"is_active": true,
"inserted_at": "2026-03-12T00:00:00",
"updated_at": "2026-03-12T00:00:00"
}
}
```

### Error Response

- `404 Not Found` — Model not found for the given `provider` and `model_name`.
- `404` — Model not found.
75 changes: 2 additions & 73 deletions backend/app/api/docs/model_config/list_models.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,3 @@
## Endpoint
List active model configurations.

**GET** `/api/v1/models`

Retrieve a list of all active model configurations.

Returns model details including provider, model name, supported config parameters, input/output modalities, pricing, and active status.

Optionally filter by provider (e.g. openai, google).

### Query Parameters

- **`provider`** (optional) — Filter by provider name (e.g. `openai`, `google`)
- **`skip`** (optional, default 0) — Number of records to skip for pagination
- **`limit`** (optional, default 100, max 100) — Maximum number of records to return

### Example Response

```json
{
"success": true,
"metadata": {
"has_more": true
},
"data": {
"data": [
{
"id": 1,
"provider": "openai",
"model_name": "gpt-4o-mini",
"config": {
"temperature": {
"type": "float",
"default": 1.0,
"min": 0.0,
"max": 2.0,
"description": "Controls randomness. Lower = more deterministic."
},
"top_p": {
"type": "float",
"default": 1.0,
"min": 0.0,
"max": 1.0,
"description": "Nucleus sampling. Use either this or temperature, not both."
},
"max_output_tokens": {
"type": "int",
"default": 2048,
"min": 1,
"max": 32768,
"description": "Max tokens in the response."
}
},
"input_modalities": ["TEXT", "IMAGE"],
"output_modalities": ["TEXT"],
"pricing": {
"response": {
"input_token_cost": 0.15,
"output_token_cost": 0.6
},
"batch": {
"input_token_cost": 0.075,
"output_token_cost": 0.3
}
},
"is_active": true,
"inserted_at": "2026-03-12T00:00:00",
"updated_at": "2026-03-12T00:00:00"
}
],
"count": 1
}
}
```
Filter by `provider` (`openai` | `google` | `sarvamai` | `elevenlabs`). Paginate with `skip` / `limit` (max 100). Only active models returned, sorted by `provider`, `model_name`. `metadata.has_more` flags more records.
53 changes: 3 additions & 50 deletions backend/app/api/docs/model_config/list_models_grouped.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,5 @@
## Endpoint
List active models grouped by provider.

**GET** `/api/v1/models/grouped`
Returns a dict keyed by provider; each value is the list of that provider's active models.

Retrieve active models grouped by provider.

Supports pagination of model rows before grouping:
- `skip` (default `0`)
- `limit` (default `100`, max `100`)

Returns a dictionary where each key is a provider present in the paginated slice, and each value is a list of active model configurations for that provider.
Includes `metadata.has_more` when additional model rows exist.

### Example Response

```json
{
"success": true,
"metadata": {
"has_more": true
},
"data": {
"openai": [
{
"id": 2,
"provider": "openai",
"model_name": "gpt-4o",
"config": {
"temperature": {
"type": "float",
"default": 1.0,
"min": 0.0,
"max": 2.0,
"description": "Controls randomness. Lower = more deterministic."
}
},
"input_modalities": ["TEXT", "IMAGE"],
"output_modalities": ["TEXT"],
"pricing": {
"response": {
"input_token_cost": 2.5,
"output_token_cost": 10
}
},
"is_active": true,
"inserted_at": "2026-03-12T00:00:00",
"updated_at": "2026-03-12T00:00:00"
}
]
}
}
```
Pagination (`skip` / `limit`) is applied **before** grouping — adjust `limit` if expecting many models per provider.
17 changes: 1 addition & 16 deletions backend/app/api/docs/model_config/list_providers.md
Original file line number Diff line number Diff line change
@@ -1,16 +1 @@
## Endpoint

**GET** `/api/v1/models/providers`

Retrieve the list of providers that currently have active models.

Returns provider names sorted in ascending order.

### Example Response

```json
{
"success": true,
"data": ["google", "openai"]
}
```
List provider names that have at least one active model. Sorted ascending.
21 changes: 21 additions & 0 deletions backend/app/api/docs/model_config/update_model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Partially update a model configuration. Only fields sent are updated; omitted fields stay unchanged.

**Updatable fields:** `completion_type`, `config`, `input_modalities`, `output_modalities`, `pricing`, `is_active`

Arrays and objects are **replaced** (no deep merge). `provider` and `model_name` cannot be changed here.

### Example

```json
{
"completion_type": ["text", "stt"],
"pricing": {
"response": { "input_token_cost": 0.5, "output_token_cost": 3.0 }
}
}
```

### Errors

- `404` — Model not found.
- `422` — Validation error.
19 changes: 19 additions & 0 deletions backend/app/api/docs/model_config/update_models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Update multiple model configurations in one request.

Each item must include `provider` + `model_name` to identify the target. Other fields are optional and follow the same rules as the single PATCH endpoint (replace semantics, no deep merge).

Atomic — if any target is missing, no updates are applied.

### Example

```json
[
{ "provider": "google", "model_name": "gemini-2.5-flash", "completion_type": ["text", "stt"] },
{ "provider": "sarvamai", "model_name": "saaras:v3", "is_active": false }
]
```

### Errors

- `404` — One or more targets not found.
- `422` — Validation error.
Loading