|
@@ -24,6 +24,7 @@ import { DEFAULT_HEADERS } from "./constants"
|
|
|
import { BaseProvider } from "./base-provider"
|
|
import { BaseProvider } from "./base-provider"
|
|
|
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
|
|
import type { SingleCompletionHandler, ApiHandlerCreateMessageMetadata } from "../index"
|
|
|
import { getApiRequestTimeout } from "./utils/timeout-config"
|
|
import { getApiRequestTimeout } from "./utils/timeout-config"
|
|
|
|
|
+import { handleOpenAIError } from "./utils/openai-error-handler"
|
|
|
|
|
|
|
|
// TODO: Rename this to OpenAICompatibleHandler. Also, I think the
|
|
// TODO: Rename this to OpenAICompatibleHandler. Also, I think the
|
|
|
// `OpenAINativeHandler` can subclass from this, since it's obviously
|
|
// `OpenAINativeHandler` can subclass from this, since it's obviously
|
|
@@ -31,6 +32,7 @@ import { getApiRequestTimeout } from "./utils/timeout-config"
|
|
|
export class OpenAiHandler extends BaseProvider implements SingleCompletionHandler {
|
|
export class OpenAiHandler extends BaseProvider implements SingleCompletionHandler {
|
|
|
protected options: ApiHandlerOptions
|
|
protected options: ApiHandlerOptions
|
|
|
private client: OpenAI
|
|
private client: OpenAI
|
|
|
|
|
+ private readonly providerName = "OpenAI"
|
|
|
|
|
|
|
|
constructor(options: ApiHandlerOptions) {
|
|
constructor(options: ApiHandlerOptions) {
|
|
|
super()
|
|
super()
|
|
@@ -174,10 +176,15 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|
|
// Add max_tokens if needed
|
|
// Add max_tokens if needed
|
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
|
|
|
|
|
|
- const stream = await this.client.chat.completions.create(
|
|
|
|
|
- requestOptions,
|
|
|
|
|
- isAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ let stream
|
|
|
|
|
+ try {
|
|
|
|
|
+ stream = await this.client.chat.completions.create(
|
|
|
|
|
+ requestOptions,
|
|
|
|
|
+ isAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw handleOpenAIError(error, this.providerName)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
const matcher = new XmlMatcher(
|
|
const matcher = new XmlMatcher(
|
|
|
"think",
|
|
"think",
|
|
@@ -236,10 +243,15 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|
|
// Add max_tokens if needed
|
|
// Add max_tokens if needed
|
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
|
|
|
|
|
|
- const response = await this.client.chat.completions.create(
|
|
|
|
|
- requestOptions,
|
|
|
|
|
- this._isAzureAiInference(modelUrl) ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ let response
|
|
|
|
|
+ try {
|
|
|
|
|
+ response = await this.client.chat.completions.create(
|
|
|
|
|
+ requestOptions,
|
|
|
|
|
+ this._isAzureAiInference(modelUrl) ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw handleOpenAIError(error, this.providerName)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
yield {
|
|
yield {
|
|
|
type: "text",
|
|
type: "text",
|
|
@@ -281,15 +293,20 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|
|
// Add max_tokens if needed
|
|
// Add max_tokens if needed
|
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
|
|
|
|
|
|
- const response = await this.client.chat.completions.create(
|
|
|
|
|
- requestOptions,
|
|
|
|
|
- isAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ let response
|
|
|
|
|
+ try {
|
|
|
|
|
+ response = await this.client.chat.completions.create(
|
|
|
|
|
+ requestOptions,
|
|
|
|
|
+ isAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw handleOpenAIError(error, this.providerName)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
return response.choices[0]?.message.content || ""
|
|
return response.choices[0]?.message.content || ""
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
if (error instanceof Error) {
|
|
if (error instanceof Error) {
|
|
|
- throw new Error(`OpenAI completion error: ${error.message}`)
|
|
|
|
|
|
|
+ throw new Error(`${this.providerName} completion error: ${error.message}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
throw error
|
|
throw error
|
|
@@ -327,10 +344,15 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|
|
// This allows O3 models to limit response length when includeMaxTokens is enabled
|
|
// This allows O3 models to limit response length when includeMaxTokens is enabled
|
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
|
|
|
|
|
|
- const stream = await this.client.chat.completions.create(
|
|
|
|
|
- requestOptions,
|
|
|
|
|
- methodIsAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ let stream
|
|
|
|
|
+ try {
|
|
|
|
|
+ stream = await this.client.chat.completions.create(
|
|
|
|
|
+ requestOptions,
|
|
|
|
|
+ methodIsAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw handleOpenAIError(error, this.providerName)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
yield* this.handleStreamResponse(stream)
|
|
yield* this.handleStreamResponse(stream)
|
|
|
} else {
|
|
} else {
|
|
@@ -352,10 +374,15 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|
|
// This allows O3 models to limit response length when includeMaxTokens is enabled
|
|
// This allows O3 models to limit response length when includeMaxTokens is enabled
|
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
this.addMaxTokensIfNeeded(requestOptions, modelInfo)
|
|
|
|
|
|
|
|
- const response = await this.client.chat.completions.create(
|
|
|
|
|
- requestOptions,
|
|
|
|
|
- methodIsAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ let response
|
|
|
|
|
+ try {
|
|
|
|
|
+ response = await this.client.chat.completions.create(
|
|
|
|
|
+ requestOptions,
|
|
|
|
|
+ methodIsAzureAiInference ? { path: OPENAI_AZURE_AI_INFERENCE_PATH } : {},
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ throw handleOpenAIError(error, this.providerName)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
yield {
|
|
yield {
|
|
|
type: "text",
|
|
type: "text",
|