Switch AI defaults to OpenAI gpt-4.1-nano.

Prefer the cheapest ChatGPT model that supports our JSON completions, and skip custom temperature for gpt-5/o-series models.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-10 20:33:43 +03:30
co-authored by Cursor
parent 0743063c15
commit 23ba6344f6
2 changed files with 30 additions and 14 deletions
+4 -4
View File
@@ -66,12 +66,12 @@ OLD_S3_FORCE_PATH_STYLE=true
OLD_S3_ACCESS_KEY_ID= OLD_S3_ACCESS_KEY_ID=
OLD_S3_SECRET_ACCESS_KEY= OLD_S3_SECRET_ACCESS_KEY=
# AI product generation (use Groq free tier or OpenAI) # AI product / category generation (OpenAI preferred; Groq optional fallback)
AI_PROVIDER=groq AI_PROVIDER=openai
OPENAI_API_KEY=
OPENAI_MODEL=gpt-4.1-nano
GROQ_API_KEY= GROQ_API_KEY=
GROQ_MODEL=llama-3.3-70b-versatile GROQ_MODEL=llama-3.3-70b-versatile
OPENAI_API_KEY=
OPENAI_MODEL=gpt-4o-mini
MEDIA_MAX_FILE_SIZE_MB=10 MEDIA_MAX_FILE_SIZE_MB=10
+26 -10
View File
@@ -38,31 +38,47 @@ export function resolveAiProvider(config: ConfigService): AiProviderConfig {
return { return {
apiKey: openAiKey, apiKey: openAiKey,
baseUrl: 'https://api.openai.com/v1', baseUrl: 'https://api.openai.com/v1',
model: config.get<string>('OPENAI_MODEL')?.trim() || 'gpt-4o-mini', model: config.get<string>('OPENAI_MODEL')?.trim() || 'gpt-4.1-nano',
}; };
} }
function supportsCustomTemperature(model: string): boolean {
// gpt-5 / o-series chat models only accept the API default temperature.
const id = model.trim().toLowerCase();
return !(
id.startsWith('gpt-5') ||
id.startsWith('o1') ||
id.startsWith('o3') ||
id.startsWith('o4')
);
}
export async function requestAiJsonCompletion( export async function requestAiJsonCompletion(
provider: AiProviderConfig, provider: AiProviderConfig,
systemPrompt: string, systemPrompt: string,
userPrompt: string, userPrompt: string,
temperature = 0.4, temperature = 0.4,
): Promise<string> { ): Promise<string> {
const body: Record<string, unknown> = {
model: provider.model,
response_format: { type: 'json_object' },
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt },
],
};
if (supportsCustomTemperature(provider.model)) {
body.temperature = temperature;
}
const response = await fetch(`${provider.baseUrl}/chat/completions`, { const response = await fetch(`${provider.baseUrl}/chat/completions`, {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: `Bearer ${provider.apiKey}`, Authorization: `Bearer ${provider.apiKey}`,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify(body),
model: provider.model,
temperature,
response_format: { type: 'json_object' },
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt },
],
}),
}); });
if (!response.ok) { if (!response.ok) {