Skip to content

Commit 87bfc44

Browse files
authored
Merge branch 'main' into chore/ignore-model-details-camel-case-conversion
2 parents 70a734f + 5acd856 commit 87bfc44

22 files changed

+1116
-181
lines changed

src/globals.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,9 @@ export const documentMimeTypes = [
229229
fileExtensionMimeTypeMap.md,
230230
fileExtensionMimeTypeMap.txt,
231231
];
232+
233+
export enum BatchEndpoints {
234+
CHAT_COMPLETIONS = '/v1/chat/completions',
235+
COMPLETIONS = '/v1/completions',
236+
EMBEDDINGS = '/v1/embeddings',
237+
}

src/handlers/handlerUtils.ts

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -667,13 +667,18 @@ export async function tryTargetsRecursively(
667667
`${currentJsonPath}.targets[${originalIndex}]`,
668668
currentInheritedConfig
669669
);
670-
if (response?.headers.get('x-portkey-gateway-exception') === 'true') {
671-
break;
672-
}
670+
const codes = currentTarget.strategy?.onStatusCodes;
671+
const gatewayException =
672+
response?.headers.get('x-portkey-gateway-exception') === 'true';
673673
if (
674-
response?.ok &&
675-
!currentTarget.strategy?.onStatusCodes?.includes(response?.status)
674+
// If onStatusCodes is provided, and the response status is not in the list
675+
(Array.isArray(codes) && !codes.includes(response?.status)) ||
676+
// If onStatusCodes is not provided, and the response is ok
677+
(!codes && response?.ok) ||
678+
// If the response is a gateway exception
679+
gatewayException
676680
) {
681+
// Skip the fallback
677682
break;
678683
}
679684
}
@@ -790,53 +795,35 @@ export async function tryTargetsRecursively(
790795
// tryPost always returns a Response.
791796
// TypeError will check for all unhandled exceptions.
792797
// GatewayError will check for all handled exceptions which cannot allow the request to proceed.
793-
if (
794-
error instanceof TypeError ||
795-
error instanceof GatewayError ||
796-
!error.response ||
797-
(error.response && !(error.response instanceof Response))
798-
) {
799-
console.error(
800-
'tryTargetsRecursively error: ',
801-
error.message,
802-
error.cause,
803-
error.stack
804-
);
805-
const errorMessage =
806-
error instanceof GatewayError
807-
? error.message
808-
: 'Something went wrong';
809-
response = new Response(
810-
JSON.stringify({
811-
status: 'failure',
812-
message: errorMessage,
813-
}),
814-
{
815-
status: 500,
816-
headers: {
817-
'content-type': 'application/json',
818-
// Add this header so that the fallback loop can be interrupted if its an exception.
819-
'x-portkey-gateway-exception': 'true',
820-
},
821-
}
822-
);
823-
} else {
824-
response = error.response;
825-
if (isHandlingCircuitBreaker) {
826-
await c.get('recordCircuitBreakerFailure')?.(
827-
env(c),
828-
currentInheritedConfig.id,
829-
currentTarget.cbConfig,
830-
currentJsonPath,
831-
response.status
832-
);
798+
console.error(
799+
'tryTargetsRecursively error: ',
800+
error.message,
801+
error.cause,
802+
error.stack
803+
);
804+
const errorMessage =
805+
error instanceof GatewayError
806+
? error.message
807+
: 'Something went wrong';
808+
response = new Response(
809+
JSON.stringify({
810+
status: 'failure',
811+
message: errorMessage,
812+
}),
813+
{
814+
status: 500,
815+
headers: {
816+
'content-type': 'application/json',
817+
// Add this header so that the fallback loop can be interrupted if its an exception.
818+
'x-portkey-gateway-exception': 'true',
819+
},
833820
}
834-
}
821+
);
835822
}
836823
break;
837824
}
838825

839-
return response;
826+
return response!;
840827
}
841828

