added multi-llm support#90
Conversation
|
@mxskeen is attempting to deploy a commit to the Hussain's Projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
Adds configurable provider endpoint + model selection to support OpenAI-compatible “multi-LLM” backends across the app’s AI features.
Changes:
- Persist new user settings (
apiBaseUrl,modelId) and return them via/api/getUserSettings. - Thread
apiBaseUrl/modelIdthrough UI components and AI request payloads. - Update the OpenAI API route to use a configurable
baseURLand selectablemodel.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/pages/api/openai.ts |
Accepts baseUrl/modelId and uses them to configure the OpenAI client and model. |
src/pages/api/getUserSettings.ts |
Returns apiBaseUrl and modelId as part of user settings. |
src/components/app/Settings.tsx |
Adds UI fields to edit/save Base URL and Model ID. |
src/components/app/ProblemsQueue.tsx |
Passes Base URL / Model ID into AI analyze + chat flows. |
src/components/app/ProblemModal.tsx |
Passes Base URL / Model ID into solution generation requests. |
src/components/app/Problem.tsx |
Passes Base URL / Model ID into AI analyze + chat flows. |
src/components/app/ChatWindow.tsx |
Includes Base URL / Model ID in requests to /api/openai. |
prisma/schema.prisma |
Adds apiBaseUrl and modelId fields to the User model with defaults. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const { question, solution, userSolution, userMessage, apiKey, baseUrl, modelId, mode = "chat" } = req.body; | ||
|
|
||
| const openai = new OpenAI({ | ||
| apiKey: apiKey, | ||
| baseURL: baseUrl || "https://api.openai.com/v1", | ||
| }); |
There was a problem hiding this comment.
baseUrl is taken directly from the request body and used as the OpenAI client baseURL. Because this route is unauthenticated, this creates an SSRF / proxy primitive and can also exfiltrate the caller-supplied apiKey to an arbitrary host via the Authorization header. Consider restricting baseUrl to an allowlist (or a server-side config), enforce https, and explicitly block localhost/private/metadata IP ranges; also consider rejecting non-POST requests here to reduce abuse surface.
| apiKey String? @default("null") | ||
| apiBaseUrl String? @default("https://api.openai.com/v1") | ||
| modelId String? @default("gpt-4o") |
There was a problem hiding this comment.
The Prisma schema adds apiBaseUrl and modelId, but there’s no corresponding migration checked in under prisma/migrations. If the project relies on migrations (it looks like it does), this will cause schema drift / deploy failures. Please generate and commit a migration for these new columns.
| type={isBaseUrlVisible ? "text" : "password"} | ||
| id="apiBaseUrl" | ||
| defaultValue={data.apiBaseUrl} | ||
| placeholder="https://api.openai.com/v1" | ||
| className="w-full px-3 py-2 bg-[#2A303C] border border-[#3A4150]/70 rounded-md shadow-sm outline-none focus:outline-none focus:border-[#06b6d4]/70 focus:ring-1 focus:ring-[#3b82f6]/50 transition-all duration-200 text-primary h-11" | ||
| style={{ outline: 'none' }} | ||
| /> | ||
| <button | ||
| type="button" | ||
| onClick={() => setIsBaseUrlVisible(!isBaseUrlVisible)} | ||
| className="absolute right-3 top-1/2 -translate-y-1/2 text-[#8A94A6] hover:text-[#ffffff] transition-colors" | ||
| > | ||
| {isBaseUrlVisible ? 'Hide' : 'Show'} | ||
| </button> |
There was a problem hiding this comment.
The Base URL field is rendered as type="password", but this value isn’t a secret. Using a password input can confuse users and password managers and harms accessibility. Consider using type="text" (and optionally keep a separate “reset to default” affordance) instead of hide/show behavior here.
| type={isBaseUrlVisible ? "text" : "password"} | |
| id="apiBaseUrl" | |
| defaultValue={data.apiBaseUrl} | |
| placeholder="https://api.openai.com/v1" | |
| className="w-full px-3 py-2 bg-[#2A303C] border border-[#3A4150]/70 rounded-md shadow-sm outline-none focus:outline-none focus:border-[#06b6d4]/70 focus:ring-1 focus:ring-[#3b82f6]/50 transition-all duration-200 text-primary h-11" | |
| style={{ outline: 'none' }} | |
| /> | |
| <button | |
| type="button" | |
| onClick={() => setIsBaseUrlVisible(!isBaseUrlVisible)} | |
| className="absolute right-3 top-1/2 -translate-y-1/2 text-[#8A94A6] hover:text-[#ffffff] transition-colors" | |
| > | |
| {isBaseUrlVisible ? 'Hide' : 'Show'} | |
| </button> | |
| type="text" | |
| id="apiBaseUrl" | |
| defaultValue={data.apiBaseUrl} | |
| placeholder="https://api.openai.com/v1" | |
| className="w-full px-3 py-2 bg-[#2A303C] border border-[#3A4150]/70 rounded-md shadow-sm outline-none focus:outline-none focus:border-[#06b6d4]/70 focus:ring-1 focus:ring-[#3b82f6]/50 transition-all duration-200 text-primary h-11" | |
| style={{ outline: 'none' }} | |
| /> |
| type={isModelIdVisible ? "text" : "password"} | ||
| id="modelId" | ||
| defaultValue={data.modelId} | ||
| placeholder="gpt-4o" | ||
| className="w-full px-3 py-2 bg-[#2A303C] border border-[#3A4150]/70 rounded-md shadow-sm outline-none focus:outline-none focus:border-[#06b6d4]/70 focus:ring-1 focus:ring-[#3b82f6]/50 transition-all duration-200 text-primary h-11" | ||
| style={{ outline: 'none' }} | ||
| /> | ||
| <button | ||
| type="button" | ||
| onClick={() => setIsModelIdVisible(!isModelIdVisible)} | ||
| className="absolute right-3 top-1/2 -translate-y-1/2 text-[#8A94A6] hover:text-[#ffffff] transition-colors" | ||
| > | ||
| {isModelIdVisible ? 'Hide' : 'Show'} | ||
| </button> |
There was a problem hiding this comment.
The Model ID field is rendered as type="password", but model identifiers aren’t sensitive. This makes it harder to review/edit the value and can interfere with autofill/password managers. Consider switching this input to type="text" and dropping the hide/show toggle.
| type={isModelIdVisible ? "text" : "password"} | |
| id="modelId" | |
| defaultValue={data.modelId} | |
| placeholder="gpt-4o" | |
| className="w-full px-3 py-2 bg-[#2A303C] border border-[#3A4150]/70 rounded-md shadow-sm outline-none focus:outline-none focus:border-[#06b6d4]/70 focus:ring-1 focus:ring-[#3b82f6]/50 transition-all duration-200 text-primary h-11" | |
| style={{ outline: 'none' }} | |
| /> | |
| <button | |
| type="button" | |
| onClick={() => setIsModelIdVisible(!isModelIdVisible)} | |
| className="absolute right-3 top-1/2 -translate-y-1/2 text-[#8A94A6] hover:text-[#ffffff] transition-colors" | |
| > | |
| {isModelIdVisible ? 'Hide' : 'Show'} | |
| </button> | |
| type="text" | |
| id="modelId" | |
| defaultValue={data.modelId} | |
| placeholder="gpt-4o" | |
| className="w-full px-3 py-2 bg-[#2A303C] border border-[#3A4150]/70 rounded-md shadow-sm outline-none focus:outline-none focus:border-[#06b6d4]/70 focus:ring-1 focus:ring-[#3b82f6]/50 transition-all duration-200 text-primary h-11" | |
| style={{ outline: 'none' }} | |
| /> |
|
hey @hussiiii, loved the project. added multi-llm support in the project, right now default is openai with gpt-4o. but i added option of adding custom opeai-compatible model, merging this pr will add this feature. so user can add any openai-compatible models, like open source models too. Also When you deploy this with your database configured, run: npx prisma migrate dev --name add_api_config thanks |
Description
Closes #{{ ISSUE_NUMBER }}
Checklist
Screenshots / Logs (optional)
Type of Change