feat(ai-moderation): implement error handling and robust streaming for llmClient
Wrap the LLM completion logic in a try-catch block to provide detailed error logging, including status codes and raw response data, when API requests fail. - Add comprehensive error logging for failed LLM API calls. - Ensure streaming responses are correctly aggregated and returned even when wrapped in error handling logic.
This commit is contained in:
@@ -100,46 +100,59 @@ export async function llmChat(
|
|||||||
return retryWithBackoff(
|
return retryWithBackoff(
|
||||||
async () => {
|
async () => {
|
||||||
return withLlmConcurrency(async () => {
|
return withLlmConcurrency(async () => {
|
||||||
const response = await client.chat.completions.create(params);
|
try {
|
||||||
if (stream) {
|
const response = await client.chat.completions.create(params);
|
||||||
let content = "";
|
if (stream) {
|
||||||
let finishReason = "stop";
|
let content = "";
|
||||||
for await (const chunk of response as any) {
|
let finishReason = "stop";
|
||||||
const choice = chunk?.choices?.[0];
|
for await (const chunk of response as any) {
|
||||||
|
const choice = chunk?.choices?.[0];
|
||||||
// Dynamic parsing to support multiple providers (OpenAI, Ollama, Groq, Anthropic via proxy, etc.)
|
|
||||||
const textChunk =
|
|
||||||
choice?.delta?.content ||
|
|
||||||
choice?.message?.content ||
|
|
||||||
choice?.text ||
|
|
||||||
chunk?.message?.content ||
|
|
||||||
chunk?.response ||
|
|
||||||
chunk?.content ||
|
|
||||||
"";
|
|
||||||
|
|
||||||
content += textChunk;
|
// Dynamic parsing to support multiple providers (OpenAI, Ollama, Groq, Anthropic via proxy, etc.)
|
||||||
|
const textChunk =
|
||||||
const fr = choice?.finish_reason || chunk?.finish_reason;
|
choice?.delta?.content ||
|
||||||
if (fr) {
|
choice?.message?.content ||
|
||||||
finishReason = fr;
|
choice?.text ||
|
||||||
|
chunk?.message?.content ||
|
||||||
|
chunk?.response ||
|
||||||
|
chunk?.content ||
|
||||||
|
"";
|
||||||
|
|
||||||
|
content += textChunk;
|
||||||
|
|
||||||
|
const fr = choice?.finish_reason || chunk?.finish_reason;
|
||||||
|
if (fr) {
|
||||||
|
finishReason = fr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return {
|
||||||
|
id: 'stream-aggregated',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
message: { role: 'assistant', content, refusal: null },
|
||||||
|
finish_reason: finishReason,
|
||||||
|
index: 0,
|
||||||
|
logprobs: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
created: Math.floor(Date.now() / 1000),
|
||||||
|
model: model,
|
||||||
|
object: 'chat.completion',
|
||||||
|
} as OpenAI.Chat.Completions.ChatCompletion;
|
||||||
}
|
}
|
||||||
return {
|
return response as OpenAI.Chat.Completions.ChatCompletion;
|
||||||
id: 'stream-aggregated',
|
} catch (error: any) {
|
||||||
choices: [
|
log.error(
|
||||||
{
|
{
|
||||||
message: { role: 'assistant', content, refusal: null },
|
error: error.message,
|
||||||
finish_reason: finishReason,
|
status: error.status,
|
||||||
index: 0,
|
rawResponse: error.error || error.body || error.response?.data || "N/A",
|
||||||
logprobs: null,
|
model
|
||||||
},
|
},
|
||||||
],
|
"LLM API request failed"
|
||||||
created: Math.floor(Date.now() / 1000),
|
);
|
||||||
model: model,
|
throw error;
|
||||||
object: 'chat.completion',
|
|
||||||
} as OpenAI.Chat.Completions.ChatCompletion;
|
|
||||||
}
|
}
|
||||||
return response as OpenAI.Chat.Completions.ChatCompletion;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user