shows more helpful errors when users' prefills are invalid during AWS streaming
This commit is contained in:
parent
96756d32f3
commit
9ce10b4f6a
|
@ -6,7 +6,6 @@ import { APIFormat, keyPool } from "../../../shared/key-management";
|
|||
import {
|
||||
copySseResponseHeaders,
|
||||
initializeSseStream,
|
||||
|
||||
} from "../../../shared/streaming";
|
||||
import type { logger } from "../../../logger";
|
||||
import { enqueue } from "../../queue";
|
||||
|
@ -15,7 +14,8 @@ import { getAwsEventStreamDecoder } from "./streaming/aws-event-stream-decoder";
|
|||
import { EventAggregator } from "./streaming/event-aggregator";
|
||||
import { SSEMessageTransformer } from "./streaming/sse-message-transformer";
|
||||
import { SSEStreamAdapter } from "./streaming/sse-stream-adapter";
|
||||
import { buildSpoofedSSE } from "./error-generator";
|
||||
import { buildSpoofedSSE, sendErrorToClient } from "./error-generator";
|
||||
import { BadRequestError } from "../../../shared/errors";
|
||||
|
||||
const pipelineAsync = promisify(pipeline);
|
||||
|
||||
|
@ -109,6 +109,18 @@ export const handleStreamedResponse: RawResponseBodyHandler = async (
|
|||
);
|
||||
req.retryCount++;
|
||||
await enqueue(req);
|
||||
} else if (err instanceof BadRequestError) {
|
||||
sendErrorToClient({
|
||||
req,
|
||||
res,
|
||||
options: {
|
||||
format: req.inboundApi,
|
||||
title: "Proxy streaming error (Bad Request)",
|
||||
message: `The API returned an error while streaming your request. Your prompt might not be formatted correctly.\n\n*${err.message}*`,
|
||||
reqId: req.id,
|
||||
model: req.body?.model,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const { message, stack, lastEvent } = err;
|
||||
const eventText = JSON.stringify(lastEvent, null, 2) ?? "undefined";
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Message } from "@smithy/eventstream-codec";
|
|||
import { APIFormat } from "../../../../shared/key-management";
|
||||
import { RetryableError } from "../index";
|
||||
import { buildSpoofedSSE } from "../error-generator";
|
||||
import { BadRequestError } from "../../../../shared/errors";
|
||||
|
||||
type SSEStreamAdapterOptions = TransformOptions & {
|
||||
contentType?: string;
|
||||
|
@ -59,8 +60,7 @@ export class SSEStreamAdapter extends Transform {
|
|||
return [`event: ${eventObj.type}`, `data: ${event}`].join(`\n`);
|
||||
}
|
||||
}
|
||||
// Intentional fallthrough, as non-JSON events may as well be errors
|
||||
// noinspection FallThroughInSwitchStatementJS
|
||||
// noinspection FallThroughInSwitchStatementJS -- non-JSON data is unexpected
|
||||
case "exception":
|
||||
case "error":
|
||||
const type = String(
|
||||
|
@ -72,16 +72,32 @@ export class SSEStreamAdapter extends Transform {
|
|||
"AWS request throttled after streaming has already started; retrying"
|
||||
);
|
||||
throw new RetryableError("AWS request throttled mid-stream");
|
||||
case "validationexception":
|
||||
try {
|
||||
const { message } = JSON.parse(bodyStr);
|
||||
this.log.error({ message }, "Received AWS validation error");
|
||||
this.emit(
|
||||
"error",
|
||||
new BadRequestError(`AWS validation error: ${message}`)
|
||||
);
|
||||
return null;
|
||||
} catch (error) {
|
||||
this.log.error(
|
||||
{ body: bodyStr, error },
|
||||
"Could not parse AWS validation error"
|
||||
);
|
||||
}
|
||||
// noinspection FallThroughInSwitchStatementJS -- who knows what this is
|
||||
default:
|
||||
this.log.error({ message, type }, "Received bad AWS stream event");
|
||||
let text;
|
||||
try {
|
||||
const { bytes } = JSON.parse(bodyStr);
|
||||
text = Buffer.from(bytes, "base64").toString("utf8");
|
||||
text = JSON.parse(bodyStr).message;
|
||||
} catch (error) {
|
||||
text = bodyStr;
|
||||
}
|
||||
const error: any = new Error(`Got mysterious error chunk: ${type}`);
|
||||
const error: any = new Error(
|
||||
`Got mysterious error chunk: [${type}] ${text}`
|
||||
);
|
||||
error.lastEvent = text;
|
||||
this.emit("error", error);
|
||||
return null;
|
||||
|
|
Loading…
Reference in New Issue