Merge pull request #1973 from Stijnus/feat/openai-like-api-models

feat: add support for OPENAI_LIKE_API_MODELS
This commit is contained in:
Stijnus
2025-09-07 10:42:38 +02:00
committed by GitHub
5 changed files with 111 additions and 12 deletions

View File

@@ -10,6 +10,7 @@ export default class OpenAILikeProvider extends BaseProvider {
config = { config = {
baseUrlKey: 'OPENAI_LIKE_API_BASE_URL', baseUrlKey: 'OPENAI_LIKE_API_BASE_URL',
apiTokenKey: 'OPENAI_LIKE_API_KEY', apiTokenKey: 'OPENAI_LIKE_API_KEY',
modelsKey: 'OPENAI_LIKE_API_MODELS',
}; };
staticModels: ModelInfo[] = []; staticModels: ModelInfo[] = [];
@@ -31,12 +32,17 @@ export default class OpenAILikeProvider extends BaseProvider {
return []; return [];
} }
try {
const response = await fetch(`${baseUrl}/models`, { const response = await fetch(`${baseUrl}/models`, {
headers: { headers: {
Authorization: `Bearer ${apiKey}`, Authorization: `Bearer ${apiKey}`,
}, },
}); });
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const res = (await response.json()) as any; const res = (await response.json()) as any;
return res.data.map((model: any) => ({ return res.data.map((model: any) => ({
@@ -45,6 +51,95 @@ export default class OpenAILikeProvider extends BaseProvider {
provider: this.name, provider: this.name,
maxTokenAllowed: 8000, maxTokenAllowed: 8000,
})); }));
} catch (error) {
console.log(`${this.name}: Not allowed to GET /models endpoint for provider`, error);
// Fallback to OPENAI_LIKE_API_MODELS if available
// eslint-disable-next-line dot-notation
const modelsEnv = serverEnv['OPENAI_LIKE_API_MODELS'] || settings?.OPENAI_LIKE_API_MODELS;
if (modelsEnv) {
console.log(`${this.name}: OPENAI_LIKE_API_MODELS=${modelsEnv}`);
return this._parseModelsFromEnv(modelsEnv);
}
return [];
}
}
/**
* Parse OPENAI_LIKE_API_MODELS environment variable
* Format: path/to/model1:limit;path/to/model2:limit;path/to/model3:limit
*/
private _parseModelsFromEnv(modelsEnv: string): ModelInfo[] {
if (!modelsEnv) {
return [];
}
try {
const models: ModelInfo[] = [];
const modelEntries = modelsEnv.split(';');
for (const entry of modelEntries) {
const trimmedEntry = entry.trim();
if (!trimmedEntry) {
continue;
}
const [modelPath, limitStr] = trimmedEntry.split(':');
if (!modelPath) {
continue;
}
const limit = limitStr ? parseInt(limitStr.trim(), 10) : 8000;
const modelName = modelPath.trim();
// Generate a readable label from the model path
const label = this._generateModelLabel(modelName);
models.push({
name: modelName,
label,
provider: this.name,
maxTokenAllowed: limit,
});
}
console.log(`${this.name}: Parsed Models:`, models);
return models;
} catch (error) {
console.error(`${this.name}: Error parsing OPENAI_LIKE_API_MODELS:`, error);
return [];
}
}
/**
* Generate a readable label from model path
*/
private _generateModelLabel(modelPath: string): string {
// Extract the last part of the path and clean it up
const parts = modelPath.split('/');
const lastPart = parts[parts.length - 1];
// Remove common prefixes and clean up the name
let label = lastPart
.replace(/^accounts\//, '')
.replace(/^fireworks\/models\//, '')
.replace(/^models\//, '')
// Capitalize first letter of each word
.replace(/\b\w/g, (l) => l.toUpperCase())
// Replace spaces with hyphens for a cleaner look
.replace(/\s+/g, '-');
// Add provider suffix if not already present
if (!label.includes('Fireworks') && !label.includes('OpenAI')) {
label += ' (OpenAI Compatible)';
}
return label;
} }
getModelInstance(options: { getModelInstance(options: {

View File

@@ -17,6 +17,7 @@ export type ProviderInfo = {
export interface IProviderSetting { export interface IProviderSetting {
enabled?: boolean; enabled?: boolean;
baseUrl?: string; baseUrl?: string;
OPENAI_LIKE_API_MODELS?: string;
} }
export type IProviderConfig = ProviderInfo & { export type IProviderConfig = ProviderInfo & {

View File

@@ -60,6 +60,7 @@ export default defineConfig((config) => {
envPrefix: [ envPrefix: [
'VITE_', 'VITE_',
'OPENAI_LIKE_API_BASE_URL', 'OPENAI_LIKE_API_BASE_URL',
'OPENAI_LIKE_API_MODELS',
'OLLAMA_API_BASE_URL', 'OLLAMA_API_BASE_URL',
'LMSTUDIO_API_BASE_URL', 'LMSTUDIO_API_BASE_URL',
'TOGETHER_API_BASE_URL', 'TOGETHER_API_BASE_URL',

View File

@@ -60,6 +60,7 @@ export default defineConfig((config) => {
envPrefix: [ envPrefix: [
'VITE_', 'VITE_',
'OPENAI_LIKE_API_BASE_URL', 'OPENAI_LIKE_API_BASE_URL',
'OPENAI_LIKE_API_MODELS',
'OLLAMA_API_BASE_URL', 'OLLAMA_API_BASE_URL',
'LMSTUDIO_API_BASE_URL', 'LMSTUDIO_API_BASE_URL',
'TOGETHER_API_BASE_URL', 'TOGETHER_API_BASE_URL',

View File

@@ -9,6 +9,7 @@ interface Env {
OLLAMA_API_BASE_URL: string; OLLAMA_API_BASE_URL: string;
OPENAI_LIKE_API_KEY: string; OPENAI_LIKE_API_KEY: string;
OPENAI_LIKE_API_BASE_URL: string; OPENAI_LIKE_API_BASE_URL: string;
OPENAI_LIKE_API_MODELS: string;
TOGETHER_API_KEY: string; TOGETHER_API_KEY: string;
TOGETHER_API_BASE_URL: string; TOGETHER_API_BASE_URL: string;
DEEPSEEK_API_KEY: string; DEEPSEEK_API_KEY: string;