Skip to content

Add OpenAI API compatible LLM support with automatic fallback#51

Open
Copilot wants to merge 3 commits intomainfrom
copilot/fix-9fea9bd8-6efe-4706-8e6a-fcdfcf0acb38
Open

Add OpenAI API compatible LLM support with automatic fallback#51
Copilot wants to merge 3 commits intomainfrom
copilot/fix-9fea9bd8-6efe-4706-8e6a-fcdfcf0acb38

Conversation

Copy link
Contributor

Copilot AI commented Sep 27, 2025

Overview

This PR implements OpenAI API compatible LLM support for Vinci Clips, addressing the feature request to remove limitations of being Gemini-only and enable users to use ChatGPT, Perplexity, and other LLM providers.

What's New

Multi-Provider LLM Support

  • Google Gemini (existing, free tier available)
  • OpenAI (ChatGPT, GPT-4, GPT-4 Turbo, etc.)
  • OpenAI-compatible APIs (Perplexity, local models, gpt4free proxies, etc.)

Intelligent Provider Selection

  • Primary provider selection via LLM_PROVIDER environment variable
  • Automatic fallback to available providers if primary fails
  • Provider detection based on configured API keys

Zero Breaking Changes

Existing Gemini configurations continue working without modification. All current functionality is preserved.

Configuration Examples

Basic OpenAI Setup

LLM_PROVIDER=openai
OPENAI_API_KEY=sk-your-openai-key-here
LLM_MODEL=gpt-3.5-turbo

Perplexity AI Setup

LLM_PROVIDER=openai
LLM_API_KEY=pplx-your-perplexity-key
LLM_BASE_URL=https://api.perplexity.ai
LLM_MODEL=llama-3.1-sonar-small-128k-online

Hybrid Setup (Recommended)

GEMINI_API_KEY=your-gemini-key      # Free transcription
OPENAI_API_KEY=your-openai-key      # Premium analysis
LLM_PROVIDER=openai                 # Use OpenAI as primary

Technical Implementation

New LLM Abstraction Layer

  • backend/src/services/llmService.js - Unified interface for all LLM providers
  • Handles provider-specific API differences transparently
  • Maintains exact same functionality as original Gemini implementation

Updated Routes

All LLM-dependent routes now use the abstraction layer:

  • analyze.js - Transcript analysis for clip suggestions
  • upload.js - Audio transcription from uploaded files
  • import.js - Transcription for imported videos
  • retry-transcription.js - Retry failed transcriptions

New API Endpoint

  • GET /clips/llm/provider-info - Returns current provider configuration and available providers

Audio Transcription Note

Audio transcription currently requires Gemini due to its file upload API. OpenAI Whisper integration is planned for future releases. For now, you can use:

  • Gemini for transcription (free)
  • OpenAI/others for analysis (premium quality)

Testing

The implementation has been thoroughly tested with:

  • Single provider configurations (Gemini-only, OpenAI-only)
  • Multi-provider setups with automatic fallback
  • Custom OpenAI-compatible API configurations
  • Error handling and provider detection

Documentation

  • Comprehensive setup guide in LLM_PROVIDERS.md
  • Updated .env.example with all configuration options
  • Troubleshooting section and migration guide included

Benefits

  • Universal Access: No longer limited to specific API providers
  • Cost Optimization: Mix free and paid services based on needs
  • High Availability: Automatic failover keeps service running
  • Global Accessibility: Support for various regional and alternative AI services

Closes #[issue-number]

Original prompt

This section details on the original issue you should resolve

<issue_title>[FEATURE] Add OpenAI API compatible LLM Support </issue_title>
<issue_description>## Feature Summary
Add chatgpt api + api of gemini + or anlthers llm

Problem Statement

Can be nice to not get limited only by gemini

Proposed Solution

Describe the solution you'd like
Because i have api key of chatgpt and others ia like perplexity and others easy to have the api key

Use Cases

Who would benefit from this feature?

  • [x ] Content creators
  • [x ] Social media managers
  • [ x] Video editors
  • [x ] Developers
  • Other: _not limitations on the api, a global open source best free app to clip anything

Specific use cases:

  1. As a [own cliper of tiktoi], I want [soport another api keys like chatgpt and others free apis easy to have] so that [benefit] all and achieve a intuitive plataform for all
  2. When [i dont have api key of gemini], I need [to use ny chatgpt api key o free api keys from gpt4free] to [acces to this tool]</issue_description>

Comments on the Issue (you are @copilot in this section)

