Skip to content

Commit 56b62e1

Browse files
committed
transform finish reasons for vertex
stop reason for google bedrock titan finish reason fix fix finish reason for deepseek fix finish reason for mistral fix finish reason for together ai changes from self review fix finish reason for anthropic completions
1 parent 2ddd3f5 commit 56b62e1

File tree

15 files changed

+395
-61
lines changed

15 files changed

+395
-61
lines changed

src/providers/anthropic/complete.ts

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { ANTHROPIC } from '../../globals';
22
import { Params } from '../../types/requestBody';
33
import { CompletionResponse, ErrorResponse, ProviderConfig } from '../types';
4-
import { generateInvalidProviderResponseError } from '../utils';
4+
import {
5+
generateInvalidProviderResponseError,
6+
transformFinishReason,
7+
} from '../utils';
8+
import { ANTHROPIC_STOP_REASON, AnthropicStreamState, AnthropicErrorResponse } from './types';
59
import { AnthropicErrorResponseTransform } from './utils';
6-
import { AnthropicErrorResponse } from './types';
710

811
// TODO: this configuration does not enforce the maximum token limit for the input parameter. If you want to enforce this, you might need to add a custom validation function or a max property to the ParameterConfig interface, and then use it in the input configuration. However, this might be complex because the token count is not a simple length check, but depends on the specific tokenization method used by the model.
912

