fix(email): support legacy AI gateway models
This commit is contained in:
@@ -75,17 +75,14 @@ export function buildSuggestionMail(message: any) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function suggestEmailEntities(message: any, allCandidates: EntityCandidate[]) {
|
||||
const central = Boolean(secrets.FEDEO_CENTRAL_SERVICES_ENABLED && centralServicesClient.configured())
|
||||
if (!central && !secrets.OPENAI_API_KEY) {
|
||||
throw Object.assign(new Error("Die KI-Erkennung ist noch nicht konfiguriert."), { statusCode: 503 })
|
||||
}
|
||||
const mail = buildSuggestionMail(message)
|
||||
const candidates = selectCandidates(allCandidates, JSON.stringify(mail))
|
||||
if (!candidates.length) return []
|
||||
const request: any = {
|
||||
model: "gpt-5.6-luna",
|
||||
reasoning_effort: "none",
|
||||
export function buildEntitySuggestionRequest(
|
||||
mail: ReturnType<typeof buildSuggestionMail>,
|
||||
candidates: EntityCandidate[],
|
||||
model = "gpt-5.6-luna",
|
||||
) {
|
||||
return {
|
||||
model,
|
||||
...(model.startsWith("gpt-5") ? { reasoning_effort: "none" } : {}),
|
||||
store: false,
|
||||
max_completion_tokens: 1500,
|
||||
response_format: zodResponseFormat(suggestionFormat as any, "email_entity_suggestions"),
|
||||
@@ -94,9 +91,35 @@ export async function suggestEmailEntities(message: any, allCandidates: EntityCa
|
||||
{ role: "user", content: JSON.stringify({ mail, candidates }) },
|
||||
],
|
||||
}
|
||||
const completion = central
|
||||
? await centralServicesClient.aiChatCompletions(request)
|
||||
: await new OpenAI({ apiKey: secrets.OPENAI_API_KEY, timeout: 45000, maxRetries: 0 }).chat.completions.create(request)
|
||||
}
|
||||
|
||||
export function shouldRetryWithLegacyAiModel(error: any) {
|
||||
return [400, 404, 422, 500, 502].includes(Number(error?.status))
|
||||
}
|
||||
|
||||
export async function suggestEmailEntities(message: any, allCandidates: EntityCandidate[]) {
|
||||
const central = Boolean(secrets.FEDEO_CENTRAL_SERVICES_ENABLED && centralServicesClient.configured())
|
||||
if (!central && !secrets.OPENAI_API_KEY) {
|
||||
throw Object.assign(new Error("Die KI-Erkennung ist noch nicht konfiguriert."), { statusCode: 503 })
|
||||
}
|
||||
const mail = buildSuggestionMail(message)
|
||||
const candidates = selectCandidates(allCandidates, JSON.stringify(mail))
|
||||
if (!candidates.length) return []
|
||||
const request: any = buildEntitySuggestionRequest(mail, candidates)
|
||||
let completion: any
|
||||
if (central) {
|
||||
try {
|
||||
completion = await centralServicesClient.aiChatCompletions(request)
|
||||
} catch (error: any) {
|
||||
if (!shouldRetryWithLegacyAiModel(error)) throw error
|
||||
completion = await centralServicesClient.aiChatCompletions(
|
||||
buildEntitySuggestionRequest(mail, candidates, "gpt-4o-mini"),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
completion = await new OpenAI({ apiKey: secrets.OPENAI_API_KEY, timeout: 45000, maxRetries: 0 })
|
||||
.chat.completions.create(request)
|
||||
}
|
||||
const choice = completion.choices?.[0]
|
||||
if (choice?.finish_reason !== "stop" || choice?.message?.refusal || !choice?.message?.content) {
|
||||
throw new Error("Die KI konnte keine vollständige Analyse liefern. Bitte erneut versuchen.")
|
||||
|
||||
@@ -2,8 +2,10 @@ import assert from "node:assert/strict"
|
||||
import test from "node:test"
|
||||
import {
|
||||
buildSuggestionMail,
|
||||
buildEntitySuggestionRequest,
|
||||
dismissEntitySuggestion,
|
||||
selectCandidates,
|
||||
shouldRetryWithLegacyAiModel,
|
||||
validateSuggestions,
|
||||
type EntityCandidate,
|
||||
} from "../src/modules/email/email.entity-suggestions"
|
||||
@@ -69,3 +71,22 @@ test("dismisses only the selected entity suggestion", () => {
|
||||
)
|
||||
assert.deepEqual(dismissEntitySuggestion(null, "customers", 1), [])
|
||||
})
|
||||
|
||||
test("uses Luna by default and omits reasoning effort for the legacy fallback", () => {
|
||||
const request = buildEntitySuggestionRequest(buildSuggestionMail({ subject: "Test" }), [customer])
|
||||
assert.equal(request.model, "gpt-5.6-luna")
|
||||
assert.equal(request.reasoning_effort, "none")
|
||||
|
||||
const fallback = buildEntitySuggestionRequest(buildSuggestionMail({ subject: "Test" }), [customer], "gpt-4o-mini")
|
||||
assert.equal(fallback.model, "gpt-4o-mini")
|
||||
assert.equal("reasoning_effort" in fallback, false)
|
||||
})
|
||||
|
||||
test("retries model compatibility errors without retrying auth, rate-limit, or configuration errors", () => {
|
||||
for (const status of [400, 404, 422, 500, 502]) {
|
||||
assert.equal(shouldRetryWithLegacyAiModel({ status }), true)
|
||||
}
|
||||
for (const status of [401, 403, 429, 503]) {
|
||||
assert.equal(shouldRetryWithLegacyAiModel({ status }), false)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user