Skip to content

Commit 86aae1e

Browse files
committed
Make Bytez impl conform to the transform spec per maintainer feedback.
1 parent 99bff2d commit 86aae1e

File tree

5 files changed

+47
-254
lines changed

5 files changed

+47
-254
lines changed

src/handlers/handlerUtils.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,12 +510,7 @@ export async function tryPost(
510510
body: transformedRequestBody,
511511
headers: fetchOptions.headers,
512512
},
513-
requestParams: {
514-
// in the event transformedRequestBody request is empty, e.g. you have opted to handle requests via a custom requestHandler
515-
...params,
516-
// if this is populated, we will overwrite whatever was initially in params
517-
...transformedRequestBody,
518-
},
513+
requestParams: transformedRequestBody,
519514
finalUntransformedRequest: {
520515
body: params,
521516
},

src/providers/bytez/api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ProviderAPIConfig } from '../types';
2+
import { version } from '../../../package.json';
23

34
const BytezInferenceAPI: ProviderAPIConfig = {
45
getBaseURL: () => 'https://api.bytez.com',
@@ -8,6 +9,7 @@ const BytezInferenceAPI: ProviderAPIConfig = {
89
const headers: Record<string, string> = {};
910

1011
headers['Authorization'] = `Key ${apiKey}`;
12+
headers['user-agent'] = `portkey-${version}`;
1113

1214
return headers;
1315
},

src/providers/bytez/chatComplete.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,18 @@ const BytezInferenceChatCompleteConfig: ProviderConfig = {
66
required: true,
77
},
88
max_tokens: {
9-
// NOTE param acts as an alias, it will be added to "params" on the req body
10-
// we do this adaptation ourselves in our custom requestHandler. See src/providers/bytez/index.ts
11-
param: 'max_new_tokens',
9+
param: 'params.max_new_tokens',
1210
default: 100,
1311
min: 0,
1412
},
1513
temperature: {
16-
param: 'temperature',
14+
param: 'params.temperature',
1715
default: 1,
1816
min: 0,
1917
max: 2,
2018
},
2119
top_p: {
22-
param: 'top_p',
20+
param: 'params.top_p',
2321
default: 1,
2422
min: 0,
2523
max: 1,

src/providers/bytez/index.ts

Lines changed: 41 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,56 @@
1+
import { BYTEZ } from '../../globals';
12
import { ProviderConfigs } from '../types';
3+
import { generateErrorResponse } from '../utils';
24
import BytezInferenceAPI from './api';
35
import { BytezInferenceChatCompleteConfig } from './chatComplete';
4-
import { bodyAdapter, LRUCache } from './utils';
56
import { BytezResponse } from './types';
67

7-
const BASE_URL = 'https://api.bytez.com/models/v2';
8-
9-
const IS_CHAT_MODEL_CACHE = new LRUCache({ size: 100 });
10-
118
const BytezInferenceAPIConfig: ProviderConfigs = {
129
api: BytezInferenceAPI,
1310
chatComplete: BytezInferenceChatCompleteConfig,
14-
requestHandlers: {
15-
chatComplete: async ({ providerOptions, requestBody }) => {
16-
try {
17-
const { model: modelId } = requestBody;
18-
19-
const adaptedBody = bodyAdapter(requestBody);
20-
21-
const headers = {
22-
'Content-Type': 'application/json',
23-
Authorization: `Key ${providerOptions.apiKey}`,
24-
};
25-
26-
const isChatModel = await validateModelIsChat(modelId, headers);
27-
28-
if (!isChatModel) {
29-
return constructFailureResponse(
30-
'Bytez only supports chat models on PortKey',
31-
{ status: 400 }
32-
);
33-
}
34-
35-
const url = `${BASE_URL}/${modelId}`;
36-
37-
const response = await fetch(url, {
38-
method: 'POST',
39-
headers,
40-
body: JSON.stringify(adaptedBody),
41-
});
42-
43-
if (adaptedBody.stream) {
44-
return new Response(response.body, response);
45-
}
46-
47-
const { error, output }: BytezResponse = await response.json();
48-
49-
if (error) {
50-
return constructFailureResponse(error, response);
51-
}
52-
53-
return new Response(
54-
JSON.stringify({
55-
id: crypto.randomUUID(),
56-
object: 'chat.completion',
57-
created: Date.now(),
58-
model: modelId,
59-
choices: [
60-
{
61-
index: 0,
62-
message: output,
63-
logprobs: null,
64-
finish_reason: 'stop',
65-
},
66-
],
67-
usage: {
68-
inferenceTime: response.headers.get('inference-time'),
69-
modelSize: response.headers.get('inference-meter'),
70-
},
71-
}),
72-
response
11+
responseTransforms: {
12+
chatComplete: (
13+
response: BytezResponse,
14+
responseStatus: number,
15+
responseHeaders: any,
16+
strictOpenAiCompliance: boolean,
17+
endpoint: string,
18+
requestBody: any
19+
) => {
20+
const { error, output } = response;
21+
22+
if (error) {
23+
return generateErrorResponse(
24+
{
25+
message: error,
26+
type: String(responseStatus),
27+
param: null,
28+
code: null,
29+
},
30+
BYTEZ
7331
);
74-
} catch (error: any) {
75-
return constructFailureResponse(error.message);
7632
}
33+
34+
return {
35+
id: crypto.randomUUID(),
36+
object: 'chat.completion',
37+
created: Date.now(),
38+
model: requestBody.model,
39+
choices: [
40+
{
41+
index: 0,
42+
message: output,
43+
logprobs: null,
44+
finish_reason: 'stop',
45+
},
46+
],
47+
usage: {
48+
inferenceTime: responseHeaders.get('inference-time'),
49+
modelSize: responseHeaders.get('inference-meter'),
50+
},
51+
};
7752
},
7853
},
7954
};
8055

81-
async function validateModelIsChat(
82-
modelId: string,
83-
headers: Record<string, any>
84-
) {
85-
// return from cache if already validated
86-
if (IS_CHAT_MODEL_CACHE.has(modelId)) {
87-
return IS_CHAT_MODEL_CACHE.get(modelId);
88-
}
89-
90-
const url = `${BASE_URL}/list/models?modelId=${modelId}`;
91-
92-
const response = await fetch(url, {
93-
headers,
94-
});
95-
96-
const {
97-
error,
98-
output: [model],
99-
}: BytezResponse = await response.json();
100-
101-
if (error) {
102-
throw new Error(error);
103-
}
104-
105-
const isChatModel = model.task === 'chat';
106-
107-
IS_CHAT_MODEL_CACHE.set(modelId, isChatModel);
108-
109-
return isChatModel;
110-
}
111-
112-
function constructFailureResponse(message: string, response?: object) {
113-
return new Response(
114-
JSON.stringify({
115-
status: 'failure',
116-
message,
117-
}),
118-
{
119-
status: 500,
120-
headers: {
121-
'content-type': 'application/json',
122-
},
123-
// override defaults if desired
124-
...response,
125-
}
126-
);
127-
}
128-
12956
export default BytezInferenceAPIConfig;

src/providers/bytez/utils.ts

Lines changed: 0 additions & 129 deletions
This file was deleted.

0 commit comments

Comments
 (0)