@@ -57,7 +60,7 @@ export const AnthropicCompleteConfig: ProviderConfig = {
5760

5861
interface AnthropicCompleteResponse {
5962
completion: string;
60-
stop_reason: string;
63+
stop_reason: ANTHROPIC_STOP_REASON;
6164
model: string;
6265
truncated: boolean;
6366
stop: null | string;
@@ -68,10 +71,20 @@ interface AnthropicCompleteResponse {
6871
// TODO: The token calculation is wrong atm
6972
export const AnthropicCompleteResponseTransform: (
7073
response: AnthropicCompleteResponse | AnthropicErrorResponse,
71-
responseStatus: number
72-
) => CompletionResponse | ErrorResponse = (response, responseStatus) => {
73-
if (responseStatus !== 200 && 'error' in response) {
74-
return AnthropicErrorResponseTransform(response);
74+
responseStatus: number,
75+
responseHeaders: Headers,
76+
strictOpenAiCompliance: boolean
77+
) => CompletionResponse | ErrorResponse = (
78+
response,
79+
responseStatus,
80+
_responseHeaders,
81+
strictOpenAiCompliance
82+
) => {
83+
if (responseStatus !== 200) {
84+
const errorResposne = AnthropicErrorResponseTransform(
85+
response as AnthropicErrorResponse
86+
);
87+
if (errorResposne) return errorResposne;
7588
}
7689

7790
if ('completion' in response) {
@@ -86,7 +99,10 @@ export const AnthropicCompleteResponseTransform: (
8699
text: response.completion,
87100
index: 0,
88101
logprobs: null,
89-
finish_reason: response.stop_reason,
102+
finish_reason: transformFinishReason(
103+
response.stop_reason,
104+
strictOpenAiCompliance
105+
),
90106
},
91107
],
92108
};
@@ -96,8 +112,16 @@ export const AnthropicCompleteResponseTransform: (
96112
};
97113

98114
export const AnthropicCompleteStreamChunkTransform: (
99-
response: string
100-
) => string | undefined = (responseChunk) => {
115+
response: string,
116+
fallbackId: string,
117+
streamState: AnthropicStreamState,
118+
strictOpenAiCompliance: boolean
119+
) => string | undefined = (
120+
responseChunk,
121+
fallbackId,
122+
streamState,
123+
strictOpenAiCompliance
124+
) => {
101125
let chunk = responseChunk.trim();
102126
if (chunk.startsWith('event: ping')) {
103127
return;
@@ -110,6 +134,9 @@ export const AnthropicCompleteStreamChunkTransform: (
110134
return chunk;
111135
}
112136
const parsedChunk: AnthropicCompleteResponse = JSON.parse(chunk);
137+
const finishReason = parsedChunk.stop_reason
138+
? transformFinishReason(parsedChunk.stop_reason, strictOpenAiCompliance)
139+
: null;
113140
return (
114141
`data: ${JSON.stringify({
115142
id: parsedChunk.log_id,
@@ -122,7 +149,7 @@ export const AnthropicCompleteStreamChunkTransform: (
122149
text: parsedChunk.completion,
123150
index: 0,
124151
logprobs: null,
125-
finish_reason: parsedChunk.stop_reason,
152+
finish_reason: finishReason,
126153
},
127154
],
128155
})}` + '\n\n'

src/providers/bedrock/complete.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { BEDROCK } from '../../globals';
22
import { Params } from '../../types/requestBody';
33
import { CompletionResponse, ErrorResponse, ProviderConfig } from '../types';
4-
import { generateInvalidProviderResponseError } from '../utils';
4+
import {
5+
generateInvalidProviderResponseError,
6+
transformFinishReason,
7+
} from '../utils';
58
import { BedrockErrorResponseTransform } from './chatComplete';
69
import { BedrockErrorResponse } from './embed';
10+
import { TITAN_STOP_REASON as TITAN_COMPLETION_REASON } from './types';
711

812
export const BedrockAnthropicCompleteConfig: ProviderConfig = {
913
prompt: {
@@ -380,7 +384,7 @@ export interface BedrockTitanCompleteResponse {
380384
results: {
381385
tokenCount: number;
382386
outputText: string;
383-
completionReason: string;
387+
completionReason: TITAN_COMPLETION_REASON;
384388
}[];
385389
}
386390

@@ -420,7 +424,10 @@ export const BedrockTitanCompleteResponseTransform: (
420424
text: generation.outputText,
421425
index: index,
422426
logprobs: null,
423-
finish_reason: generation.completionReason,
427+
finish_reason: transformFinishReason(
428+
generation.completionReason,
429+
strictOpenAiCompliance
430+
),
424431
})),
425432
usage: {
426433
prompt_tokens: response.inputTextTokenCount,
@@ -437,7 +444,7 @@ export interface BedrockTitanStreamChunk {
437444
outputText: string;
438445
index: number;
439446
totalOutputTextTokenCount: number;
440-
completionReason: string | null;
447+
completionReason: TITAN_COMPLETION_REASON | null;
441448
'amazon-bedrock-invocationMetrics': {
442449
inputTokenCount: number;
443450
outputTokenCount: number;
@@ -462,6 +469,12 @@ export const BedrockTitanCompleteStreamChunkTransform: (
462469
let chunk = responseChunk.trim();
463470
chunk = chunk.trim();
464471
const parsedChunk: BedrockTitanStreamChunk = JSON.parse(chunk);
472+
const finishReason = parsedChunk.completionReason
473+
? transformFinishReason(
474+
parsedChunk.completionReason,
475+
_strictOpenAiCompliance
476+
)
477+
: null;
465478

466479
return [
467480
`data: ${JSON.stringify({
@@ -490,7 +503,7 @@ export const BedrockTitanCompleteStreamChunkTransform: (
490503
text: '',
491504
index: 0,
492505
logprobs: null,
493-
finish_reason: parsedChunk.completionReason,
506+
finish_reason: finishReason,
494507
},
495508
],
496509
usage: {

src/providers/bedrock/types.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export interface BedrockChatCompletionResponse {
108108
content: BedrockContentItem[];
109109
};
110110
};
111-
stopReason: BEDROCK_STOP_REASON;
111+
stopReason: BEDROCK_CONVERSE_STOP_REASON;
112112
usage: {
113113
inputTokens: number;
114114
outputTokens: number;
@@ -156,7 +156,7 @@ export type BedrockContentItem = {
156156
};
157157

158158
export interface BedrockStreamState {
159-
stopReason?: BEDROCK_STOP_REASON;
159+
stopReason?: BEDROCK_CONVERSE_STOP_REASON;
160160
currentToolCallIndex?: number;
161161
currentContentBlockIndex?: number;
162162
}
@@ -186,7 +186,7 @@ export interface BedrockChatCompleteStreamChunk {
186186
input?: object;
187187
};
188188
};
189-
stopReason?: BEDROCK_STOP_REASON;
189+
stopReason?: BEDROCK_CONVERSE_STOP_REASON;
190190
metrics?: {
191191
latencyMs: number;
192192
};
@@ -199,13 +199,22 @@ export interface BedrockChatCompleteStreamChunk {
199199
cacheWriteInputTokenCount?: number;
200200
cacheWriteInputTokens?: number;
201201
};
202+
message?: string;
202203
}
203204

204-
export enum BEDROCK_STOP_REASON {
205+
export enum BEDROCK_CONVERSE_STOP_REASON {
205206
end_turn = 'end_turn',
206207
tool_use = 'tool_use',
207208
max_tokens = 'max_tokens',
208209
stop_sequence = 'stop_sequence',
209210
guardrail_intervened = 'guardrail_intervened',
210211
content_filtered = 'content_filtered',
211212
}
213+
214+
export enum TITAN_STOP_REASON {
215+
FINISHED = 'FINISHED',
216+
LENGTH = 'LENGTH',
217+
STOP_CRITERIA_MET = 'STOP_CRITERIA_MET',
218+
RAG_QUERY_WHEN_RAG_DISABLED = 'RAG_QUERY_WHEN_RAG_DISABLED',
219+
CONTENT_FILTERED = 'CONTENT_FILTERED',
220+
}

src/providers/deepseek/chatComplete.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import {
99
import {
1010
generateErrorResponse,
1111
generateInvalidProviderResponseError,
12+
transformFinishReason,
1213
} from '../utils';
14+
import { DEEPSEEK_STOP_REASON } from './types';
1315

1416
export const DeepSeekChatCompleteConfig: ProviderConfig = {
1517
model: {
@@ -127,8 +129,15 @@ interface DeepSeekStreamChunk {
127129

128130
export const DeepSeekChatCompleteResponseTransform: (
129131
response: DeepSeekChatCompleteResponse | DeepSeekErrorResponse,
130-
responseStatus: number
131-
) => ChatCompletionResponse | ErrorResponse = (response, responseStatus) => {
132+
responseStatus: number,
133+
responseHeaders: Headers,
134+
strictOpenAiCompliance: boolean
135+
) => ChatCompletionResponse | ErrorResponse = (
136+
response,
137+
responseStatus,
138+
_responseHeaders,
139+
strictOpenAiCompliance
140+
) => {
132141
if ('message' in response && responseStatus !== 200) {
133142
return generateErrorResponse(
134143
{
@@ -154,7 +163,10 @@ export const DeepSeekChatCompleteResponseTransform: (
154163
role: c.message.role,
155164
content: c.message.content,
156165
},
157-
finish_reason: c.finish_reason,
166+
finish_reason: transformFinishReason(
167+
c.finish_reason as DEEPSEEK_STOP_REASON,
168+
strictOpenAiCompliance
169+
),
158170
})),
159171
usage: {
160172
prompt_tokens: response.usage?.prompt_tokens,
@@ -168,15 +180,31 @@ export const DeepSeekChatCompleteResponseTransform: (
168180
};
169181

170182
export const DeepSeekChatCompleteStreamChunkTransform: (
171-
response: string
172-
) => string = (responseChunk) => {
183+
response: string,
184+
fallbackId: string,
185+
streamState: any,
186+
strictOpenAiCompliance: boolean,
187+
gatewayRequest: Params
188+
) => string | string[] = (
189+
responseChunk,
190+
fallbackId,
191+
_streamState,
192+
strictOpenAiCompliance,
193+
_gatewayRequest
194+
) => {
173195
let chunk = responseChunk.trim();
174196
chunk = chunk.replace(/^data: /, '');
175197
chunk = chunk.trim();
176198
if (chunk === '[DONE]') {
177199
return `data: ${chunk}\n\n`;
178200
}
179201
const parsedChunk: DeepSeekStreamChunk = JSON.parse(chunk);
202+
const finishReason = parsedChunk.choices[0].finish_reason
203+
? transformFinishReason(
204+
parsedChunk.choices[0].finish_reason as DEEPSEEK_STOP_REASON,
205+
strictOpenAiCompliance
206+
)
207+
: null;
180208
return (
181209
`data: ${JSON.stringify({
182210
id: parsedChunk.id,
@@ -188,7 +216,7 @@ export const DeepSeekChatCompleteStreamChunkTransform: (
188216
{
189217
index: parsedChunk.choices[0].index,
190218
delta: parsedChunk.choices[0].delta,
191-
finish_reason: parsedChunk.choices[0].finish_reason,
219+
finish_reason: finishReason,
192220
},
193221
],
194222
usage: parsedChunk.usage,

src/providers/deepseek/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export enum DEEPSEEK_STOP_REASON {
2+
stop = 'stop',
3+
length = 'length',
4+
tool_calls = 'tool_calls',
5+
content_filter = 'content_filter',
6+
insufficient_system_resource = 'insufficient_system_resource',
7+
}

src/providers/google-vertex-ai/chatComplete.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
import {
3838
generateErrorResponse,
3939
generateInvalidProviderResponseError,
40+
transformFinishReason,
4041
} from '../utils';
4142
import { transformGenerationConfig } from './transformGenerationConfig';
4243
import type {
@@ -494,7 +495,10 @@ export const GoogleChatCompleteResponseTransform: (
494495
return {
495496
message: message,
496497
index: index,
497-
finish_reason: generation.finishReason,
498+
finish_reason: transformFinishReason(
499+
generation.finishReason,
500+
strictOpenAiCompliance
501+
),
498502
logprobs,
499503
...(!strictOpenAiCompliance && {
500504
safetyRatings: generation.safetyRatings,
@@ -615,6 +619,13 @@ export const GoogleChatCompleteStreamChunkTransform: (
615619
provider: GOOGLE_VERTEX_AI,
616620
choices:
617621
parsedChunk.candidates?.map((generation, index) => {
622+
const finishReason = generation.finishReason
623+
? transformFinishReason(
624+
parsedChunk.candidates[0].finishReason,
625+
strictOpenAiCompliance
626+
)
627+
: null;
628+
618629
let message: any = { role: 'assistant', content: '' };
619630
if (generation.content?.parts[0]?.text) {
620631
const contentBlocks = [];
@@ -661,7 +672,7 @@ export const GoogleChatCompleteStreamChunkTransform: (
661672
return {
662673
delta: message,
663674
index: index,
664-
finish_reason: generation.finishReason,
675+
finish_reason: finishReason,
665676
...(!strictOpenAiCompliance && {
666677
safetyRatings: generation.safetyRatings,
667678
}),
@@ -761,7 +772,10 @@ export const VertexAnthropicChatCompleteResponseTransform: (
761772
},
762773
index: 0,
763774
logprobs: null,
764-
finish_reason: response.stop_reason,
775+
finish_reason: transformFinishReason(
776+
response.stop_reason,
777+
strictOpenAiCompliance
778+
),
765779
},
766780
],
767781
usage: {
@@ -874,7 +888,10 @@ export const VertexAnthropicChatCompleteStreamChunkTransform: (
874888
{
875889
index: 0,
876890
delta: {},
877-
finish_reason: parsedChunk.delta?.stop_reason,
891+
finish_reason: transformFinishReason(
892+
parsedChunk.delta?.stop_reason,
893+
strictOpenAiCompliance
894+
),
878895
},
879896
],
880897
usage: {

src/providers/google-vertex-ai/types.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export interface GoogleResponseCandidate {
4040
},
4141
];
4242
};
43-
finishReason: string;
43+
finishReason: VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON;
4444
index: 0;
4545
safetyRatings: {
4646
category: string;
@@ -243,3 +243,15 @@ export interface GoogleFinetuneRecord {
243243
};
244244
};
245245
}
246+
247+
export enum VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON {
248+
FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED',
249+
STOP = 'STOP',
250+
MAX_TOKENS = 'MAX_TOKENS',
251+
SAFETY = 'SAFETY',
252+
RECITATION = 'RECITATION',
253+
OTHER = 'OTHER',
254+
BLOCKLIST = 'BLOCKLIST',
255+
PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',
256+
SPII = 'SPII',
257+
}

0 commit comments

Comments
 (0)