feat: Add Bayer MGA provider with dynamic model fetching

- Implemented BayerMGAProvider extending BaseProvider
- Configured base URL: https://chat.int.bayer.com/api/v2
- Added dynamic model fetching from /models endpoint with filters
- Integrated provider into UI (CloudProvidersTab, ServiceStatusTab)
- Added provider registration in LLM registry
- Supports user-configurable API token input
- Filters models by availability status
- Maps API response to ModelInfo format with proper token limits
This commit is contained in:
Nirmal Arya
2025-05-31 13:34:28 -04:00
parent a4a398fe71
commit 14172c4de6
4 changed files with 110 additions and 7 deletions

View File

@@ -19,6 +19,7 @@ import type { IconType } from 'react-icons';
type ProviderName =
| 'AmazonBedrock'
| 'Anthropic'
| 'BayerMGA'
| 'Cohere'
| 'Deepseek'
| 'Google'
@@ -36,6 +37,7 @@ type ProviderName =
const PROVIDER_ICONS: Record<ProviderName, IconType> = {
AmazonBedrock: SiAmazon,
Anthropic: FaBrain,
BayerMGA: BsRobot,
Cohere: BiChip,
Deepseek: BiCodeBlock,
Google: SiGoogle,
@@ -53,6 +55,7 @@ const PROVIDER_ICONS: Record<ProviderName, IconType> = {
// Update PROVIDER_DESCRIPTIONS to use the same type
const PROVIDER_DESCRIPTIONS: Partial<Record<ProviderName, string>> = {
Anthropic: 'Access Claude and other Anthropic models',
BayerMGA: 'Connect to Bayer\'s internal AI assistant platform',
OpenAI: 'Use GPT-4, GPT-3.5, and other OpenAI models',
};

View File

@@ -16,11 +16,13 @@ import { useToast } from '~/components/ui/use-toast';
type ProviderName =
| 'AmazonBedrock'
| 'Anthropic'
| 'BayerMGA'
| 'Cohere'
| 'Deepseek'
| 'Google'
| 'Groq'
| 'HuggingFace'
| 'Hyperbolic'
| 'Mistral'
| 'OpenAI'
| 'OpenRouter'
@@ -82,6 +84,14 @@ const PROVIDER_STATUS_URLS: Record<ProviderName, ProviderConfig> = {
},
testModel: 'claude-3-sonnet-20240229',
},
BayerMGA: {
statusUrl: 'https://chat.int.bayer.com',
apiUrl: 'https://chat.int.bayer.com/api/v2/models?include_hidden_models=false&include_aliases=true',
headers: {
Authorization: 'Bearer $BAYER_MGA_API_KEY',
},
testModel: 'gpt-4o',
},
Cohere: {
statusUrl: 'https://status.cohere.com/',
apiUrl: 'https://api.cohere.ai/v1/models',
@@ -170,11 +180,20 @@ const PROVIDER_STATUS_URLS: Record<ProviderName, ProviderConfig> = {
},
testModel: 'deepseek-chat',
},
Hyperbolic: {
statusUrl: 'https://status.hyperbolic.ai/',
apiUrl: 'https://api.hyperbolic.ai/v1/models',
headers: {
Authorization: 'Bearer $HYPERBOLIC_API_KEY',
},
testModel: 'claude-3-opus-20240229',
},
};
const PROVIDER_ICONS: Record<ProviderName, IconType> = {
AmazonBedrock: SiAmazon,
Anthropic: FaBrain,
BayerMGA: BsRobot,
Cohere: BiChip,
Google: SiGoogle,
Groq: BsCloud,
@@ -186,6 +205,7 @@ const PROVIDER_ICONS: Record<ProviderName, IconType> = {
Together: BsCloud,
XAI: BsRobot,
Deepseek: BiCodeBlock,
Hyperbolic: BsCloud,
};
const ServiceStatusTab = () => {
@@ -209,6 +229,7 @@ const ServiceStatusTab = () => {
const envKeyMap: Record<ProviderName, string> = {
OpenAI: 'OPENAI_API_KEY',
Anthropic: 'ANTHROPIC_API_KEY',
BayerMGA: 'BAYER_MGA_API_KEY',
Cohere: 'COHERE_API_KEY',
Google: 'GOOGLE_GENERATIVE_AI_API_KEY',
HuggingFace: 'HuggingFace_API_KEY',
@@ -220,6 +241,7 @@ const ServiceStatusTab = () => {
OpenRouter: 'OPEN_ROUTER_API_KEY',
XAI: 'XAI_API_KEY',
Deepseek: 'DEEPSEEK_API_KEY',
Hyperbolic: 'HYPERBOLIC_API_KEY',
};
const envKey = envKeyMap[provider];

View File

@@ -0,0 +1,76 @@
import { BaseProvider, getOpenAILikeModel } from '~/lib/modules/llm/base-provider';
import type { ModelInfo } from '~/lib/modules/llm/types';
import type { IProviderSetting } from '~/types/model';
import type { LanguageModelV1 } from 'ai';
export default class BayerMGAProvider extends BaseProvider {
name = 'BayerMGA';
getApiKeyLink = 'https://chat.int.bayer.com';
labelForGetApiKey = 'Get Bayer MGA API Key';
config = {
baseUrl: 'https://chat.int.bayer.com/api/v2',
apiTokenKey: 'BAYER_MGA_API_KEY',
};
staticModels: ModelInfo[] = [];
async getDynamicModels(
apiKeys?: Record<string, string>,
settings?: IProviderSetting,
serverEnv: Record<string, string> = {},
): Promise<ModelInfo[]> {
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey({
apiKeys,
providerSettings: settings,
serverEnv,
defaultBaseUrlKey: 'BAYER_MGA_API_BASE_URL',
defaultApiTokenKey: 'BAYER_MGA_API_KEY',
});
if (!baseUrl || !apiKey) {
return [];
}
const response = await fetch(`${baseUrl}/models?include_hidden_models=false&include_aliases=true`, {
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
const res = (await response.json()) as any;
// Filter for available models and map to ModelInfo format
return res.data
.filter((model: any) => model.model_status === 'available')
.map((model: any) => ({
name: model.model,
label: model.name || model.model,
provider: this.name,
maxTokenAllowed: model.context_window || 8000,
}));
}
getModelInstance(options: {
model: string;
serverEnv: Env;
apiKeys?: Record<string, string>;
providerSettings?: Record<string, IProviderSetting>;
}): LanguageModelV1 {
const { model, serverEnv, apiKeys, providerSettings } = options;
const { baseUrl, apiKey } = this.getProviderBaseUrlAndKey({
apiKeys,
providerSettings: providerSettings?.[this.name],
serverEnv: serverEnv as any,
defaultBaseUrlKey: 'BAYER_MGA_API_BASE_URL',
defaultApiTokenKey: 'BAYER_MGA_API_KEY',
});
if (!baseUrl || !apiKey) {
throw new Error(`Missing configuration for ${this.name} provider`);
}
return getOpenAILikeModel(baseUrl, apiKey, model);
}
}

View File

@@ -1,9 +1,13 @@
import AmazonBedrockProvider from './providers/amazon-bedrock';
import AnthropicProvider from './providers/anthropic';
import BayerMGAProvider from './providers/bayer-mga';
import CohereProvider from './providers/cohere';
import DeepseekProvider from './providers/deepseek';
import GithubProvider from './providers/github';
import GoogleProvider from './providers/google';
import GroqProvider from './providers/groq';
import HuggingFaceProvider from './providers/huggingface';
import HyperbolicProvider from './providers/hyperbolic';
import LMStudioProvider from './providers/lmstudio';
import MistralProvider from './providers/mistral';
import OllamaProvider from './providers/ollama';
@@ -13,27 +17,25 @@ import OpenAIProvider from './providers/openai';
import PerplexityProvider from './providers/perplexity';
import TogetherProvider from './providers/together';
import XAIProvider from './providers/xai';
import HyperbolicProvider from './providers/hyperbolic';
import AmazonBedrockProvider from './providers/amazon-bedrock';
import GithubProvider from './providers/github';
export {
AmazonBedrockProvider,
AnthropicProvider,
BayerMGAProvider,
CohereProvider,
DeepseekProvider,
GithubProvider,
GoogleProvider,
GroqProvider,
HuggingFaceProvider,
HyperbolicProvider,
LMStudioProvider,
MistralProvider,
OllamaProvider,
OpenAIProvider,
OpenRouterProvider,
OpenAILikeProvider,
PerplexityProvider,
XAIProvider,
TogetherProvider,
LMStudioProvider,
AmazonBedrockProvider,
GithubProvider,
XAIProvider,
};