Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const SILICONFLOW: string = 'siliconflow';
export const CEREBRAS: string = 'cerebras';
export const INFERENCENET: string = 'inference-net';
export const SAMBANOVA: string = 'sambanova';
export const LEMONFOX_AI: string = 'lemonfox-ai';
export const UPSTAGE: string = 'upstage';

export const VALID_PROVIDERS = [
Expand Down Expand Up @@ -113,6 +114,7 @@ export const VALID_PROVIDERS = [
CEREBRAS,
INFERENCENET,
SAMBANOVA,
LEMONFOX_AI,
UPSTAGE,
];

Expand Down
2 changes: 2 additions & 0 deletions src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import HuggingfaceConfig from './huggingface';
import { cerebrasProviderAPIConfig } from './cerebras';
import { InferenceNetProviderConfigs } from './inference-net';
import SambaNovaConfig from './sambanova';
import LemonfoxAIConfig from './lemonfox-ai';
import { UpstageConfig } from './upstage';

const Providers: { [key: string]: ProviderConfigs } = {
Expand Down Expand Up @@ -86,6 +87,7 @@ const Providers: { [key: string]: ProviderConfigs } = {
cerebras: cerebrasProviderAPIConfig,
'inference-net': InferenceNetProviderConfigs,
sambanova: SambaNovaConfig,
'lemonfox-ai': LemonfoxAIConfig,
upstage: UpstageConfig,
};

Expand Down
27 changes: 27 additions & 0 deletions src/providers/lemonfox-ai/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ProviderAPIConfig } from '../types';

const LemonfoxAIAPIConfig: ProviderAPIConfig = {
getBaseURL: () => 'https://api.lemonfox.ai/v1',
headers: ({ providerOptions, fn }) => {
const headersObj: Record<string, string> = {
Authorization: `Bearer ${providerOptions.apiKey}`,
};
if (fn === 'createTranscription')
headersObj['content-type'] = 'multipart/form-data';
return headersObj;
},
getEndpoint: ({ fn }) => {
switch (fn) {
case 'chatComplete':
return '/chat/completions';
case 'imageGenerate':
return '/images/generations';
case 'createTranscription':
return '/audio/transcriptions';
default:
return '';
}
},
};

export default LemonfoxAIAPIConfig;
180 changes: 180 additions & 0 deletions src/providers/lemonfox-ai/chatComplete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { LEMONFOX_AI } from '../../globals';
import {
ChatCompletionResponse,
ErrorResponse,
ProviderConfig,
} from '../types';

import {
generateErrorResponse,
generateInvalidProviderResponseError,
} from '../utils';

export const LemonfoxAIChatCompleteConfig: ProviderConfig = {
model: {
param: 'model',
required: true,
default: 'zephyr-chat',
},
messages: {
param: 'messages',
default: [],
},
temperature: {
param: 'temperature',
default: 1,
min: 0,
max: 2,
},
top_p: {
param: 'top_p',
default: 1,
min: 0,
max: 1,
},
max_tokens: {
param: 'max_tokens',
default: Infinity,
min: 1,
},
stream: {
param: 'stream',
default: false,
},
stop: {
param: 'stop',
default: null,
},
frequency_penalty: {
param: 'frequency_penalty',
default: 0,
min: -2,
max: 2,
},
presence_penalty: {
param: 'presence_penalty',
default: 0,
min: -2,
max: 2,
},
};

interface LemonfoxAIChatCompleteResponse extends ChatCompletionResponse {
id: string;
object: string;
created: number;
model: string;
usage: {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
}

export interface LemonfoxAIErrorResponse {
object: string;
message: string;
type: string;
param: string | null;
code: string;
}

interface LemonfoxAIStreamChunk {
id: string;
object: string;
created: number;
model: string;
choices: {
delta: {
role?: string | null;
content?: string;
};
index: number;
finish_reason: string | null;
}[];
}

interface LemonfoxAIStreamChunk {
id: string;
object: string;
created: number;
model: string;
choices: {
delta: {
role?: string | null;
content?: string;
};
index: number;
finish_reason: string | null;
}[];
}

export const LemonfoxAIChatCompleteResponseTransform: (
response: LemonfoxAIChatCompleteResponse | LemonfoxAIErrorResponse,
responseStatus: number
) => ChatCompletionResponse | ErrorResponse = (response, responseStatus) => {
if ('message' in response && responseStatus !== 200) {
return generateErrorResponse(
{
message: response.message,
type: response.type,
param: response.param,
code: response.code,
},
LEMONFOX_AI
);
}

if ('choices' in response) {
return {
id: response.id,
object: response.object,
created: response.created,
model: response.model,
provider: LEMONFOX_AI,
choices: response.choices.map((c) => ({
index: c.index,
message: {
role: c.message.role,
content: c.message.content,
},
finish_reason: c.finish_reason,
})),
usage: {
prompt_tokens: response.usage?.prompt_tokens,
completion_tokens: response.usage?.completion_tokens,
total_tokens: response.usage?.total_tokens,
},
};
}

return generateInvalidProviderResponseError(response, LEMONFOX_AI);
};

export const LemonfoxAIChatCompleteStreamChunkTransform: (
response: string
) => string = (responseChunk) => {
let chunk = responseChunk.trim();
chunk = chunk.replace(/^data: /, '');
chunk = chunk.trim();
if (chunk === '[DONE]') {
return `data: ${chunk}\n\n`;
}
const parsedChunk: LemonfoxAIStreamChunk = JSON.parse(chunk);
return (
`data: ${JSON.stringify({
id: parsedChunk.id,
object: parsedChunk.object,
created: parsedChunk.created,
model: parsedChunk.model,
provider: LEMONFOX_AI,
choices: [
{
index: parsedChunk.choices[0].index,
delta: parsedChunk.choices[0].delta,
finish_reason: parsedChunk.choices[0].finish_reason,
},
],
})}` + '\n\n'
);
};
34 changes: 34 additions & 0 deletions src/providers/lemonfox-ai/createTranscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { LEMONFOX_AI } from '../../globals';

import { generateInvalidProviderResponseError } from '../utils';

import { ErrorResponse, ProviderConfig } from '../types';

export const LemonfoxAIcreateTranscriptionConfig: ProviderConfig = {
file: {
param: 'file',
required: true,
},
response_format: {
param: 'response_format',
},
prompt: {
param: 'prompt',
},
language: {
param: 'language',
},
translate: {
param: 'translate',
},
};

export const LemonfoxAICreateTranscriptionResponseTransform: (
response: Response | ErrorResponse,
responseStatus: number
) => Response | ErrorResponse = (response, responseStatus) => {
if (responseStatus !== 200 && 'error' in response) {
return generateInvalidProviderResponseError(response, LEMONFOX_AI);
}
return response;
};
58 changes: 58 additions & 0 deletions src/providers/lemonfox-ai/imageGenerate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { LEMONFOX_AI } from '../../globals';
import { ErrorResponse, ImageGenerateResponse, ProviderConfig } from '../types';

import {
generateErrorResponse,
generateInvalidProviderResponseError,
} from '../utils';

export const LemonfoxAIImageGenerateConfig: ProviderConfig = {
prompt: {
param: 'prompt',
required: true,
},
negative_prompt: {
param: 'negative_prompt',
},
n: {
param: 'n',
max: 8,
min: 1,
default: 1,
},
response_format: {
param: 'response_format',
default: 'url',
},
size: {
param: 'size',
},
};

interface LemonfoxAIImageObject {
b64_json?: string; // The base64-encoded JSON of the generated image, if response_format is b64_json.
url?: string; // The URL of the generated image, if response_format is url (default).
}

interface LemonfoxAIImageGenerateResponse extends ImageGenerateResponse {
data: LemonfoxAIImageObject[];
}

export const LemonfoxImageGenerateResponseTransform: (
response: LemonfoxAIImageGenerateResponse | ErrorResponse,
responseStatus: number
) => ImageGenerateResponse | ErrorResponse = (response, responseStatus) => {
if (responseStatus !== 200 && 'error' in response) {
return generateErrorResponse(
{
message: response['error'].message,
type: response['error'].type,
param: null,
code: null,
},
LEMONFOX_AI
);
}

return response;
};
Loading
Loading