gateway
gateway copied to clipboard
Fix stop reason for a few providers
Title:
- Transform Stop Reason from Provider specific enums to OpenAI Response Schema compliant ones
Description:
- I'm using Enums instead of string types to be explicit, it adds a few lines of code which would have been simply overlapping types if we used string types instead, I find this more readable
- Did not make any of the existing response types non nullable
TO-DO
- At some of the places, stop reason is hardcoded to be length/stop, I did not change those as part of this PR.
- Types and Utils can be extracted from inside the providers
complete.tsandchatComplete.tsfiles to make the code more readable
Motivation:
- Portkey Gateway currently does not transform the stop_reason at a lot of places and it fails with strictly typed languages and fails validations.
Related Issues:
- https://github.com/Portkey-AI/gateway/issues/459
Also thanks to @unsync for his initial PR on this. I've extended it to all the providers
@VisargD for your review
Hey! This PR is not currently handling stop reason transformation for streaming calls.
| provider | chat | chat streaming | completion | completion streaming |
|---|---|---|---|---|
| Ai21 | :white_check_mark: | N/A | :white_check_mark: | N/A |
| Anthropic | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Anyscale | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Azure OpenAI | :white_check_mark: | N/A | :white_check_mark: | N/A |
| Cohere | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| DeepInfra | :white_check_mark: | :white_check_mark: | N/A | N/A |
| Fireworks | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | |
| Groq | :white_check_mark: | :white_check_mark: | N/A | N/A |
| Lingyi | :white_check_mark: | :white_check_mark: | N/A | N/A |
| Mistral | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| MonsterAPI | :white_check_mark: | N/A | N/A | N/A |
| Moonshot | :white_check_mark: | N/A | N/A | N/A |
| Novita | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Ollama | [ ] | [ ] | [ ] | [ ] |
| Openrouter | Not possible, they return different stop reason depending on deployed model/provider | |||
| Palm | :white_check_mark: | N/A | :white_check_mark: | N/A |
| Perplexity | :white_check_mark: | :white_check_mark: | N/A | N/A |
| Predibase | Not possible, they return different stop reason depending on deployed model/provider | |||
| Reka | :white_check_mark: | N/A | N/A | N/A |
| Together | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Workers | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Zhipu | :white_check_mark: | :white_check_mark: | N/A | N/A |
@VisargD please review this, I'll have to make changes again if new providers are added
closing this for now as discussed with @VisargD and @ayush-portkey Stems from decision not to transform any of the json values, and only stick to transforming keys.
| Transforming stop reason | Not Transforming |
|---|---|
| ✅ Compatible with OpenAI SDK, even when type validation is applied (zod, pydantic, etc) | Will break with OpenAI SDK if type validation applied |
| Context loss | ✅ No Context loss |
| Added maintenance | ✅ No maintenance |
Illustrated example on why doing this would mean context loss:
VERTEX_AI provider returns following types with key finishReason
export enum finishReason {
FINISH_REASON_UNSPECIFIED = 'FINISH_REASON_UNSPECIFIED',
STOP = 'STOP',
MAX_TOKENS = 'MAX_TOKENS',
SAFETY = 'SAFETY',
RECITATION = 'RECITATION',
OTHER = 'OTHER',
BLOCKLIST = 'BLOCKLIST',
PROHIBITED_CONTENT = 'PROHIBITED_CONTENT',
SPII = 'SPII',
}
since OPENAI only has 4 finish_reason enums, we map the above keys to one of the 4.
const transformVertexGeminiChatStopReason = (
stopReason?: VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON | string
): OPEN_AI_CHAT_COMPLETION_FINISH_REASON => {
switch (stopReason) {
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.STOP:
return OPEN_AI_CHAT_COMPLETION_FINISH_REASON.stop;
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.SAFETY:
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.RECITATION:
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.BLOCKLIST:
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.PROHIBITED_CONTENT:
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.SPII:
return OPEN_AI_CHAT_COMPLETION_FINISH_REASON.content_filter;
case VERTEX_GEMINI_GENERATE_CONTENT_FINISH_REASON.MAX_TOKENS:
return OPEN_AI_CHAT_COMPLETION_FINISH_REASON.length;
default:
return OPEN_AI_CHAT_COMPLETION_FINISH_REASON.stop;
}
};