mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions
431 lines
12 KiB
TypeScript
431 lines
12 KiB
TypeScript
import {
|
|
Verbosity,
|
|
EModelEndpoint,
|
|
ReasoningEffort,
|
|
ReasoningSummary,
|
|
} from 'librechat-data-provider';
|
|
import { getOpenAIConfig } from './config';
|
|
|
|
describe('getOpenAIConfig - Backward Compatibility', () => {
|
|
describe('OpenAI endpoint', () => {
|
|
it('should handle GPT-5 model with reasoning and web search', () => {
|
|
const apiKey = 'sk-proj-somekey';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'gpt-5-nano',
|
|
verbosity: Verbosity.high,
|
|
reasoning_effort: ReasoningEffort.high,
|
|
reasoning_summary: ReasoningSummary.detailed,
|
|
useResponsesApi: true,
|
|
web_search: true,
|
|
user: 'some-user',
|
|
},
|
|
proxy: '',
|
|
reverseProxyUrl: null,
|
|
endpoint: EModelEndpoint.openAI,
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'gpt-5-nano',
|
|
useResponsesApi: true,
|
|
user: 'some-user',
|
|
apiKey: 'sk-proj-somekey',
|
|
reasoning: {
|
|
effort: ReasoningEffort.high,
|
|
summary: ReasoningSummary.detailed,
|
|
},
|
|
modelKwargs: {
|
|
text: {
|
|
verbosity: Verbosity.high,
|
|
},
|
|
},
|
|
},
|
|
configOptions: {},
|
|
tools: [
|
|
{
|
|
type: 'web_search',
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('OpenRouter endpoint', () => {
|
|
it('should handle OpenRouter configuration with dropParams and custom headers', () => {
|
|
const apiKey = 'sk-xxxx';
|
|
const endpoint = 'OpenRouter';
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'qwen/qwen3-max',
|
|
user: 'some-user',
|
|
},
|
|
reverseProxyUrl: 'https://gateway.ai.cloudflare.com/v1/account-id/gateway-id/openrouter',
|
|
headers: {
|
|
'x-librechat-thread-id': '{{LIBRECHAT_BODY_CONVERSATIONID}}',
|
|
'x-test-key': '{{TESTING_USER_VAR}}',
|
|
},
|
|
proxy: '',
|
|
dropParams: ['user'],
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'qwen/qwen3-max',
|
|
include_reasoning: true,
|
|
apiKey: 'sk-xxxx',
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://gateway.ai.cloudflare.com/v1/account-id/gateway-id/openrouter',
|
|
defaultHeaders: {
|
|
'HTTP-Referer': 'https://librechat.ai',
|
|
'X-Title': 'LibreChat',
|
|
'x-librechat-thread-id': '{{LIBRECHAT_BODY_CONVERSATIONID}}',
|
|
'x-test-key': '{{TESTING_USER_VAR}}',
|
|
},
|
|
},
|
|
tools: [],
|
|
provider: 'openrouter',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Azure OpenAI endpoint', () => {
|
|
it('should handle basic Azure OpenAI configuration', () => {
|
|
const apiKey = 'some_key';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'gpt-4o',
|
|
user: 'some_user_id',
|
|
},
|
|
reverseProxyUrl: null,
|
|
endpoint: 'azureOpenAI',
|
|
azure: {
|
|
azureOpenAIApiKey: 'some_azure_key',
|
|
azureOpenAIApiInstanceName: 'some_instance_name',
|
|
azureOpenAIApiDeploymentName: 'gpt-4o',
|
|
azureOpenAIApiVersion: '2024-02-15-preview',
|
|
},
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'gpt-4o',
|
|
user: 'some_user_id',
|
|
azureOpenAIApiKey: 'some_azure_key',
|
|
azureOpenAIApiInstanceName: 'some_instance_name',
|
|
azureOpenAIApiDeploymentName: 'gpt-4o',
|
|
azureOpenAIApiVersion: '2024-02-15-preview',
|
|
},
|
|
configOptions: {},
|
|
tools: [],
|
|
});
|
|
});
|
|
|
|
it('should handle Azure OpenAI with Responses API and reasoning', () => {
|
|
const apiKey = 'some_azure_key';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'gpt-5',
|
|
reasoning_effort: ReasoningEffort.high,
|
|
reasoning_summary: ReasoningSummary.detailed,
|
|
verbosity: Verbosity.high,
|
|
useResponsesApi: true,
|
|
user: 'some_user_id',
|
|
},
|
|
endpoint: 'azureOpenAI',
|
|
azure: {
|
|
azureOpenAIApiKey: 'some_azure_key',
|
|
azureOpenAIApiInstanceName: 'some_instance_name',
|
|
azureOpenAIApiDeploymentName: 'gpt-5',
|
|
azureOpenAIApiVersion: '2024-12-01-preview',
|
|
},
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'gpt-5',
|
|
useResponsesApi: true,
|
|
user: 'some_user_id',
|
|
apiKey: 'some_azure_key',
|
|
reasoning: {
|
|
effort: ReasoningEffort.high,
|
|
summary: ReasoningSummary.detailed,
|
|
},
|
|
modelKwargs: {
|
|
text: {
|
|
verbosity: Verbosity.high,
|
|
},
|
|
},
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://some_instance_name.openai.azure.com/openai/v1',
|
|
defaultHeaders: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
defaultQuery: {
|
|
'api-version': 'preview',
|
|
},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
|
|
it('should handle Azure serverless configuration with dropParams', () => {
|
|
const apiKey = 'some_azure_key';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'jais-30b-chat',
|
|
user: 'some_user_id',
|
|
},
|
|
reverseProxyUrl: 'https://some_endpoint_name.services.ai.azure.com/models',
|
|
endpoint: 'azureOpenAI',
|
|
headers: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
dropParams: ['stream_options', 'user'],
|
|
azure: false as const,
|
|
defaultQuery: {
|
|
'api-version': '2024-05-01-preview',
|
|
},
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'jais-30b-chat',
|
|
apiKey: 'some_azure_key',
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://some_endpoint_name.services.ai.azure.com/models',
|
|
defaultHeaders: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
defaultQuery: {
|
|
'api-version': '2024-05-01-preview',
|
|
},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
|
|
it('should handle Azure serverless with user-provided key configuration', () => {
|
|
const apiKey = 'some_azure_key';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'grok-3',
|
|
user: 'some_user_id',
|
|
},
|
|
reverseProxyUrl: 'https://some_endpoint_name.services.ai.azure.com/models',
|
|
endpoint: 'azureOpenAI',
|
|
headers: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
dropParams: ['stream_options', 'user'],
|
|
azure: false as const,
|
|
defaultQuery: {
|
|
'api-version': '2024-05-01-preview',
|
|
},
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'grok-3',
|
|
apiKey: 'some_azure_key',
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://some_endpoint_name.services.ai.azure.com/models',
|
|
defaultHeaders: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
defaultQuery: {
|
|
'api-version': '2024-05-01-preview',
|
|
},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
|
|
it('should handle Azure serverless with Mistral model configuration', () => {
|
|
const apiKey = 'some_azure_key';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'Mistral-Large-2411',
|
|
user: 'some_user_id',
|
|
},
|
|
reverseProxyUrl: 'https://some_endpoint_name.services.ai.azure.com/models',
|
|
endpoint: 'azureOpenAI',
|
|
headers: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
dropParams: ['stream_options', 'user'],
|
|
azure: false as const,
|
|
defaultQuery: {
|
|
'api-version': '2024-05-01-preview',
|
|
},
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'Mistral-Large-2411',
|
|
apiKey: 'some_azure_key',
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://some_endpoint_name.services.ai.azure.com/models',
|
|
defaultHeaders: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
defaultQuery: {
|
|
'api-version': '2024-05-01-preview',
|
|
},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
|
|
it('should handle Azure serverless with DeepSeek model without dropParams', () => {
|
|
const apiKey = 'some_azure_key';
|
|
const endpoint = undefined;
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'DeepSeek-R1',
|
|
user: 'some_user_id',
|
|
},
|
|
reverseProxyUrl: 'https://some_endpoint_name.models.ai.azure.com/v1/',
|
|
endpoint: 'azureOpenAI',
|
|
headers: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
azure: false as const,
|
|
defaultQuery: {
|
|
'api-version': '2024-08-01-preview',
|
|
},
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'DeepSeek-R1',
|
|
user: 'some_user_id',
|
|
apiKey: 'some_azure_key',
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://some_endpoint_name.models.ai.azure.com/v1/',
|
|
defaultHeaders: {
|
|
'api-key': 'some_azure_key',
|
|
},
|
|
defaultQuery: {
|
|
'api-version': '2024-08-01-preview',
|
|
},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Custom endpoints', () => {
|
|
it('should handle Groq custom endpoint configuration', () => {
|
|
const apiKey = 'gsk_somekey';
|
|
const endpoint = 'groq';
|
|
const options = {
|
|
modelOptions: {
|
|
model: 'qwen/qwen3-32b',
|
|
user: 'some-user',
|
|
},
|
|
reverseProxyUrl: 'https://api.groq.com/openai/v1/',
|
|
proxy: '',
|
|
headers: {},
|
|
endpoint: 'groq',
|
|
endpointType: 'custom',
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: 'qwen/qwen3-32b',
|
|
user: 'some-user',
|
|
apiKey: 'gsk_somekey',
|
|
},
|
|
configOptions: {
|
|
baseURL: 'https://api.groq.com/openai/v1/',
|
|
defaultHeaders: {},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
|
|
it('should handle Cloudflare Workers AI with custom headers and addParams', () => {
|
|
const apiKey = 'someKey';
|
|
const endpoint = 'Cloudflare Workers AI';
|
|
const options = {
|
|
modelOptions: {
|
|
model: '@cf/deepseek-ai/deepseek-r1-distill-qwen-32b',
|
|
user: 'some-user',
|
|
},
|
|
reverseProxyUrl:
|
|
'https://gateway.ai.cloudflare.com/v1/${CF_ACCOUNT_ID}/${CF_GATEWAY_ID}/workers-ai/v1',
|
|
proxy: '',
|
|
headers: {
|
|
'x-librechat-thread-id': '{{LIBRECHAT_BODY_CONVERSATIONID}}',
|
|
'x-test-key': '{{TESTING_USER_VAR}}',
|
|
},
|
|
addParams: {
|
|
disableStreaming: true,
|
|
},
|
|
endpoint: 'Cloudflare Workers AI',
|
|
endpointType: 'custom',
|
|
};
|
|
|
|
const result = getOpenAIConfig(apiKey, options, endpoint);
|
|
|
|
expect(result).toEqual({
|
|
llmConfig: {
|
|
streaming: true,
|
|
model: '@cf/deepseek-ai/deepseek-r1-distill-qwen-32b',
|
|
user: 'some-user',
|
|
disableStreaming: true,
|
|
apiKey: 'someKey',
|
|
},
|
|
configOptions: {
|
|
baseURL:
|
|
'https://gateway.ai.cloudflare.com/v1/${CF_ACCOUNT_ID}/${CF_GATEWAY_ID}/workers-ai/v1',
|
|
defaultHeaders: {
|
|
'x-librechat-thread-id': '{{LIBRECHAT_BODY_CONVERSATIONID}}',
|
|
'x-test-key': '{{TESTING_USER_VAR}}',
|
|
},
|
|
},
|
|
tools: [],
|
|
});
|
|
});
|
|
});
|
|
});
|