mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-31 04:02:26 +08:00
feat(llm): have OpenAI provider not require API keys (for endpoints like LM Studio)
This commit is contained in:
parent
c26b74495c
commit
85cfc8fbd4
@ -44,7 +44,7 @@ export async function validateEmbeddingProviders(validationWarning: HTMLElement)
|
|||||||
// Check OpenAI configuration
|
// Check OpenAI configuration
|
||||||
const apiKey = options.get('openaiApiKey');
|
const apiKey = options.get('openaiApiKey');
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
configIssues.push(`OpenAI API key is missing`);
|
configIssues.push(`OpenAI API key is missing (optional for OpenAI-compatible endpoints)`);
|
||||||
}
|
}
|
||||||
} else if (provider === 'anthropic') {
|
} else if (provider === 'anthropic') {
|
||||||
// Check Anthropic configuration
|
// Check Anthropic configuration
|
||||||
|
@ -66,12 +66,13 @@ async function listModels(req: Request, res: Response) {
|
|||||||
const apiKey = await options.getOption('openaiApiKey');
|
const apiKey = await options.getOption('openaiApiKey');
|
||||||
|
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error('OpenAI API key is not configured');
|
// Log warning but don't throw - some OpenAI-compatible endpoints don't require API keys
|
||||||
|
log.info('OpenAI API key is not configured when listing models. This may cause issues with official OpenAI endpoints.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize OpenAI client with the API key and base URL
|
// Initialize OpenAI client with the API key (or empty string) and base URL
|
||||||
const openai = new OpenAI({
|
const openai = new OpenAI({
|
||||||
apiKey,
|
apiKey: apiKey || '', // Default to empty string if no API key
|
||||||
baseURL: openaiBaseUrl
|
baseURL: openaiBaseUrl
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,9 +85,9 @@ async function listModels(req: Request, res: Response) {
|
|||||||
// Include all models as chat models, without filtering by specific model names
|
// Include all models as chat models, without filtering by specific model names
|
||||||
// This allows models from providers like OpenRouter to be displayed
|
// This allows models from providers like OpenRouter to be displayed
|
||||||
const chatModels = allModels
|
const chatModels = allModels
|
||||||
.filter((model) =>
|
.filter((model) =>
|
||||||
// Exclude models that are explicitly for embeddings
|
// Exclude models that are explicitly for embeddings
|
||||||
!model.id.includes('embedding') &&
|
!model.id.includes('embedding') &&
|
||||||
!model.id.includes('embed')
|
!model.id.includes('embed')
|
||||||
)
|
)
|
||||||
.map((model) => ({
|
.map((model) => ({
|
||||||
|
@ -14,7 +14,9 @@ export class OpenAIService extends BaseAIService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override isAvailable(): boolean {
|
override isAvailable(): boolean {
|
||||||
return super.isAvailable() && !!options.getOption('openaiApiKey');
|
// Make API key optional to support OpenAI-compatible endpoints that don't require authentication
|
||||||
|
// The provider is considered available as long as the parent checks pass
|
||||||
|
return super.isAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getClient(apiKey: string, baseUrl?: string): OpenAI {
|
private getClient(apiKey: string, baseUrl?: string): OpenAI {
|
||||||
@ -29,7 +31,7 @@ export class OpenAIService extends BaseAIService {
|
|||||||
|
|
||||||
async generateChatCompletion(messages: Message[], opts: ChatCompletionOptions = {}): Promise<ChatResponse> {
|
async generateChatCompletion(messages: Message[], opts: ChatCompletionOptions = {}): Promise<ChatResponse> {
|
||||||
if (!this.isAvailable()) {
|
if (!this.isAvailable()) {
|
||||||
throw new Error('OpenAI service is not available. Check API key and AI settings.');
|
throw new Error('OpenAI service is not available. Check AI settings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get provider-specific options from the central provider manager
|
// Get provider-specific options from the central provider manager
|
||||||
|
@ -134,7 +134,7 @@ export async function createProvidersFromCurrentOptions(): Promise<EmbeddingProv
|
|||||||
const ollamaEmbeddingBaseUrl = await options.getOption('ollamaEmbeddingBaseUrl');
|
const ollamaEmbeddingBaseUrl = await options.getOption('ollamaEmbeddingBaseUrl');
|
||||||
if (ollamaEmbeddingBaseUrl) {
|
if (ollamaEmbeddingBaseUrl) {
|
||||||
const embeddingModel = await options.getOption('ollamaEmbeddingModel');
|
const embeddingModel = await options.getOption('ollamaEmbeddingModel');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ollamaProvider = new OllamaEmbeddingProvider({
|
const ollamaProvider = new OllamaEmbeddingProvider({
|
||||||
model: embeddingModel,
|
model: embeddingModel,
|
||||||
@ -152,23 +152,30 @@ export async function createProvidersFromCurrentOptions(): Promise<EmbeddingProv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create OpenAI provider if API key is configured
|
// Create OpenAI provider even without API key (for OpenAI-compatible endpoints)
|
||||||
const openaiApiKey = await options.getOption('openaiApiKey');
|
const openaiApiKey = await options.getOption('openaiApiKey');
|
||||||
if (openaiApiKey) {
|
const openaiBaseUrl = await options.getOption('openaiBaseUrl');
|
||||||
const openaiModel = await options.getOption('openaiEmbeddingModel') || 'text-embedding-3-small';
|
|
||||||
const openaiBaseUrl = await options.getOption('openaiBaseUrl') || 'https://api.openai.com/v1';
|
// Only create OpenAI provider if base URL is set or API key is provided
|
||||||
|
if (openaiApiKey || openaiBaseUrl) {
|
||||||
|
const openaiModel = await options.getOption('openaiEmbeddingModel')
|
||||||
|
const finalBaseUrl = openaiBaseUrl || 'https://api.openai.com/v1';
|
||||||
|
|
||||||
|
if (!openaiApiKey) {
|
||||||
|
log.info('Creating OpenAI embedding provider without API key. This may cause issues with official OpenAI endpoints.');
|
||||||
|
}
|
||||||
|
|
||||||
const openaiProvider = new OpenAIEmbeddingProvider({
|
const openaiProvider = new OpenAIEmbeddingProvider({
|
||||||
model: openaiModel,
|
model: openaiModel,
|
||||||
dimension: 1536,
|
dimension: 1536,
|
||||||
type: 'float32',
|
type: 'float32',
|
||||||
apiKey: openaiApiKey,
|
apiKey: openaiApiKey || '', // Default to empty string
|
||||||
baseUrl: openaiBaseUrl
|
baseUrl: finalBaseUrl
|
||||||
});
|
});
|
||||||
|
|
||||||
registerEmbeddingProvider(openaiProvider);
|
registerEmbeddingProvider(openaiProvider);
|
||||||
result.push(openaiProvider);
|
result.push(openaiProvider);
|
||||||
log.info(`Created OpenAI provider on-demand: ${openaiModel}`);
|
log.info(`Created OpenAI provider on-demand: ${openaiModel} at ${finalBaseUrl}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create Voyage provider if API key is configured
|
// Create Voyage provider if API key is configured
|
||||||
@ -221,7 +228,7 @@ export async function getEnabledEmbeddingProviders(): Promise<EmbeddingProvider[
|
|||||||
|
|
||||||
// First try to get existing registered providers
|
// First try to get existing registered providers
|
||||||
const existingProviders = Array.from(providers.values());
|
const existingProviders = Array.from(providers.values());
|
||||||
|
|
||||||
// If no providers are registered, create them on-demand from current options
|
// If no providers are registered, create them on-demand from current options
|
||||||
if (existingProviders.length === 0) {
|
if (existingProviders.length === 0) {
|
||||||
log.info('No providers registered, creating from current options');
|
log.info('No providers registered, creating from current options');
|
||||||
@ -352,7 +359,8 @@ export function getOpenAIOptions(
|
|||||||
try {
|
try {
|
||||||
const apiKey = options.getOption('openaiApiKey');
|
const apiKey = options.getOption('openaiApiKey');
|
||||||
if (!apiKey) {
|
if (!apiKey) {
|
||||||
throw new Error('OpenAI API key is not configured');
|
// Log warning but don't throw - some OpenAI-compatible endpoints don't require API keys
|
||||||
|
log.info('OpenAI API key is not configured. This may cause issues with official OpenAI endpoints.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseUrl = options.getOption('openaiBaseUrl') || PROVIDER_CONSTANTS.OPENAI.BASE_URL;
|
const baseUrl = options.getOption('openaiBaseUrl') || PROVIDER_CONSTANTS.OPENAI.BASE_URL;
|
||||||
@ -377,7 +385,7 @@ export function getOpenAIOptions(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
// Connection settings
|
// Connection settings
|
||||||
apiKey,
|
apiKey: apiKey || '', // Default to empty string if no API key
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
|
||||||
// Provider metadata
|
// Provider metadata
|
||||||
|
Loading…
x
Reference in New Issue
Block a user