842829
export function constructConfigFromRequestHeaders(
@@ -944,10 +931,13 @@ export function constructConfigFromRequestHeaders(
944931
requestHeaders[`x-${POWERED_BY}-vertex-storage-bucket-name`],
945932
filename: requestHeaders[`x-${POWERED_BY}-provider-file-name`],
946933
vertexModelName: requestHeaders[`x-${POWERED_BY}-provider-model`],
934+
vertexBatchEndpoint:
935+
requestHeaders[`x-${POWERED_BY}-provider-batch-endpoint`],
947936
};
948937

949938
const fireworksConfig = {
950939
fireworksAccountId: requestHeaders[`x-${POWERED_BY}-fireworks-account-id`],
940+
fireworksFileLength: requestHeaders[`x-${POWERED_BY}-file-upload-size`],
951941
};
952942

953943
const anthropicConfig = {

src/handlers/services/responseService.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,6 @@ export class ResponseService {
6262

6363
this.updateHeaders(finalMappedResponse, cache.cacheStatus, retryAttempt);
6464

65-
if (!finalMappedResponse.ok) {
66-
const errorObj: any = new Error(await finalMappedResponse.clone().text());
67-
errorObj.status = finalMappedResponse.status;
68-
errorObj.response = finalMappedResponse;
69-
throw errorObj;
70-
}
71-
7265
return {
7366
response: finalMappedResponse,
7467
responseJson,

src/handlers/streamHandlerUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ export function createLineSplitter(): TransformStream {
309309
leftover = lines.pop() || '';
310310
for (const line of lines) {
311311
if (line.trim()) {
312-
controller.enqueue(line);
312+
controller.enqueue(line.trim());
313313
}
314314
}
315315
return;

src/providers/deepseek/chatComplete.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export const DeepSeekChatCompleteConfig: ProviderConfig = {
2727
});
2828
},
2929
},
30+
response_format: {
31+
param: 'response_format',
32+
default: null,
33+
},
3034
max_tokens: {
3135
param: 'max_tokens',
3236
default: 100,

src/providers/fireworks-ai/api.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,23 @@ const FireworksAIAPIConfig: ProviderAPIConfig = {
2121
Accept: 'application/json',
2222
};
2323
},
24-
getEndpoint: ({ fn, gatewayRequestBodyJSON: gatewayRequestBody, c }) => {
24+
getEndpoint: ({
25+
fn,
26+
gatewayRequestBodyJSON: gatewayRequestBody,
27+
c,
28+
gatewayRequestURL,
29+
}) => {
2530
const model = gatewayRequestBody?.model;
31+
32+
const jobIdIndex = ['cancelFinetune'].includes(fn ?? '') ? -2 : -1;
33+
const jobId = gatewayRequestURL.split('/').at(jobIdIndex);
34+
35+
const url = new URL(gatewayRequestURL);
36+
const params = url.searchParams;
37+
38+
const size = params.get('limit') ?? 50;
39+
const page = params.get('after') ?? '1';
40+
2641
switch (fn) {
2742
case 'complete':
2843
return '/completions';
@@ -33,7 +48,7 @@ const FireworksAIAPIConfig: ProviderAPIConfig = {
3348
case 'imageGenerate':
3449
return `/image_generation/${model}`;
3550
case 'uploadFile':
36-
return `/datasets`;
51+
return '';
3752
case 'retrieveFile': {
3853
const datasetId = c.req.param('id');
3954
return `/datasets/${datasetId}`;
@@ -45,13 +60,13 @@ const FireworksAIAPIConfig: ProviderAPIConfig = {
4560
return `/datasets/${datasetId}`;
4661
}
4762
case 'createFinetune':
48-
return `/fineTuningJobs`;
63+
return `/supervisedFineTuningJobs`;
4964
case 'retrieveFinetune':
50-
return `/fineTuningJobs/${c.req.param('jobId')}`;
65+
return `/supervisedFineTuningJobs/${jobId}`;
5166
case 'listFinetunes':
52-
return `/fineTuningJobs`;
67+
return `/supervisedFineTuningJobs?pageToken=${page}&pageSize=${size}`;
5368
case 'cancelFinetune':
54-
return `/fineTuningJobs/${c.req.param('jobId')}`;
69+
return `/supervisedFineTuningJobs/${jobId}`;
5570
default:
5671
return '';
5772
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { FIREWORKS_AI } from '../../globals';
2+
import { Params } from '../../types/requestBody';
3+
import { RequestHandler } from '../types';
4+
import FireworksAIAPIConfig from './api';
5+
import { fireworkFinetuneToOpenAIFinetune } from './utils';
6+
7+
export const FireworkCancelFinetuneResponseTransform = (
8+
response: any,
9+
status: number
10+
) => {
11+
if (status !== 200) {
12+
const error = response?.error || 'Failed to cancel finetune';
13+
return new Response(JSON.stringify({ error: { message: error } }), {
14+
status: status || 500,
15+
});
16+
}
17+
18+
return fireworkFinetuneToOpenAIFinetune(response);
19+
};
20+
21+
export const FireworksCancelFinetuneRequestHandler: RequestHandler<
22+
Params
23+
> = async ({ requestBody, requestURL, providerOptions, c }) => {
24+
const headers = await FireworksAIAPIConfig.headers({
25+
c,
26+
fn: 'cancelFinetune',
27+
providerOptions,
28+
transformedRequestUrl: requestURL,
29+
transformedRequestBody: requestBody,
30+
});
31+
32+
const baseURL = await FireworksAIAPIConfig.getBaseURL({
33+
c,
34+
gatewayRequestURL: requestURL,
35+
providerOptions,
36+
});
37+
38+
const endpoint = FireworksAIAPIConfig.getEndpoint({
39+
c,
40+
fn: 'cancelFinetune',
41+
gatewayRequestBodyJSON: requestBody,
42+
gatewayRequestURL: requestURL,
43+
providerOptions,
44+
});
45+
46+
try {
47+
const request = await fetch(baseURL + endpoint, {
48+
method: 'DELETE',
49+
headers,
50+
body: JSON.stringify(requestBody),
51+
});
52+
53+
if (!request.ok) {
54+
const error = await request.json();
55+
return new Response(
56+
JSON.stringify({
57+
error: { message: (error as any).error },
58+
provider: FIREWORKS_AI,
59+
}),
60+
{
61+
status: 500,
62+
headers: {
63+
'Content-Type': 'application/json',
64+
},
65+
}
66+
);
67+
}
68+
69+
const response = await request.json();
70+
71+
const mappedResponse = fireworkFinetuneToOpenAIFinetune(response as any);
72+
73+
return new Response(JSON.stringify(mappedResponse), {
74+
status: 200,
75+
headers: { 'Content-Type': 'application/json' },
76+
});
77+
} catch (error) {
78+
const errorMessage =
79+
error instanceof Error ? error.message : 'Unknown error';
80+
return new Response(JSON.stringify({ error: { message: errorMessage } }), {
81+
status: 500,
82+
});
83+
}
84+
};

0 commit comments

Comments
 (0)