@samyaksgupta Since you have mentioned globally open source app the most reliable option is to use Gemini as it's free for everyone and most importantly not everyone has openai keys/ any other "ia" there you mentioned, we will think about this in a later issue, but you can "soport" by contributing, pull the code and raise a PR , try getting a Gemini API Key from Google it's free @sdntsng Agree with @Owlock - should have OpenAI integration for LLM since most (all?) LLM providers are OpenAI API compatible @sdntsng *Agent Friendly Issue Summary*

#Feature Request: Add OpenAI-Compatible LLM API Endpoints for Universal Access

Feature Summary

Implement support for OpenAI-compatible LLM API endpoints (e.g., ChatGPT, Perplexity, and others) alongside the existing Gemini integration. This would allow users to configure and use a variety of LLM providers through a standardized OpenAI API format, enabling broader accessibility and flexibility.

Problem Statement

The current implementation is limited to Google's Gemini API, which restricts users who may not have access to a Gemini API key or prefer alternative providers. This creates barriers for users with keys from other services like OpenAI's ChatGPT or free/open-source alternatives, limiting the app's universality and adoption as an open-source tool for clipping and processing content from platforms like TikTok.

Proposed Solution

Add configurable LLM API endpoints that follow the OpenAI API specification as a standard interface. This would involve:

  • Allowing users to input API keys and base URLs for compatible providers (e.g., OpenAI's ChatGPT, Perplexity, or even free proxies like gpt4free).
  • Implementing a backend abstraction layer to route requests to the selected LLM provider while maintaining compatibility with the OpenAI format for seamless integration.
  • Supporting multiple providers simultaneously, with a fallback mechanism if one fails.
  • Ensuring the solution remains open-source and free, without imposing limitations on API usage beyond what the providers enforce.

This approach would make the app more inclusive, as users could easily switch between providers based on availability, cost, or performance.

Use Cases

This feature would benefit a wide range of users by removing API provider lock-in and promoting a truly universal, open-source clipping platform.

  • Content creators
  • Social media managers
  • Video editors
  • Developers
  • Other: Anyone seeking a global, open-source, free app for clipping and processing content without API restrictions.

Specific use cases:

  • As a TikTok clipper user, I want to support additional API keys like ChatGPT and other easily accessible free APIs so that I can benefit from diverse LLM capabilities and achieve an intuitive platform for all.
  • When I don't have a Gemini API key, I need to use my ChatGPT API key or free API keys from services like gpt4free to access this tool without interruptions.</comment_new>
Fixes #50

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@sdntsng
Copy link
Contributor

sdntsng commented Sep 27, 2025

FYI:

Feature Request: Add OpenAI-Compatible LLM API Endpoints for Universal Access

Feature Summary

Implement support for OpenAI-compatible LLM API endpoints (e.g., ChatGPT, Perplexity, and others) alongside the existing Gemini integration. This would allow users to configure and use a variety of LLM providers through a standardized OpenAI API format, enabling broader accessibility and flexibility.

Problem Statement

The current implementation is limited to Google's Gemini API, which restricts users who may not have access to a Gemini API key or prefer alternative providers. This creates barriers for users with keys from other services like OpenAI's ChatGPT or free/open-source alternatives, limiting the app's universality and adoption as an open-source tool for clipping and processing content from platforms like TikTok.

Proposed Solution

Add configurable LLM API endpoints that follow the OpenAI API specification as a standard interface. This would involve:

  • Allowing users to input API keys and base URLs for compatible providers (e.g., OpenAI's ChatGPT, Perplexity, or even free proxies like gpt4free).
  • Implementing a backend abstraction layer to route requests to the selected LLM provider while maintaining compatibility with the OpenAI format for seamless integration.
  • Supporting multiple providers simultaneously, with a fallback mechanism if one fails.
  • Ensuring the solution remains open-source and free, without imposing limitations on API usage beyond what the providers enforce.

This approach would make the app more inclusive, as users could easily switch between providers based on availability, cost, or performance.

Use Cases

This feature would benefit a wide range of users by removing API provider lock-in and promoting a truly universal, open-source clipping platform.

  • Content creators
  • Social media managers
  • Video editors
  • Developers
  • Other: Anyone seeking a global, open-source, free app for clipping and processing content without API restrictions.

Specific use cases:

  • As a TikTok clipper user, I want to support additional API keys like ChatGPT and other easily accessible free APIs so that I can benefit from diverse LLM capabilities and achieve an intuitive platform for all.
  • When I don't have a Gemini API key, I need to use my ChatGPT API key or free API keys from services like gpt4free to access this tool without interruptions.

Copilot AI and others added 2 commits September 27, 2025 21:01
Co-authored-by: sdntsng <19806109+sdntsng@users.noreply.github.com>
Co-authored-by: sdntsng <19806109+sdntsng@users.noreply.github.com>
Copilot AI changed the title [WIP] [FEATURE] Add OpenAI API compatible LLM Support Add OpenAI API compatible LLM support with automatic fallback Sep 27, 2025
Copilot AI requested a review from sdntsng September 27, 2025 21:07
@sdntsng sdntsng marked this pull request as ready for review January 22, 2026 14:23
Copilot AI review requested due to automatic review settings January 22, 2026 14:23
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements multi-provider LLM support for Vinci Clips, enabling the use of OpenAI, Perplexity, and other OpenAI-compatible APIs alongside the existing Google Gemini integration. The implementation includes intelligent provider selection with automatic fallback, maintains backward compatibility with existing Gemini configurations, and provides comprehensive documentation.

Changes:

  • Added new LLM abstraction layer to support multiple providers (Gemini, OpenAI, OpenAI-compatible APIs)
  • Implemented automatic provider fallback when primary provider fails
  • Added configuration endpoint to check current LLM provider status
  • Updated all LLM-dependent routes to use the new service abstraction
  • Comprehensive documentation for setup and migration

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
backend/src/services/llmService.js New abstraction layer providing unified interface for all LLM providers with fallback logic
backend/src/routes/upload.js Updated to use LLM service for transcription instead of direct Gemini API calls
backend/src/routes/import.js Updated to use LLM service for URL-imported video transcription
backend/src/routes/retry-transcription.js Updated to use LLM service for retry operations
backend/src/routes/analyze.js Updated to use LLM service for transcript analysis
backend/src/routes/llm-info.js New endpoint providing LLM provider configuration information
backend/src/routes/index.js Registered new LLM info route
backend/package.json Added OpenAI SDK dependency (v5.23.1)
backend/package-lock.json Dependency lock file updated for OpenAI package
backend/.env.example Updated with comprehensive LLM provider configuration examples
LLM_PROVIDERS.md New comprehensive documentation for LLM provider setup and usage
Files not reviewed (1)
  • backend/package-lock.json: Language not supported

Comment on lines +168 to +172
const content = response.choices[0].message.content;
const parsed = JSON.parse(content);

// OpenAI might return an object with clips array, normalize to array
return Array.isArray(parsed) ? parsed : (parsed.clips || []);
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OpenAI response normalization assumes the response will either be an array or have a 'clips' property. If OpenAI returns a different structure or an empty object, this will return an empty array without any error indication, potentially masking issues with the LLM response format. Consider adding validation to ensure the response contains expected data.

Suggested change
const content = response.choices[0].message.content;
const parsed = JSON.parse(content);
// OpenAI might return an object with clips array, normalize to array
return Array.isArray(parsed) ? parsed : (parsed.clips || []);
const content = response &&
Array.isArray(response.choices) &&
response.choices[0] &&
response.choices[0].message &&
response.choices[0].message.content;
if (!content) {
throw new Error('OpenAI response is missing message content for clip analysis.');
}
let parsed;
try {
parsed = JSON.parse(content);
} catch (err) {
throw new Error(`Failed to parse OpenAI JSON response for clip analysis: ${err.message}`);
}
// Normalize known-good formats and validate structure
if (Array.isArray(parsed)) {
return parsed;
}
if (parsed && typeof parsed === 'object') {
if (Array.isArray(parsed.clips)) {
return parsed.clips;
}
throw new Error('OpenAI JSON response for clip analysis is missing expected "clips" array.');
}
throw new Error('OpenAI JSON response for clip analysis has an unexpected format.');

Copilot uses AI. Check for mistakes.
Comment on lines +117 to +118
// Use the LLM service for transcription
const transcriptContent = await llmService.transcribeAudio(mp3DestPath, mp3FileName);
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message references "Gemini API or upload error" but the code now uses the LLM service abstraction which could be using OpenAI or other providers. The error message should be provider-agnostic to avoid confusion.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +19
router.get('/provider-info', async (req, res) => {
try {
const providerInfo = llmService.getProviderInfo();
res.status(200).json({
status: 'success',
data: providerInfo
});
} catch (error) {
console.error('Error getting provider info:', error);
res.status(500).json({
status: 'error',
error: 'Failed to get LLM provider information'
});
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getProviderInfo method is synchronous and doesn't throw errors, so wrapping it in a try-catch with async/await is unnecessary. The async keyword on the route handler is also not needed since there are no await calls. This could be simplified to a synchronous handler.

Suggested change
router.get('/provider-info', async (req, res) => {
try {
const providerInfo = llmService.getProviderInfo();
res.status(200).json({
status: 'success',
data: providerInfo
});
} catch (error) {
console.error('Error getting provider info:', error);
res.status(500).json({
status: 'error',
error: 'Failed to get LLM provider information'
});
}
router.get('/provider-info', (req, res) => {
const providerInfo = llmService.getProviderInfo();
res.status(200).json({
status: 'success',
data: providerInfo
});

Copilot uses AI. Check for mistakes.
Comment on lines +32 to +59
async analyzeTranscript(transcriptText, videoDuration, maxTimeFormatted) {
const prompt = `Given the following transcript, propose 3-5 video clips that would make engaging short content. The video is ${Math.floor(videoDuration / 60)}:${String(Math.floor(videoDuration % 60)).padStart(2, '0')} long.

CRITICAL CONSTRAINTS:
- Video duration is EXACTLY ${maxTimeFormatted} - DO NOT suggest any timestamps beyond this
- Each clip should be 30-90 seconds total duration
- All timestamps must be in MM:SS format and within 0:00 to ${maxTimeFormatted}

You can suggest two types of clips:

1. SINGLE SEGMENT clips: One continuous segment from start time to end time
2. MULTI-SEGMENT clips: Multiple segments that when combined tell a coherent story

For single segments: provide 'start' and 'end' times in MM:SS format.
For multi-segments: provide an array of segments in 'segments' field, each with 'start' and 'end' times.

VALIDATION RULES:
- Every timestamp must be ≤ ${maxTimeFormatted}
- Total duration must be 30-90 seconds
- Focus on complete thoughts or exchanges
- Ensure segments make sense when combined

Output format: JSON array where each object has:
- 'title': descriptive title
- For single segments: 'start' and 'end' fields
- For multi-segments: 'segments' array with objects containing 'start' and 'end'

Transcript: ${transcriptText}`;
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The transcript text is directly injected into the prompt without any length validation or truncation. Very long transcripts could exceed the LLM's token limits, causing API failures. Consider adding validation to check transcript length and either truncate or chunk long transcripts before analysis.

Copilot uses AI. Check for mistakes.
content: prompt
}
],
response_format: { type: 'json_object' },
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The response_format parameter with type 'json_object' requires the model to support JSON mode. Not all OpenAI-compatible APIs support this feature, and some older models like gpt-3.5-turbo may not reliably support it. This could cause failures when using alternative providers or certain OpenAI models. Consider adding error handling or making this parameter optional based on the provider/model being used.

Copilot uses AI. Check for mistakes.
Comment on lines +76 to +87
} catch (error) {
console.error(`LLM analysis failed with ${this.provider}:`, error);
// Try fallback if primary fails
if (this.provider === 'openai' && this.geminiClient) {
console.log('Falling back to Gemini...');
return await this.analyzeWithGemini(prompt);
} else if (this.provider === 'gemini' && this.openaiClient) {
console.log('Falling back to OpenAI...');
return await this.analyzeWithOpenAI(prompt);
}
throw error;
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback mechanism could create an infinite recursion if analyzeWithGemini or analyzeWithOpenAI throw an error that doesn't originate from the primary provider check. Consider tracking whether a fallback has already been attempted to prevent potential recursive calls.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +30
initializeProviders() {
// Initialize Gemini (default/fallback)
if (process.env.GEMINI_API_KEY) {
this.geminiClient = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
// Don't initialize file manager here - create it when needed
}

// Initialize OpenAI-compatible clients
if (process.env.OPENAI_API_KEY || process.env.LLM_API_KEY) {
const config = {
apiKey: process.env.OPENAI_API_KEY || process.env.LLM_API_KEY,
};

// Support custom base URL for OpenAI-compatible APIs
if (process.env.LLM_BASE_URL) {
config.baseURL = process.env.LLM_BASE_URL;
}

this.openaiClient = new OpenAI(config);
}
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No validation is performed on environment variables during initialization. Invalid API keys, malformed base URLs, or unsupported model names will only be detected at runtime when the first API call is made. Consider adding validation in initializeProviders to fail fast with clear error messages during service startup.

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +26
if (process.env.LLM_BASE_URL) {
config.baseURL = process.env.LLM_BASE_URL;
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LLM_BASE_URL environment variable is not validated for security. A malicious or misconfigured URL could redirect API requests to an untrusted server, potentially exposing API keys or sensitive data. Consider validating that the base URL uses HTTPS (except for localhost) and optionally maintaining a whitelist of allowed domains for production environments.

Copilot uses AI. Check for mistakes.
Comment on lines +254 to +255
// Export singleton instance
module.exports = new LLMService(); No newline at end of file
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The service is exported as a singleton instance, which means the provider configuration is determined at module load time. If environment variables change after the service is first imported, the configuration won't update. This could be problematic in testing scenarios or if configuration needs to change at runtime. Consider exporting the class and allowing consumers to instantiate as needed, or provide a method to reinitialize the service.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add OpenAI API compatible LLM Support

3 participants