ruvector/studio/lib/ai/model.ts
rUv 814f595995 feat(studio): Add complete RuVector Studio application
Major additions:
- Complete Next.js studio application with 1600+ components
- Docker support (Dockerfile.combined, docker-compose.yml)
- GCP deployment documentation and benchmarks
- SQL benchmark scripts for performance testing
- Sentry integration for monitoring
- Comprehensive test suite and mocks

Studio features:
- Dashboard and admin interfaces
- Data visualization components
- Authentication and user management
- API integration with RuVector backend
- Static data and public assets

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 23:04:48 +00:00

110 lines
3.3 KiB
TypeScript

import { openai } from '@ai-sdk/openai'
import { LanguageModel } from 'ai'
import { checkAwsCredentials, createRoutedBedrock } from './bedrock'
import {
BedrockModel,
Model,
OpenAIModel,
PROVIDERS,
ProviderModelConfig,
ProviderName,
getDefaultModelForProvider,
} from './model.utils'
type PromptProviderOptions = Record<string, any>
type ProviderOptions = Record<string, any>
type ModelSuccess = {
model: LanguageModel
promptProviderOptions?: PromptProviderOptions
providerOptions?: ProviderOptions
error?: never
}
export type ModelError = {
model?: never
promptProviderOptions?: never
providerOptions?: never
error: Error
}
type ModelResponse = ModelSuccess | ModelError
export const ModelErrorMessage = 'No valid AI model available based on available credentials.'
export type GetModelParams = {
provider?: ProviderName
model?: Model
routingKey: string
isLimited?: boolean
}
/**
* Retrieves a LanguageModel from a specific provider and model.
* - If provider/model not specified, auto-selects based on available credentials (prefers Bedrock).
* - If isLimited is true, uses the provider's default model.
* - Returns promptProviderOptions that callers can attach to the system message.
*/
export async function getModel({
provider,
model,
routingKey,
isLimited = true,
}: GetModelParams): Promise<ModelResponse> {
const envThrottled = process.env.IS_THROTTLED !== 'false'
let preferredProvider: ProviderName | undefined = provider
const hasAwsCredentials = await checkAwsCredentials()
const hasAwsBedrockRoleArn = !!process.env.AWS_BEDROCK_ROLE_ARN
const hasOpenAIKey = !!process.env.OPENAI_API_KEY
// Auto-pick a provider if not specified defaulting to Bedrock
if (!preferredProvider) {
if (hasAwsBedrockRoleArn && hasAwsCredentials) {
preferredProvider = 'bedrock'
} else if (hasOpenAIKey) {
preferredProvider = 'openai'
}
}
if (!preferredProvider) {
return { error: new Error(ModelErrorMessage) }
}
const providerRegistry = PROVIDERS[preferredProvider]
if (!providerRegistry) {
return { error: new Error(`Unknown provider: ${preferredProvider}`) }
}
const models = providerRegistry.models as Record<Model, ProviderModelConfig>
const useDefault = isLimited || envThrottled || !model || !models[model]
const chosenModelId = useDefault ? getDefaultModelForProvider(preferredProvider) : model
if (preferredProvider === 'bedrock') {
if (!hasAwsBedrockRoleArn || !hasAwsCredentials) {
return { error: new Error('AWS Bedrock credentials not available') }
}
const bedrock = createRoutedBedrock(routingKey)
const model = await bedrock(chosenModelId as BedrockModel)
const promptProviderOptions = (
providerRegistry.models as Record<BedrockModel, ProviderModelConfig>
)[chosenModelId as BedrockModel]?.promptProviderOptions
return { model, promptProviderOptions }
}
if (preferredProvider === 'openai') {
if (!hasOpenAIKey) {
return { error: new Error('OPENAI_API_KEY not available') }
}
return {
model: openai(chosenModelId as OpenAIModel),
promptProviderOptions: models[chosenModelId as OpenAIModel]?.promptProviderOptions,
providerOptions: providerRegistry.providerOptions,
}
}
return { error: new Error(`Unsupported provider: ${preferredProvider}`) }
}