mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
Compare commits
20 Commits
dev
...
feat/llm-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e15213846 | ||
|
|
f0cc4ae573 | ||
|
|
e0282b00db | ||
|
|
9a9c36b806 | ||
|
|
d5381625cd | ||
|
|
f6ae3d6593 | ||
|
|
0fb1b854df | ||
|
|
64a011664a | ||
|
|
1db7c048d9 | ||
|
|
4c5627c966 | ||
|
|
d97d137a51 | ||
|
|
ded9e293ff | ||
|
|
83d504bed2 | ||
|
|
a5f1ffb35b | ||
|
|
97c6516a14 | ||
|
|
876dde8bc7 | ||
|
|
0bfdd74b25 | ||
|
|
a7d2f81b18 | ||
|
|
3699eaa556 | ||
|
|
21adf9e0fb |
@@ -36,7 +36,7 @@ from backend.util.models import Pagination
|
|||||||
from backend.util.request import parse_url
|
from backend.util.request import parse_url
|
||||||
|
|
||||||
from .block import BlockInput
|
from .block import BlockInput
|
||||||
from .db import BaseDbModel
|
from .db import BaseDbModel, execute_raw_with_schema
|
||||||
from .db import prisma as db
|
from .db import prisma as db
|
||||||
from .db import query_raw_with_schema, transaction
|
from .db import query_raw_with_schema, transaction
|
||||||
from .dynamic_fields import is_tool_pin, sanitize_pin_name
|
from .dynamic_fields import is_tool_pin, sanitize_pin_name
|
||||||
@@ -1670,15 +1670,15 @@ async def migrate_llm_models(migrate_to: LlmModel):
|
|||||||
# Update each block
|
# Update each block
|
||||||
for id, path in llm_model_fields.items():
|
for id, path in llm_model_fields.items():
|
||||||
query = f"""
|
query = f"""
|
||||||
UPDATE platform."AgentNode"
|
UPDATE {{schema_prefix}}"AgentNode"
|
||||||
SET "constantInput" = jsonb_set("constantInput", $1, to_jsonb($2), true)
|
SET "constantInput" = jsonb_set("constantInput", $1, to_jsonb($2), true)
|
||||||
WHERE "agentBlockId" = $3
|
WHERE "agentBlockId" = $3
|
||||||
AND "constantInput" ? ($4)::text
|
AND "constantInput" ? ($4)::text
|
||||||
AND "constantInput"->>($4)::text NOT IN {escaped_enum_values}
|
AND "constantInput"->>($4)::text NOT IN {escaped_enum_values}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
await db.execute_raw(
|
await execute_raw_with_schema(
|
||||||
query, # type: ignore - is supposed to be LiteralString
|
query,
|
||||||
[path],
|
[path],
|
||||||
migrate_to.value,
|
migrate_to.value,
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "LlmCostUnit" AS ENUM ('RUN', 'TOKENS');
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LlmProvider" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"displayName" TEXT NOT NULL,
|
||||||
|
"description" TEXT,
|
||||||
|
"defaultCredentialProvider" TEXT,
|
||||||
|
"defaultCredentialId" TEXT,
|
||||||
|
"defaultCredentialType" TEXT,
|
||||||
|
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||||
|
|
||||||
|
CONSTRAINT "LlmProvider_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LlmModelCreator" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
"displayName" TEXT NOT NULL,
|
||||||
|
"description" TEXT,
|
||||||
|
"websiteUrl" TEXT,
|
||||||
|
"logoUrl" TEXT,
|
||||||
|
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||||
|
|
||||||
|
CONSTRAINT "LlmModelCreator_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LlmModel" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
"slug" TEXT NOT NULL,
|
||||||
|
"displayName" TEXT NOT NULL,
|
||||||
|
"description" TEXT,
|
||||||
|
"providerId" TEXT NOT NULL,
|
||||||
|
"creatorId" TEXT,
|
||||||
|
"contextWindow" INTEGER NOT NULL,
|
||||||
|
"maxOutputTokens" INTEGER,
|
||||||
|
"priceTier" INTEGER NOT NULL DEFAULT 1,
|
||||||
|
"isEnabled" BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
"isRecommended" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"supportsTools" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"supportsJsonOutput" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"supportsReasoning" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"supportsParallelToolCalls" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"capabilities" JSONB NOT NULL DEFAULT '{}',
|
||||||
|
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||||
|
|
||||||
|
CONSTRAINT "LlmModel_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LlmModelCost" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
"unit" "LlmCostUnit" NOT NULL DEFAULT 'RUN',
|
||||||
|
"creditCost" INTEGER NOT NULL,
|
||||||
|
"credentialProvider" TEXT NOT NULL,
|
||||||
|
"credentialId" TEXT,
|
||||||
|
"credentialType" TEXT,
|
||||||
|
"currency" TEXT,
|
||||||
|
"metadata" JSONB NOT NULL DEFAULT '{}',
|
||||||
|
"llmModelId" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "LlmModelCost_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "LlmModelMigration" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
"sourceModelSlug" TEXT NOT NULL,
|
||||||
|
"targetModelSlug" TEXT NOT NULL,
|
||||||
|
"reason" TEXT,
|
||||||
|
"migratedNodeIds" JSONB NOT NULL DEFAULT '[]',
|
||||||
|
"nodeCount" INTEGER NOT NULL,
|
||||||
|
"customCreditCost" INTEGER,
|
||||||
|
"isReverted" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
"revertedAt" TIMESTAMP(3),
|
||||||
|
|
||||||
|
CONSTRAINT "LlmModelMigration_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "LlmProvider_name_key" ON "LlmProvider"("name");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "LlmModelCreator_name_key" ON "LlmModelCreator"("name");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "LlmModel_slug_key" ON "LlmModel"("slug");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LlmModel_providerId_isEnabled_idx" ON "LlmModel"("providerId", "isEnabled");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LlmModel_creatorId_idx" ON "LlmModel"("creatorId");
|
||||||
|
|
||||||
|
-- CreateIndex (partial unique for default costs - no specific credential)
|
||||||
|
CREATE UNIQUE INDEX "LlmModelCost_default_cost_key" ON "LlmModelCost"("llmModelId", "credentialProvider", "unit") WHERE "credentialId" IS NULL;
|
||||||
|
|
||||||
|
-- CreateIndex (partial unique for credential-specific costs)
|
||||||
|
CREATE UNIQUE INDEX "LlmModelCost_credential_cost_key" ON "LlmModelCost"("llmModelId", "credentialProvider", "credentialId", "unit") WHERE "credentialId" IS NOT NULL;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LlmModelMigration_targetModelSlug_idx" ON "LlmModelMigration"("targetModelSlug");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "LlmModelMigration_sourceModelSlug_isReverted_idx" ON "LlmModelMigration"("sourceModelSlug", "isReverted");
|
||||||
|
|
||||||
|
-- CreateIndex (partial unique to prevent multiple active migrations per source)
|
||||||
|
CREATE UNIQUE INDEX "LlmModelMigration_active_source_key" ON "LlmModelMigration"("sourceModelSlug") WHERE "isReverted" = false;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LlmModel" ADD CONSTRAINT "LlmModel_providerId_fkey" FOREIGN KEY ("providerId") REFERENCES "LlmProvider"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LlmModel" ADD CONSTRAINT "LlmModel_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "LlmModelCreator"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LlmModelCost" ADD CONSTRAINT "LlmModelCost_llmModelId_fkey" FOREIGN KEY ("llmModelId") REFERENCES "LlmModel"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LlmModelMigration" ADD CONSTRAINT "LlmModelMigration_sourceModelSlug_fkey" FOREIGN KEY ("sourceModelSlug") REFERENCES "LlmModel"("slug") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "LlmModelMigration" ADD CONSTRAINT "LlmModelMigration_targetModelSlug_fkey" FOREIGN KEY ("targetModelSlug") REFERENCES "LlmModel"("slug") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddCheckConstraints (enforce data integrity)
|
||||||
|
ALTER TABLE "LlmModel"
|
||||||
|
ADD CONSTRAINT "LlmModel_priceTier_check" CHECK ("priceTier" BETWEEN 1 AND 3);
|
||||||
|
|
||||||
|
ALTER TABLE "LlmModelCost"
|
||||||
|
ADD CONSTRAINT "LlmModelCost_creditCost_check" CHECK ("creditCost" >= 0);
|
||||||
|
|
||||||
|
ALTER TABLE "LlmModelMigration"
|
||||||
|
ADD CONSTRAINT "LlmModelMigration_nodeCount_check" CHECK ("nodeCount" >= 0),
|
||||||
|
ADD CONSTRAINT "LlmModelMigration_customCreditCost_check" CHECK ("customCreditCost" IS NULL OR "customCreditCost" >= 0);
|
||||||
@@ -0,0 +1,287 @@
|
|||||||
|
-- Seed LLM Registry from existing hard-coded data
|
||||||
|
-- This migration populates the LlmProvider, LlmModelCreator, LlmModel, and LlmModelCost tables
|
||||||
|
-- with data from the existing MODEL_METADATA and MODEL_COST dictionaries
|
||||||
|
|
||||||
|
-- Insert Providers
|
||||||
|
INSERT INTO "LlmProvider" ("id", "createdAt", "updatedAt", "name", "displayName", "description", "defaultCredentialProvider", "defaultCredentialType", "metadata")
|
||||||
|
VALUES
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'openai', 'OpenAI', 'OpenAI language models', 'openai', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'anthropic', 'Anthropic', 'Anthropic Claude models', 'anthropic', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'groq', 'Groq', 'Groq inference API', 'groq', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'open_router', 'OpenRouter', 'OpenRouter unified API', 'open_router', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'aiml_api', 'AI/ML API', 'AI/ML API models', 'aiml_api', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'ollama', 'Ollama', 'Ollama local models', 'ollama', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'llama_api', 'Llama API', 'Llama API models', 'llama_api', 'api_key', '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'v0', 'v0', 'v0 by Vercel models', 'v0', 'api_key', '{}'::jsonb)
|
||||||
|
ON CONFLICT ("name") DO NOTHING;
|
||||||
|
|
||||||
|
-- Insert Model Creators
|
||||||
|
INSERT INTO "LlmModelCreator" ("id", "createdAt", "updatedAt", "name", "displayName", "description", "websiteUrl", "logoUrl", "metadata")
|
||||||
|
VALUES
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'openai', 'OpenAI', 'Creator of GPT, O1, O3, and DALL-E models', 'https://openai.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'anthropic', 'Anthropic', 'Creator of Claude AI models', 'https://anthropic.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'meta', 'Meta', 'Creator of Llama foundation models', 'https://llama.meta.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'google', 'Google', 'Creator of Gemini and PaLM models', 'https://deepmind.google', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'mistralai', 'Mistral AI', 'Creator of Mistral and Codestral models', 'https://mistral.ai', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'cohere', 'Cohere', 'Creator of Command language models', 'https://cohere.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'deepseek', 'DeepSeek', 'Creator of DeepSeek reasoning models', 'https://deepseek.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'alibaba', 'Alibaba', 'Creator of Qwen language models', 'https://qwenlm.github.io', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'nvidia', 'NVIDIA', 'Creator of Nemotron models', 'https://nvidia.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'vercel', 'Vercel', 'Creator of v0 AI models', 'https://v0.dev', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'microsoft', 'Microsoft', 'Creator of Phi models', 'https://microsoft.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'xai', 'xAI', 'Creator of Grok models', 'https://x.ai', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'perplexity', 'Perplexity AI', 'Creator of Sonar search models', 'https://perplexity.ai', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'nousresearch', 'Nous Research', 'Creator of Hermes language models', 'https://nousresearch.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'amazon', 'Amazon', 'Creator of Nova language models', 'https://aws.amazon.com', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'gryphe', 'Gryphe', 'Creator of MythoMax models', 'https://huggingface.co/Gryphe', NULL, '{}'::jsonb),
|
||||||
|
(gen_random_uuid(), CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'moonshotai', 'Moonshot AI', 'Creator of Kimi language models', 'https://moonshot.ai', NULL, '{}'::jsonb)
|
||||||
|
ON CONFLICT ("name") DO NOTHING;
|
||||||
|
|
||||||
|
-- Insert Models (using CTEs to reference provider and creator IDs)
|
||||||
|
WITH provider_ids AS (
|
||||||
|
SELECT "id", "name" FROM "LlmProvider"
|
||||||
|
),
|
||||||
|
creator_ids AS (
|
||||||
|
SELECT "id", "name" FROM "LlmModelCreator"
|
||||||
|
)
|
||||||
|
INSERT INTO "LlmModel" ("id", "createdAt", "updatedAt", "slug", "displayName", "description", "providerId", "creatorId", "contextWindow", "maxOutputTokens", "isEnabled", "capabilities", "metadata")
|
||||||
|
SELECT
|
||||||
|
gen_random_uuid(),
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
model_slug,
|
||||||
|
model_display_name,
|
||||||
|
NULL,
|
||||||
|
p."id",
|
||||||
|
c."id",
|
||||||
|
context_window,
|
||||||
|
max_output_tokens,
|
||||||
|
true,
|
||||||
|
'{}'::jsonb,
|
||||||
|
'{}'::jsonb
|
||||||
|
FROM (VALUES
|
||||||
|
-- OpenAI models (creator: openai)
|
||||||
|
('o3-2025-04-16', 'O3', 'openai', 'openai', 200000, 100000),
|
||||||
|
('o3-mini', 'O3 Mini', 'openai', 'openai', 200000, 100000),
|
||||||
|
('o1', 'O1', 'openai', 'openai', 200000, 100000),
|
||||||
|
('o1-mini', 'O1 Mini', 'openai', 'openai', 128000, 65536),
|
||||||
|
('gpt-5.2-2025-12-11', 'GPT-5.2', 'openai', 'openai', 400000, 128000),
|
||||||
|
('gpt-5-2025-08-07', 'GPT 5', 'openai', 'openai', 400000, 128000),
|
||||||
|
('gpt-5.1-2025-11-13', 'GPT 5.1', 'openai', 'openai', 400000, 128000),
|
||||||
|
('gpt-5-mini-2025-08-07', 'GPT 5 Mini', 'openai', 'openai', 400000, 128000),
|
||||||
|
('gpt-5-nano-2025-08-07', 'GPT 5 Nano', 'openai', 'openai', 400000, 128000),
|
||||||
|
('gpt-5-chat-latest', 'GPT 5 Chat', 'openai', 'openai', 400000, 16384),
|
||||||
|
('gpt-4.1-2025-04-14', 'GPT 4.1', 'openai', 'openai', 1000000, 32768),
|
||||||
|
('gpt-4.1-mini-2025-04-14', 'GPT 4.1 Mini', 'openai', 'openai', 1047576, 32768),
|
||||||
|
('gpt-4o-mini', 'GPT 4o Mini', 'openai', 'openai', 128000, 16384),
|
||||||
|
('gpt-4o', 'GPT 4o', 'openai', 'openai', 128000, 16384),
|
||||||
|
('gpt-4-turbo', 'GPT 4 Turbo', 'openai', 'openai', 128000, 4096),
|
||||||
|
-- Anthropic models (creator: anthropic)
|
||||||
|
('claude-opus-4-6', 'Claude Opus 4.6', 'anthropic', 'anthropic', 200000, 128000),
|
||||||
|
('claude-sonnet-4-6', 'Claude Sonnet 4.6', 'anthropic', 'anthropic', 200000, 64000),
|
||||||
|
('claude-opus-4-1-20250805', 'Claude 4.1 Opus', 'anthropic', 'anthropic', 200000, 32000),
|
||||||
|
('claude-opus-4-20250514', 'Claude 4 Opus', 'anthropic', 'anthropic', 200000, 32000),
|
||||||
|
('claude-sonnet-4-20250514', 'Claude 4 Sonnet', 'anthropic', 'anthropic', 200000, 64000),
|
||||||
|
('claude-opus-4-5-20251101', 'Claude 4.5 Opus', 'anthropic', 'anthropic', 200000, 64000),
|
||||||
|
('claude-sonnet-4-5-20250929', 'Claude 4.5 Sonnet', 'anthropic', 'anthropic', 200000, 64000),
|
||||||
|
('claude-haiku-4-5-20251001', 'Claude 4.5 Haiku', 'anthropic', 'anthropic', 200000, 64000),
|
||||||
|
('claude-3-haiku-20240307', 'Claude 3 Haiku', 'anthropic', 'anthropic', 200000, 4096),
|
||||||
|
-- AI/ML API models (creators: alibaba, nvidia, meta)
|
||||||
|
('Qwen/Qwen2.5-72B-Instruct-Turbo', 'Qwen 2.5 72B', 'aiml_api', 'alibaba', 32000, 8000),
|
||||||
|
('nvidia/llama-3.1-nemotron-70b-instruct', 'Llama 3.1 Nemotron 70B', 'aiml_api', 'nvidia', 128000, 40000),
|
||||||
|
('meta-llama/Llama-3.3-70B-Instruct-Turbo', 'Llama 3.3 70B', 'aiml_api', 'meta', 128000, NULL),
|
||||||
|
('meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo', 'Meta Llama 3.1 70B', 'aiml_api', 'meta', 131000, 2000),
|
||||||
|
('meta-llama/Llama-3.2-3B-Instruct-Turbo', 'Llama 3.2 3B', 'aiml_api', 'meta', 128000, NULL),
|
||||||
|
-- Groq models (creator: meta for Llama)
|
||||||
|
('llama-3.3-70b-versatile', 'Llama 3.3 70B', 'groq', 'meta', 128000, 32768),
|
||||||
|
('llama-3.1-8b-instant', 'Llama 3.1 8B', 'groq', 'meta', 128000, 8192),
|
||||||
|
-- Ollama models (creators: meta for Llama, mistralai for Mistral)
|
||||||
|
('llama3.3', 'Llama 3.3', 'ollama', 'meta', 8192, NULL),
|
||||||
|
('llama3.2', 'Llama 3.2', 'ollama', 'meta', 8192, NULL),
|
||||||
|
('llama3', 'Llama 3', 'ollama', 'meta', 8192, NULL),
|
||||||
|
('llama3.1:405b', 'Llama 3.1 405B', 'ollama', 'meta', 8192, NULL),
|
||||||
|
('dolphin-mistral:latest', 'Dolphin Mistral', 'ollama', 'mistralai', 32768, NULL),
|
||||||
|
-- OpenRouter models (creators: google, mistralai, cohere, deepseek, perplexity, nousresearch, openai, amazon, microsoft, gryphe, meta, xai, moonshotai, alibaba)
|
||||||
|
('google/gemini-2.5-pro-preview-03-25', 'Gemini 2.5 Pro', 'open_router', 'google', 1050000, 8192),
|
||||||
|
('google/gemini-2.5-pro', 'Gemini 2.5 Pro', 'open_router', 'google', 1048576, 65536),
|
||||||
|
('google/gemini-3.1-pro-preview', 'Gemini 3.1 Pro Preview', 'open_router', 'google', 1048576, 65536),
|
||||||
|
('google/gemini-3-flash-preview', 'Gemini 3 Flash Preview', 'open_router', 'google', 1048576, 65536),
|
||||||
|
('google/gemini-2.5-flash', 'Gemini 2.5 Flash', 'open_router', 'google', 1048576, 65535),
|
||||||
|
('google/gemini-2.0-flash-001', 'Gemini 2.0 Flash', 'open_router', 'google', 1048576, 8192),
|
||||||
|
('google/gemini-3.1-flash-lite-preview', 'Gemini 3.1 Flash Lite Preview', 'open_router', 'google', 1048576, 65536),
|
||||||
|
('google/gemini-2.5-flash-lite-preview-06-17', 'Gemini 2.5 Flash Lite Preview', 'open_router', 'google', 1048576, 65535),
|
||||||
|
('google/gemini-2.0-flash-lite-001', 'Gemini 2.0 Flash Lite', 'open_router', 'google', 1048576, 8192),
|
||||||
|
('mistralai/mistral-nemo', 'Mistral Nemo', 'open_router', 'mistralai', 128000, 4096),
|
||||||
|
('mistralai/mistral-large-2512', 'Mistral Large 3 2512', 'open_router', 'mistralai', 262144, NULL),
|
||||||
|
('mistralai/mistral-medium-3.1', 'Mistral Medium 3.1', 'open_router', 'mistralai', 131072, NULL),
|
||||||
|
('mistralai/mistral-small-3.2-24b-instruct', 'Mistral Small 3.2 24B', 'open_router', 'mistralai', 131072, 131072),
|
||||||
|
('mistralai/codestral-2508', 'Codestral 2508', 'open_router', 'mistralai', 256000, NULL),
|
||||||
|
('cohere/command-r-08-2024', 'Command R', 'open_router', 'cohere', 128000, 4096),
|
||||||
|
('cohere/command-r-plus-08-2024', 'Command R Plus', 'open_router', 'cohere', 128000, 4096),
|
||||||
|
('cohere/command-a-03-2025', 'Command A 03.2025', 'open_router', 'cohere', 256000, 8192),
|
||||||
|
('cohere/command-a-reasoning-08-2025', 'Command A Reasoning 08.2025', 'open_router', 'cohere', 256000, 32768),
|
||||||
|
('cohere/command-a-translate-08-2025', 'Command A Translate 08.2025', 'open_router', 'cohere', 128000, 8192),
|
||||||
|
('cohere/command-a-vision-07-2025', 'Command A Vision 07.2025', 'open_router', 'cohere', 128000, 8192),
|
||||||
|
('deepseek/deepseek-chat', 'DeepSeek Chat', 'open_router', 'deepseek', 64000, 2048),
|
||||||
|
('deepseek/deepseek-r1-0528', 'DeepSeek R1', 'open_router', 'deepseek', 163840, 163840),
|
||||||
|
('perplexity/sonar', 'Perplexity Sonar', 'open_router', 'perplexity', 127000, 8000),
|
||||||
|
('perplexity/sonar-pro', 'Perplexity Sonar Pro', 'open_router', 'perplexity', 200000, 8000),
|
||||||
|
('perplexity/sonar-deep-research', 'Perplexity Sonar Deep Research', 'open_router', 'perplexity', 128000, 16000),
|
||||||
|
('perplexity/sonar-reasoning-pro', 'Sonar Reasoning Pro', 'open_router', 'perplexity', 128000, 8000),
|
||||||
|
('nousresearch/hermes-3-llama-3.1-405b', 'Hermes 3 Llama 3.1 405B', 'open_router', 'nousresearch', 131000, 4096),
|
||||||
|
('nousresearch/hermes-3-llama-3.1-70b', 'Hermes 3 Llama 3.1 70B', 'open_router', 'nousresearch', 12288, 12288),
|
||||||
|
('openai/gpt-oss-120b', 'GPT OSS 120B', 'open_router', 'openai', 131072, 131072),
|
||||||
|
('openai/gpt-oss-20b', 'GPT OSS 20B', 'open_router', 'openai', 131072, 32768),
|
||||||
|
('amazon/nova-lite-v1', 'Amazon Nova Lite', 'open_router', 'amazon', 300000, 5120),
|
||||||
|
('amazon/nova-micro-v1', 'Amazon Nova Micro', 'open_router', 'amazon', 128000, 5120),
|
||||||
|
('amazon/nova-pro-v1', 'Amazon Nova Pro', 'open_router', 'amazon', 300000, 5120),
|
||||||
|
('microsoft/wizardlm-2-8x22b', 'WizardLM 2 8x22B', 'open_router', 'microsoft', 65536, 4096),
|
||||||
|
('microsoft/phi-4', 'Phi-4', 'open_router', 'microsoft', 16384, 16384),
|
||||||
|
('gryphe/mythomax-l2-13b', 'MythoMax L2 13B', 'open_router', 'gryphe', 4096, 4096),
|
||||||
|
('meta-llama/llama-4-scout', 'Llama 4 Scout', 'open_router', 'meta', 131072, 131072),
|
||||||
|
('meta-llama/llama-4-maverick', 'Llama 4 Maverick', 'open_router', 'meta', 1048576, 1000000),
|
||||||
|
('x-ai/grok-3', 'Grok 3', 'open_router', 'xai', 131072, 131072),
|
||||||
|
('x-ai/grok-4', 'Grok 4', 'open_router', 'xai', 256000, 256000),
|
||||||
|
('x-ai/grok-4-fast', 'Grok 4 Fast', 'open_router', 'xai', 2000000, 30000),
|
||||||
|
('x-ai/grok-4.1-fast', 'Grok 4.1 Fast', 'open_router', 'xai', 2000000, 30000),
|
||||||
|
('x-ai/grok-code-fast-1', 'Grok Code Fast 1', 'open_router', 'xai', 256000, 10000),
|
||||||
|
('moonshotai/kimi-k2', 'Kimi K2', 'open_router', 'moonshotai', 131000, 131000),
|
||||||
|
('qwen/qwen3-235b-a22b-thinking-2507', 'Qwen 3 235B Thinking', 'open_router', 'alibaba', 262144, 262144),
|
||||||
|
('qwen/qwen3-coder', 'Qwen 3 Coder', 'open_router', 'alibaba', 262144, 262144),
|
||||||
|
-- Llama API models (creator: meta)
|
||||||
|
('Llama-4-Scout-17B-16E-Instruct-FP8', 'Llama 4 Scout', 'llama_api', 'meta', 128000, 4028),
|
||||||
|
('Llama-4-Maverick-17B-128E-Instruct-FP8', 'Llama 4 Maverick', 'llama_api', 'meta', 128000, 4028),
|
||||||
|
('Llama-3.3-8B-Instruct', 'Llama 3.3 8B', 'llama_api', 'meta', 128000, 4028),
|
||||||
|
('Llama-3.3-70B-Instruct', 'Llama 3.3 70B', 'llama_api', 'meta', 128000, 4028),
|
||||||
|
-- v0 models (creator: vercel)
|
||||||
|
('v0-1.5-md', 'v0 1.5 MD', 'v0', 'vercel', 128000, 64000),
|
||||||
|
('v0-1.5-lg', 'v0 1.5 LG', 'v0', 'vercel', 512000, 64000),
|
||||||
|
('v0-1.0-md', 'v0 1.0 MD', 'v0', 'vercel', 128000, 64000)
|
||||||
|
) AS models(model_slug, model_display_name, provider_name, creator_name, context_window, max_output_tokens)
|
||||||
|
JOIN provider_ids p ON p."name" = models.provider_name
|
||||||
|
JOIN creator_ids c ON c."name" = models.creator_name
|
||||||
|
ON CONFLICT ("slug") DO NOTHING;
|
||||||
|
|
||||||
|
-- Insert Costs (using CTEs to reference model IDs)
|
||||||
|
WITH model_ids AS (
|
||||||
|
SELECT "id", "slug", "providerId" FROM "LlmModel"
|
||||||
|
),
|
||||||
|
provider_ids AS (
|
||||||
|
SELECT "id", "name" FROM "LlmProvider"
|
||||||
|
)
|
||||||
|
INSERT INTO "LlmModelCost" ("id", "createdAt", "updatedAt", "unit", "creditCost", "credentialProvider", "credentialId", "credentialType", "currency", "metadata", "llmModelId")
|
||||||
|
SELECT
|
||||||
|
gen_random_uuid(),
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
CURRENT_TIMESTAMP,
|
||||||
|
'RUN'::"LlmCostUnit",
|
||||||
|
cost,
|
||||||
|
p."name",
|
||||||
|
NULL,
|
||||||
|
'api_key',
|
||||||
|
NULL,
|
||||||
|
'{}'::jsonb,
|
||||||
|
m."id"
|
||||||
|
FROM (VALUES
|
||||||
|
-- OpenAI costs
|
||||||
|
('o3-2025-04-16', 4),
|
||||||
|
('o3-mini', 2),
|
||||||
|
('o1', 16),
|
||||||
|
('o1-mini', 4),
|
||||||
|
('gpt-5.2-2025-12-11', 5),
|
||||||
|
('gpt-5-2025-08-07', 2),
|
||||||
|
('gpt-5.1-2025-11-13', 5),
|
||||||
|
('gpt-5-mini-2025-08-07', 1),
|
||||||
|
('gpt-5-nano-2025-08-07', 1),
|
||||||
|
('gpt-5-chat-latest', 5),
|
||||||
|
('gpt-4.1-2025-04-14', 2),
|
||||||
|
('gpt-4.1-mini-2025-04-14', 1),
|
||||||
|
('gpt-4o-mini', 1),
|
||||||
|
('gpt-4o', 3),
|
||||||
|
('gpt-4-turbo', 10),
|
||||||
|
-- Anthropic costs
|
||||||
|
('claude-opus-4-6', 21),
|
||||||
|
('claude-sonnet-4-6', 5),
|
||||||
|
('claude-opus-4-1-20250805', 21),
|
||||||
|
('claude-opus-4-20250514', 21),
|
||||||
|
('claude-sonnet-4-20250514', 5),
|
||||||
|
('claude-haiku-4-5-20251001', 4),
|
||||||
|
('claude-opus-4-5-20251101', 14),
|
||||||
|
('claude-sonnet-4-5-20250929', 9),
|
||||||
|
('claude-3-haiku-20240307', 1),
|
||||||
|
-- AI/ML API costs
|
||||||
|
('Qwen/Qwen2.5-72B-Instruct-Turbo', 1),
|
||||||
|
('nvidia/llama-3.1-nemotron-70b-instruct', 1),
|
||||||
|
('meta-llama/Llama-3.3-70B-Instruct-Turbo', 1),
|
||||||
|
('meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo', 1),
|
||||||
|
('meta-llama/Llama-3.2-3B-Instruct-Turbo', 1),
|
||||||
|
-- Groq costs
|
||||||
|
('llama-3.3-70b-versatile', 1),
|
||||||
|
('llama-3.1-8b-instant', 1),
|
||||||
|
-- Ollama costs
|
||||||
|
('llama3.3', 1),
|
||||||
|
('llama3.2', 1),
|
||||||
|
('llama3', 1),
|
||||||
|
('llama3.1:405b', 1),
|
||||||
|
('dolphin-mistral:latest', 1),
|
||||||
|
-- OpenRouter costs
|
||||||
|
('google/gemini-2.5-pro-preview-03-25', 4),
|
||||||
|
('google/gemini-2.5-pro', 4),
|
||||||
|
('google/gemini-3.1-pro-preview', 5),
|
||||||
|
('google/gemini-3-flash-preview', 3),
|
||||||
|
('google/gemini-3.1-flash-lite-preview', 1),
|
||||||
|
('mistralai/mistral-nemo', 1),
|
||||||
|
('mistralai/mistral-large-2512', 3),
|
||||||
|
('mistralai/mistral-medium-3.1', 2),
|
||||||
|
('mistralai/mistral-small-3.2-24b-instruct', 1),
|
||||||
|
('mistralai/codestral-2508', 2),
|
||||||
|
('cohere/command-r-08-2024', 1),
|
||||||
|
('cohere/command-r-plus-08-2024', 3),
|
||||||
|
('cohere/command-a-03-2025', 2),
|
||||||
|
('cohere/command-a-reasoning-08-2025', 3),
|
||||||
|
('cohere/command-a-translate-08-2025', 1),
|
||||||
|
('cohere/command-a-vision-07-2025', 2),
|
||||||
|
('deepseek/deepseek-chat', 2),
|
||||||
|
('perplexity/sonar', 1),
|
||||||
|
('perplexity/sonar-pro', 5),
|
||||||
|
('perplexity/sonar-deep-research', 10),
|
||||||
|
('perplexity/sonar-reasoning-pro', 5),
|
||||||
|
('nousresearch/hermes-3-llama-3.1-405b', 1),
|
||||||
|
('nousresearch/hermes-3-llama-3.1-70b', 1),
|
||||||
|
('amazon/nova-lite-v1', 1),
|
||||||
|
('amazon/nova-micro-v1', 1),
|
||||||
|
('amazon/nova-pro-v1', 1),
|
||||||
|
('microsoft/wizardlm-2-8x22b', 1),
|
||||||
|
('microsoft/phi-4', 1),
|
||||||
|
('gryphe/mythomax-l2-13b', 1),
|
||||||
|
('meta-llama/llama-4-scout', 1),
|
||||||
|
('meta-llama/llama-4-maverick', 1),
|
||||||
|
('x-ai/grok-3', 5),
|
||||||
|
('x-ai/grok-4', 9),
|
||||||
|
('x-ai/grok-4-fast', 1),
|
||||||
|
('x-ai/grok-4.1-fast', 1),
|
||||||
|
('x-ai/grok-code-fast-1', 1),
|
||||||
|
('moonshotai/kimi-k2', 1),
|
||||||
|
('qwen/qwen3-235b-a22b-thinking-2507', 1),
|
||||||
|
('qwen/qwen3-coder', 9),
|
||||||
|
('google/gemini-2.5-flash', 1),
|
||||||
|
('google/gemini-2.0-flash-001', 1),
|
||||||
|
('google/gemini-2.5-flash-lite-preview-06-17', 1),
|
||||||
|
('google/gemini-2.0-flash-lite-001', 1),
|
||||||
|
('deepseek/deepseek-r1-0528', 1),
|
||||||
|
('openai/gpt-oss-120b', 1),
|
||||||
|
('openai/gpt-oss-20b', 1),
|
||||||
|
-- Llama API costs
|
||||||
|
('Llama-4-Scout-17B-16E-Instruct-FP8', 1),
|
||||||
|
('Llama-4-Maverick-17B-128E-Instruct-FP8', 1),
|
||||||
|
('Llama-3.3-8B-Instruct', 1),
|
||||||
|
('Llama-3.3-70B-Instruct', 1),
|
||||||
|
-- v0 costs
|
||||||
|
('v0-1.5-md', 1),
|
||||||
|
('v0-1.5-lg', 2),
|
||||||
|
('v0-1.0-md', 1)
|
||||||
|
) AS costs(model_slug, cost)
|
||||||
|
JOIN model_ids m ON m."slug" = costs.model_slug
|
||||||
|
JOIN provider_ids p ON p."id" = m."providerId"
|
||||||
|
ON CONFLICT ("llmModelId", "credentialProvider", "unit") WHERE "credentialId" IS NULL DO NOTHING;
|
||||||
|
|
||||||
@@ -1301,3 +1301,164 @@ model OAuthRefreshToken {
|
|||||||
@@index([userId, applicationId])
|
@@index([userId, applicationId])
|
||||||
@@index([expiresAt]) // For cleanup
|
@@index([expiresAt]) // For cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// LLM Registry Models
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
enum LlmCostUnit {
|
||||||
|
RUN
|
||||||
|
TOKENS
|
||||||
|
}
|
||||||
|
|
||||||
|
model LlmProvider {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
name String @unique
|
||||||
|
displayName String
|
||||||
|
description String?
|
||||||
|
|
||||||
|
defaultCredentialProvider String?
|
||||||
|
defaultCredentialId String?
|
||||||
|
defaultCredentialType String?
|
||||||
|
|
||||||
|
metadata Json @default("{}")
|
||||||
|
|
||||||
|
Models LlmModel[]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
model LlmModel {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
slug String @unique
|
||||||
|
displayName String
|
||||||
|
description String?
|
||||||
|
|
||||||
|
providerId String
|
||||||
|
Provider LlmProvider @relation(fields: [providerId], references: [id], onDelete: Restrict)
|
||||||
|
|
||||||
|
// Creator is the organization that created/trained the model (e.g., OpenAI, Meta)
|
||||||
|
// This is distinct from the provider who hosts/serves the model (e.g., OpenRouter)
|
||||||
|
creatorId String?
|
||||||
|
Creator LlmModelCreator? @relation(fields: [creatorId], references: [id], onDelete: SetNull)
|
||||||
|
|
||||||
|
contextWindow Int
|
||||||
|
maxOutputTokens Int?
|
||||||
|
priceTier Int @default(1) // 1=cheapest, 2=medium, 3=expensive (DB constraint: 1-3)
|
||||||
|
isEnabled Boolean @default(true)
|
||||||
|
isRecommended Boolean @default(false)
|
||||||
|
|
||||||
|
// Model-specific capabilities
|
||||||
|
// These vary per model even within the same provider (e.g., Hugging Face)
|
||||||
|
// Default to false for safety - partially-seeded rows should not be assumed capable
|
||||||
|
supportsTools Boolean @default(false)
|
||||||
|
supportsJsonOutput Boolean @default(false)
|
||||||
|
supportsReasoning Boolean @default(false)
|
||||||
|
supportsParallelToolCalls Boolean @default(false)
|
||||||
|
|
||||||
|
capabilities Json @default("{}")
|
||||||
|
metadata Json @default("{}")
|
||||||
|
|
||||||
|
Costs LlmModelCost[]
|
||||||
|
SourceMigrations LlmModelMigration[] @relation("SourceMigrations")
|
||||||
|
TargetMigrations LlmModelMigration[] @relation("TargetMigrations")
|
||||||
|
|
||||||
|
@@index([providerId, isEnabled])
|
||||||
|
@@index([creatorId])
|
||||||
|
// Note: slug already has @unique which creates an implicit index
|
||||||
|
}
|
||||||
|
|
||||||
|
model LlmModelCost {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
unit LlmCostUnit @default(RUN)
|
||||||
|
|
||||||
|
creditCost Int // DB constraint: >= 0
|
||||||
|
|
||||||
|
// Provider identifier (e.g., "openai", "anthropic", "openrouter")
|
||||||
|
// Used to determine which credential system provides the API key.
|
||||||
|
// Allows different pricing for:
|
||||||
|
// - Default provider costs (WHERE credentialId IS NULL)
|
||||||
|
// - User's own API key costs (WHERE credentialId IS NOT NULL)
|
||||||
|
credentialProvider String
|
||||||
|
credentialId String?
|
||||||
|
credentialType String?
|
||||||
|
currency String?
|
||||||
|
|
||||||
|
metadata Json @default("{}")
|
||||||
|
|
||||||
|
llmModelId String
|
||||||
|
Model LlmModel @relation(fields: [llmModelId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
// Note: Unique constraints are implemented as partial indexes in migration SQL:
|
||||||
|
// - One for default costs (WHERE credentialId IS NULL)
|
||||||
|
// - One for credential-specific costs (WHERE credentialId IS NOT NULL)
|
||||||
|
// This allows both provider-level defaults and credential-specific overrides
|
||||||
|
}
|
||||||
|
|
||||||
|
model LlmModelCreator {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
name String @unique // e.g., "openai", "anthropic", "meta"
|
||||||
|
displayName String // e.g., "OpenAI", "Anthropic", "Meta"
|
||||||
|
description String?
|
||||||
|
websiteUrl String? // Link to creator's website
|
||||||
|
logoUrl String? // URL to creator's logo
|
||||||
|
|
||||||
|
metadata Json @default("{}")
|
||||||
|
|
||||||
|
Models LlmModel[]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
model LlmModelMigration {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
sourceModelSlug String // The original model that was disabled
|
||||||
|
targetModelSlug String // The model workflows were migrated to
|
||||||
|
reason String? // Why the migration happened (e.g., "Provider outage")
|
||||||
|
|
||||||
|
// FK constraints ensure slugs reference valid models
|
||||||
|
SourceModel LlmModel @relation("SourceMigrations", fields: [sourceModelSlug], references: [slug], onDelete: Restrict, onUpdate: Cascade)
|
||||||
|
TargetModel LlmModel @relation("TargetMigrations", fields: [targetModelSlug], references: [slug], onDelete: Restrict, onUpdate: Cascade)
|
||||||
|
|
||||||
|
// Track affected nodes as JSON array of node IDs
|
||||||
|
// Format: ["node-uuid-1", "node-uuid-2", ...]
|
||||||
|
migratedNodeIds Json @default("[]")
|
||||||
|
nodeCount Int // Number of nodes migrated (DB constraint: >= 0)
|
||||||
|
|
||||||
|
// Custom pricing override for migrated workflows during the migration period.
|
||||||
|
// Use case: When migrating users from an expensive model (e.g., GPT-4) to a cheaper
|
||||||
|
// one (e.g., GPT-3.5), you may want to temporarily maintain the original pricing
|
||||||
|
// to avoid billing surprises, or offer a discount during the transition.
|
||||||
|
//
|
||||||
|
// IMPORTANT: This field is intended for integration with the billing system.
|
||||||
|
// When billing calculates costs for nodes affected by this migration, it should
|
||||||
|
// check if customCreditCost is set and use it instead of the target model's cost.
|
||||||
|
// If null, the target model's normal cost applies.
|
||||||
|
//
|
||||||
|
// TODO: Integrate with billing system to apply this override during cost calculation.
|
||||||
|
// LIMITATION: This is a simple Int and doesn't distinguish RUN vs TOKENS pricing.
|
||||||
|
// For token-priced models, this may be ambiguous. Consider migrating to a relation
|
||||||
|
// with LlmModelCost or a dedicated override model in a follow-up PR.
|
||||||
|
customCreditCost Int? // DB constraint: >= 0 when not null
|
||||||
|
|
||||||
|
// Revert tracking
|
||||||
|
isReverted Boolean @default(false)
|
||||||
|
revertedAt DateTime?
|
||||||
|
|
||||||
|
// Note: Partial unique index in migration SQL prevents multiple active migrations per source:
|
||||||
|
// UNIQUE (sourceModelSlug) WHERE isReverted = false
|
||||||
|
@@index([targetModelSlug])
|
||||||
|
@@index([sourceModelSlug, isReverted]) // Composite index for active migration queries
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user