Files
veridian/server/utils/ai-provider.ts
T

204 lines
7.0 KiB
TypeScript

import { createCerebras, type CerebrasProvider } from "@ai-sdk/cerebras";
import { createGoogleGenerativeAI, type GoogleGenerativeAIProvider } from "@ai-sdk/google";
import { createOpenRouter, type OpenRouterProvider } from "@openrouter/ai-sdk-provider";
import { createOllama, type OllamaProvider } from "ai-sdk-ollama";
import { createOpenAICompatible, type OpenAICompatibleProvider } from '@ai-sdk/openai-compatible';
import { createCohere, type CohereProvider } from '@ai-sdk/cohere';
import { createMistral, type MistralProvider } from '@ai-sdk/mistral';
import { createLongcat, type LongcatProvider } from 'longcat-ai-sdk-provider';
import { type StreamTextTransform } from "ai";
import { providerBaseUrls, Providers } from "~/types/model";
import type { Provider as ProviderDrizzle, Model as ModelDrizzle } from '~/composables/useModels';
import { type Result, Err, Ok } from "~~/types/result";
// import { createLongcatTransformer } from "./longcat";
export type ModelGateway =
OpenRouterProvider
| OllamaProvider
| CerebrasProvider
| GoogleGenerativeAIProvider
| OpenAICompatibleProvider
| CohereProvider
| MistralProvider
| LongcatProvider;
export interface Gateway {
gateway: ModelGateway;
streamTransformer: StreamTextTransform<{}> | StreamTextTransform<{}>[] | undefined;
textTransformer: ((text: string) => string) | ((text: string) => string)[] | undefined;
}
export interface Provider {
gateway: Gateway | null;
endpoint: {
baseURL: string;
modelsEndpoint: string | null;
headers: Record<string, string>;
}
}
export enum GatewayFetchError {
NoProviderApiKey = 0,
NoProviderBaseUrl,
}
export async function getProviderDetails(provider: ProviderDrizzle, providerApiKey?: string, model?: ModelDrizzle): Promise<Result<Provider, GatewayFetchError>> {
let gateway: Gateway = {} as Gateway;
let baseURL = undefined;
let modelsEndpoint = undefined;
let headers: Record<string, string> = {};
if (provider.config.apiProxyUrl && provider.config.apiProxyUrl.trim() !== '') {
baseURL = provider.config.apiProxyUrl;
} else {
baseURL = providerBaseUrls[provider.type as typeof Providers[number]];
}
baseURL = baseURL.replace(/\/$/, '');
switch (provider.type as typeof Providers[number]) {
case 'openrouter': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createOpenRouter({
apiKey: providerApiKey,
headers: {
'HTTP-Referer': 'https://localhost:3000',
'X-Title': 'Veridian',
},
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = `/models`;
} break;
case 'closedrouter': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createOpenAICompatible({
name: 'ClosedRouter',
apiKey: providerApiKey,
baseURL,
includeUsage: true,
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = `/models`;
} break;
case 'ollama': {
if (baseURL === undefined) {
return Err(GatewayFetchError.NoProviderBaseUrl);
}
if (providerApiKey !== undefined) {
headers['Authorization'] = `Bearer ${providerApiKey}`
}
modelsEndpoint = `/api/tags`;
if (model !== undefined) {
const innerGateway = createOllama({
apiKey: providerApiKey,
baseURL,
})
gateway.gateway = ((modelId: string) => innerGateway(modelId, { think: model.capabilities.includes('reasoning') })) as OllamaProvider;
}
} break;
case 'vllm': {
gateway.gateway = createOpenAICompatible({
name: 'vLLM',
apiKey: providerApiKey,
baseURL,
includeUsage: true,
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = '/models';
} break;
case 'cerebras': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createCerebras({
apiKey: providerApiKey,
baseURL,
})
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = `/models`;
} break;
case 'google': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createGoogleGenerativeAI({
apiKey: providerApiKey,
baseURL,
});
headers['x-goog-api-key'] = `${providerApiKey}`
modelsEndpoint = `/models`;
} break;
case 'longcat': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createLongcat({
apiKey: providerApiKey,
baseURL,
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = null;
// streamTransformer = createLongcatTransformer() as StreamTextTransform<{}>;
} break;
case 'cohere': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createCohere({
apiKey: providerApiKey,
baseURL,
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = `/models`;
} break;
case 'inception': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createOpenAICompatible({
name: 'Inception',
apiKey: providerApiKey,
baseURL,
includeUsage: true,
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = null;
}
case 'mistral': {
if (providerApiKey === undefined) {
return Err(GatewayFetchError.NoProviderApiKey);
}
gateway.gateway = createMistral({
apiKey: providerApiKey,
baseURL,
});
headers['Authorization'] = `Bearer ${providerApiKey}`
modelsEndpoint = '/models';
}
}
return Ok({
gateway,
endpoint: {
baseURL,
modelsEndpoint,
headers,
}
});
}