feat(api): implement retry logic for Mistral API calls in receipt import and AI services
This commit is contained in:
@@ -47,38 +47,56 @@ Regler:
|
||||
|
||||
const userPrompt = `Produkt: "${productName}"`;
|
||||
|
||||
let raw: string;
|
||||
try {
|
||||
const response = await fetch(MISTRAL_API_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: MODEL,
|
||||
messages: [
|
||||
{ role: 'system', content: systemPrompt },
|
||||
{ role: 'user', content: userPrompt },
|
||||
],
|
||||
max_tokens: 100,
|
||||
temperature: 0.1,
|
||||
response_format: { type: 'json_object' },
|
||||
}),
|
||||
});
|
||||
let raw = '';
|
||||
const MAX_RETRIES = 3;
|
||||
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
||||
try {
|
||||
const response = await fetch(MISTRAL_API_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: MODEL,
|
||||
messages: [
|
||||
{ role: 'system', content: systemPrompt },
|
||||
{ role: 'user', content: userPrompt },
|
||||
],
|
||||
max_tokens: 100,
|
||||
temperature: 0.1,
|
||||
response_format: { type: 'json_object' },
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const err = await response.text();
|
||||
this.logger.error(`Mistral API-fel: ${response.status} ${err}`);
|
||||
throw new ServiceUnavailableException('AI-tjänsten svarade inte korrekt');
|
||||
if (response.status === 503 || response.status === 429) {
|
||||
const err = await response.text();
|
||||
this.logger.warn(`Mistral API ${response.status} (försök ${attempt}/${MAX_RETRIES}): ${err}`);
|
||||
if (attempt < MAX_RETRIES) {
|
||||
await new Promise((r) => setTimeout(r, attempt * 1500));
|
||||
continue;
|
||||
}
|
||||
throw new ServiceUnavailableException('AI-tjänsten är tillfälligt otillgänglig, försök igen');
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const err = await response.text();
|
||||
this.logger.error(`Mistral API-fel: ${response.status} ${err}`);
|
||||
throw new ServiceUnavailableException('AI-tjänsten svarade inte korrekt');
|
||||
}
|
||||
|
||||
const data = await response.json() as { choices: { message: { content: string } }[] };
|
||||
raw = data.choices?.[0]?.message?.content ?? '';
|
||||
break;
|
||||
} catch (err) {
|
||||
if (err instanceof ServiceUnavailableException) throw err;
|
||||
this.logger.error(`Mistral fetch-fel (försök ${attempt}/${MAX_RETRIES}): ${String(err)}`);
|
||||
if (attempt < MAX_RETRIES) {
|
||||
await new Promise((r) => setTimeout(r, attempt * 1500));
|
||||
continue;
|
||||
}
|
||||
throw new ServiceUnavailableException('Kunde inte nå AI-tjänsten');
|
||||
}
|
||||
|
||||
const data = await response.json() as { choices: { message: { content: string } }[] };
|
||||
raw = data.choices?.[0]?.message?.content ?? '';
|
||||
} catch (err) {
|
||||
if (err instanceof ServiceUnavailableException) throw err;
|
||||
this.logger.error(`Mistral fetch-fel: ${String(err)}`);
|
||||
throw new ServiceUnavailableException('Kunde inte nå AI-tjänsten');
|
||||
}
|
||||
|
||||
// Parsa och validera AI-svaret
|
||||
|
||||
Reference in New Issue
Block a user