litellmts-core 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -21
- package/dist/auth/copilot.js +3 -3
- package/dist/auth/store.d.ts +1 -0
- package/dist/auth/store.js +45 -5
- package/dist/handlers/ai21.js +7 -5
- package/dist/handlers/anthropic.d.ts +1 -1
- package/dist/handlers/anthropic.js +36 -71
- package/dist/handlers/cohere.js +104 -43
- package/dist/handlers/copilot.js +4 -2
- package/dist/handlers/deepinfra.js +18 -3
- package/dist/handlers/gemini.d.ts +1 -1
- package/dist/handlers/gemini.js +47 -90
- package/dist/handlers/geminiEmbedding.d.ts +1 -1
- package/dist/handlers/geminiEmbedding.js +6 -9
- package/dist/handlers/mistral.js +18 -3
- package/dist/handlers/mistralEmbedding.js +3 -1
- package/dist/handlers/ollama.js +14 -4
- package/dist/handlers/ollamaEmbedding.js +4 -2
- package/dist/handlers/openai.js +38 -11
- package/dist/handlers/openaiEmbedding.js +10 -2
- package/dist/handlers/openaiLike.d.ts +1 -1
- package/dist/handlers/openaiLike.js +26 -3
- package/dist/handlers/openaiLikeEmbedding.d.ts +1 -1
- package/dist/handlers/openaiLikeEmbedding.js +6 -2
- package/dist/handlers/replicate.js +41 -16
- package/dist/handlers/vertexAnthropic.d.ts +2 -0
- package/dist/handlers/vertexAnthropic.js +43 -0
- package/dist/handlers/vertexai.d.ts +2 -0
- package/dist/handlers/vertexai.js +51 -0
- package/dist/handlers/vertexaiEmbedding.d.ts +2 -0
- package/dist/handlers/vertexaiEmbedding.js +31 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -1
- package/dist/mappings/openaiLike.js +0 -5
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.js +7 -0
- package/dist/models/registry.d.ts +13 -0
- package/dist/models/registry.js +32 -0
- package/dist/models/types.d.ts +9 -0
- package/dist/models/types.js +2 -0
- package/dist/utils/anthropic.d.ts +10 -0
- package/dist/utils/anthropic.js +99 -0
- package/dist/utils/gemini.d.ts +12 -0
- package/dist/utils/gemini.js +73 -0
- package/dist/utils/sse.js +0 -1
- package/package.json +12 -18
package/dist/handlers/gemini.js
CHANGED
|
@@ -1,78 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GeminiHandler = GeminiHandler;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
function toGeminiContent(messages) {
|
|
7
|
-
return messages.map((msg) => {
|
|
8
|
-
const parts = [];
|
|
9
|
-
if (msg.content) {
|
|
10
|
-
parts.push({ text: msg.content });
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
role: msg.role === 'assistant' ? 'model' : msg.role,
|
|
14
|
-
parts,
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
function toFinishReason(reason) {
|
|
19
|
-
switch (reason) {
|
|
20
|
-
case 'STOP':
|
|
21
|
-
return 'stop';
|
|
22
|
-
case 'MAX_TOKENS':
|
|
23
|
-
return 'length';
|
|
24
|
-
default:
|
|
25
|
-
return 'stop';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function toUsage(meta) {
|
|
29
|
-
if (!meta)
|
|
30
|
-
return undefined;
|
|
31
|
-
return {
|
|
32
|
-
prompt_tokens: meta.promptTokenCount,
|
|
33
|
-
completion_tokens: meta.candidatesTokenCount,
|
|
34
|
-
total_tokens: meta.totalTokenCount,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
function toResponse(response, model) {
|
|
38
|
-
const candidate = response.candidates?.[0];
|
|
39
|
-
return {
|
|
40
|
-
model: model,
|
|
41
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
42
|
-
usage: toUsage(response.usageMetadata),
|
|
43
|
-
choices: [
|
|
44
|
-
{
|
|
45
|
-
index: candidate?.index ?? 0,
|
|
46
|
-
finish_reason: toFinishReason(candidate?.finishReason),
|
|
47
|
-
message: {
|
|
48
|
-
role: 'assistant',
|
|
49
|
-
content: candidate ? candidate.content.parts.map((p) => 'text' in p ? p.text : '').join('') : null,
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
async function* toStreamingResponse(stream) {
|
|
56
|
-
for await (const chunk of stream) {
|
|
57
|
-
const candidate = chunk.candidates?.[0];
|
|
58
|
-
const deltaContent = candidate?.content.parts.map((p) => 'text' in p ? p.text : '').join('') ?? '';
|
|
59
|
-
yield {
|
|
60
|
-
model: undefined,
|
|
61
|
-
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
62
|
-
usage: toUsage(chunk.usageMetadata),
|
|
63
|
-
choices: [
|
|
64
|
-
{
|
|
65
|
-
index: candidate?.index ?? 0,
|
|
66
|
-
finish_reason: toFinishReason(candidate?.finishReason),
|
|
67
|
-
delta: {
|
|
68
|
-
content: deltaContent,
|
|
69
|
-
role: 'assistant',
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
4
|
+
const genai_1 = require("@google/genai");
|
|
5
|
+
const gemini_1 = require("../utils/gemini");
|
|
76
6
|
async function GeminiHandler(params) {
|
|
77
7
|
const apiKey = params.apiKey ?? process.env.GEMINI_API_KEY;
|
|
78
8
|
if (!apiKey)
|
|
@@ -80,23 +10,50 @@ async function GeminiHandler(params) {
|
|
|
80
10
|
const modelName = params.model.startsWith('gemini/')
|
|
81
11
|
? params.model.slice(7)
|
|
82
12
|
: params.model;
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
13
|
+
const client = new genai_1.GoogleGenAI({ apiKey });
|
|
14
|
+
const contents = (0, gemini_1.toGeminiContent)(params.messages);
|
|
15
|
+
try {
|
|
16
|
+
if (params.stream) {
|
|
17
|
+
const stream = await client.models.generateContentStream({
|
|
18
|
+
model: modelName,
|
|
19
|
+
contents,
|
|
20
|
+
config: {
|
|
21
|
+
temperature: params.temperature ?? undefined,
|
|
22
|
+
topP: params.top_p ?? undefined,
|
|
23
|
+
maxOutputTokens: params.max_tokens ?? undefined,
|
|
24
|
+
stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return (0, gemini_1.toStreamingResponse)(stream, modelName);
|
|
28
|
+
}
|
|
29
|
+
const response = await client.models.generateContent({
|
|
30
|
+
model: modelName,
|
|
31
|
+
contents,
|
|
32
|
+
config: {
|
|
33
|
+
temperature: params.temperature ?? undefined,
|
|
34
|
+
topP: params.top_p ?? undefined,
|
|
35
|
+
maxOutputTokens: params.max_tokens ?? undefined,
|
|
36
|
+
stopSequences: params.stop ? (Array.isArray(params.stop) ? params.stop : [params.stop]) : undefined,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
return (0, gemini_1.toResponse)(response, modelName);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
throw new Error(`Gemini API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
97
43
|
}
|
|
98
|
-
const result = await model.generateContent({ contents });
|
|
99
|
-
return toResponse(result.response, modelName);
|
|
100
44
|
}
|
|
101
|
-
const registry_1 = require("../registry");
|
|
102
|
-
(0, registry_1.
|
|
45
|
+
const registry_1 = require("../models/registry");
|
|
46
|
+
(0, registry_1.registerModelProvider)('gemini', async ({ apiKey } = {}) => {
|
|
47
|
+
const key = apiKey ?? process.env.GEMINI_API_KEY;
|
|
48
|
+
if (!key)
|
|
49
|
+
return [];
|
|
50
|
+
const client = new genai_1.GoogleGenAI({ apiKey: key });
|
|
51
|
+
const pager = await client.models.list();
|
|
52
|
+
const models = [];
|
|
53
|
+
for await (const m of pager) {
|
|
54
|
+
models.push({ id: m.name ?? m.displayName, provider: 'gemini' });
|
|
55
|
+
}
|
|
56
|
+
return models;
|
|
57
|
+
});
|
|
58
|
+
const registry_2 = require("../registry");
|
|
59
|
+
(0, registry_2.registerCompletionHandler)('gemini/', GeminiHandler);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { EmbeddingParams, EmbeddingResponse } from '../types';
|
|
1
|
+
import type { EmbeddingParams, EmbeddingResponse } from '../types';
|
|
2
2
|
export declare function GeminiEmbeddingHandler(params: EmbeddingParams): Promise<EmbeddingResponse>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GeminiEmbeddingHandler = GeminiEmbeddingHandler;
|
|
4
|
-
const
|
|
4
|
+
const genai_1 = require("@google/genai");
|
|
5
5
|
async function GeminiEmbeddingHandler(params) {
|
|
6
6
|
const apiKey = params.apiKey ?? process.env.GEMINI_API_KEY;
|
|
7
7
|
if (!apiKey)
|
|
@@ -9,20 +9,17 @@ async function GeminiEmbeddingHandler(params) {
|
|
|
9
9
|
const modelName = params.model.startsWith('gemini/')
|
|
10
10
|
? params.model.slice(7)
|
|
11
11
|
: params.model;
|
|
12
|
-
const
|
|
13
|
-
const model = genAI.getGenerativeModel({ model: modelName });
|
|
12
|
+
const client = new genai_1.GoogleGenAI({ apiKey });
|
|
14
13
|
const input = typeof params.input === 'string'
|
|
15
14
|
? params.input
|
|
16
15
|
: params.input.join(' ');
|
|
17
|
-
const result = await
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
parts: [{ text: input }],
|
|
21
|
-
},
|
|
16
|
+
const result = await client.models.embedContent({
|
|
17
|
+
model: modelName,
|
|
18
|
+
contents: [{ role: 'user', parts: [{ text: input }] }],
|
|
22
19
|
});
|
|
23
20
|
return {
|
|
24
21
|
model: modelName,
|
|
25
|
-
data: [{ embedding: result.
|
|
22
|
+
data: [{ embedding: result.embeddings?.[0]?.values ?? [], index: 0 }],
|
|
26
23
|
};
|
|
27
24
|
}
|
|
28
25
|
const registry_1 = require("../registry");
|
package/dist/handlers/mistral.js
CHANGED
|
@@ -21,7 +21,9 @@ async function MistralHandler(params) {
|
|
|
21
21
|
const apiKey = params.apiKey ?? process.env.MISTRAL_API_KEY;
|
|
22
22
|
if (!apiKey)
|
|
23
23
|
throw new Error('Mistral requires an API key. Set MISTRAL_API_KEY environment variable or pass apiKey in params.');
|
|
24
|
-
const model = params.model.
|
|
24
|
+
const model = params.model.startsWith('mistral/')
|
|
25
|
+
? params.model.slice(8)
|
|
26
|
+
: params.model;
|
|
25
27
|
const res = await getMistralResponse(model, params.messages, baseUrl, apiKey, params.stream ?? false);
|
|
26
28
|
if (!res.ok) {
|
|
27
29
|
throw new Error(`Mistral API error: ${res.status} ${res.statusText}`);
|
|
@@ -52,5 +54,18 @@ async function MistralHandler(params) {
|
|
|
52
54
|
};
|
|
53
55
|
return result;
|
|
54
56
|
}
|
|
55
|
-
const registry_1 = require("../registry");
|
|
56
|
-
(0, registry_1.
|
|
57
|
+
const registry_1 = require("../models/registry");
|
|
58
|
+
(0, registry_1.registerModelProvider)('mistral', async ({ apiKey } = {}) => {
|
|
59
|
+
const key = apiKey ?? process.env.MISTRAL_API_KEY;
|
|
60
|
+
if (!key)
|
|
61
|
+
return [];
|
|
62
|
+
const res = await fetch('https://api.mistral.ai/v1/models', {
|
|
63
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
return [];
|
|
67
|
+
const { data } = await res.json();
|
|
68
|
+
return (data ?? []).map((m) => ({ id: m.id, provider: 'mistral' }));
|
|
69
|
+
});
|
|
70
|
+
const registry_2 = require("../registry");
|
|
71
|
+
(0, registry_2.registerCompletionHandler)('mistral/', MistralHandler);
|
|
@@ -15,7 +15,9 @@ async function getMistralResponse(model, input, baseUrl, apiKey) {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
async function MistralEmbeddingHandler(params) {
|
|
18
|
-
const model = params.model.
|
|
18
|
+
const model = params.model.startsWith('mistral/')
|
|
19
|
+
? params.model.slice(8)
|
|
20
|
+
: params.model;
|
|
19
21
|
const baseUrl = params.baseUrl ?? 'https://api.mistral.ai';
|
|
20
22
|
const apiKey = params.apiKey ?? process.env.MISTRAL_API_KEY;
|
|
21
23
|
if (!apiKey)
|
package/dist/handlers/ollama.js
CHANGED
|
@@ -67,7 +67,9 @@ async function getOllamaResponse(model, prompt, baseUrl) {
|
|
|
67
67
|
}
|
|
68
68
|
async function OllamaHandler(params) {
|
|
69
69
|
const baseUrl = params.baseUrl ?? 'http://127.0.0.1:11434';
|
|
70
|
-
const model = params.model.
|
|
70
|
+
const model = params.model.startsWith('ollama/')
|
|
71
|
+
? params.model.slice(7)
|
|
72
|
+
: params.model;
|
|
71
73
|
const prompt = (0, combinePrompts_1.combinePrompts)(params.messages);
|
|
72
74
|
const res = await getOllamaResponse(model, prompt, baseUrl);
|
|
73
75
|
if (!res.ok) {
|
|
@@ -81,9 +83,17 @@ async function OllamaHandler(params) {
|
|
|
81
83
|
chunks.push(chunk);
|
|
82
84
|
}
|
|
83
85
|
const message = chunks.reduce((acc, chunk) => {
|
|
84
|
-
return
|
|
86
|
+
return acc + chunk.choices[0].delta.content;
|
|
85
87
|
}, '');
|
|
86
88
|
return toResponse(message, model, prompt);
|
|
87
89
|
}
|
|
88
|
-
const registry_1 = require("../registry");
|
|
89
|
-
(0, registry_1.
|
|
90
|
+
const registry_1 = require("../models/registry");
|
|
91
|
+
(0, registry_1.registerModelProvider)('ollama', async () => {
|
|
92
|
+
const res = await fetch('http://127.0.0.1:11434/api/tags');
|
|
93
|
+
if (!res.ok)
|
|
94
|
+
return [];
|
|
95
|
+
const { models } = await res.json();
|
|
96
|
+
return (models ?? []).map((m) => ({ id: m.name, provider: 'ollama' }));
|
|
97
|
+
});
|
|
98
|
+
const registry_2 = require("../registry");
|
|
99
|
+
(0, registry_2.registerCompletionHandler)('ollama/', OllamaHandler);
|
|
@@ -16,11 +16,13 @@ async function getOllamaResponse(model, input, baseUrl) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
async function OllamaEmbeddingHandler(params) {
|
|
19
|
-
const model = params.model.
|
|
19
|
+
const model = params.model.startsWith('ollama/')
|
|
20
|
+
? params.model.slice(7)
|
|
21
|
+
: params.model;
|
|
20
22
|
const baseUrl = params.baseUrl ?? 'http://127.0.0.1:11434';
|
|
21
23
|
const input = typeof params.input === 'string'
|
|
22
24
|
? params.input
|
|
23
|
-
: params.input.reduce((acc, curr) =>
|
|
25
|
+
: params.input.reduce((acc, curr) => acc + curr, '');
|
|
24
26
|
const response = await getOllamaResponse(model, input, baseUrl);
|
|
25
27
|
if (!response.ok) {
|
|
26
28
|
throw new Error(`Received an error with code ${response.status} from Ollama API.`);
|
package/dist/handlers/openai.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.OpenAIHandler = OpenAIHandler;
|
|
7
7
|
const openai_1 = __importDefault(require("openai"));
|
|
8
|
+
const registry_1 = require("../models/registry");
|
|
8
9
|
function toOpenAIMessages(messages) {
|
|
9
10
|
return messages;
|
|
10
11
|
}
|
|
@@ -31,24 +32,41 @@ async function OpenAIHandler(params) {
|
|
|
31
32
|
const { apiKey: providedApiKey, baseUrl: providedBaseUrl, ...completionsParams } = params;
|
|
32
33
|
const apiKey = providedApiKey ?? process.env.OPENAI_API_KEY;
|
|
33
34
|
const baseUrl = providedBaseUrl ?? 'https://api.openai.com/v1';
|
|
35
|
+
const modelName = completionsParams.model.startsWith('openai/')
|
|
36
|
+
? completionsParams.model.slice(7)
|
|
37
|
+
: completionsParams.model;
|
|
34
38
|
const openai = new openai_1.default({
|
|
35
39
|
apiKey: apiKey,
|
|
36
40
|
baseURL: baseUrl,
|
|
37
41
|
});
|
|
38
42
|
const messages = toOpenAIMessages(completionsParams.messages);
|
|
39
43
|
if (params.stream) {
|
|
40
|
-
|
|
44
|
+
let response;
|
|
45
|
+
try {
|
|
46
|
+
response = await openai.chat.completions.create({
|
|
47
|
+
...completionsParams,
|
|
48
|
+
model: modelName,
|
|
49
|
+
stream: true,
|
|
50
|
+
messages,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
throw new Error(`OpenAI API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
55
|
+
}
|
|
56
|
+
return toStreamingResponse(response);
|
|
57
|
+
}
|
|
58
|
+
let response;
|
|
59
|
+
try {
|
|
60
|
+
response = await openai.chat.completions.create({
|
|
41
61
|
...completionsParams,
|
|
42
|
-
|
|
62
|
+
model: modelName,
|
|
63
|
+
stream: false,
|
|
43
64
|
messages,
|
|
44
65
|
});
|
|
45
|
-
return toStreamingResponse(response);
|
|
46
66
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
messages,
|
|
51
|
-
});
|
|
67
|
+
catch (err) {
|
|
68
|
+
throw new Error(`OpenAI API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
69
|
+
}
|
|
52
70
|
const result = {
|
|
53
71
|
created: response.created,
|
|
54
72
|
model: response.model,
|
|
@@ -71,6 +89,15 @@ async function OpenAIHandler(params) {
|
|
|
71
89
|
};
|
|
72
90
|
return result;
|
|
73
91
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
92
|
+
(0, registry_1.registerModelProvider)('openai', async ({ apiKey } = {}) => {
|
|
93
|
+
const key = apiKey ?? process.env.OPENAI_API_KEY;
|
|
94
|
+
if (!key)
|
|
95
|
+
return [];
|
|
96
|
+
const res = await fetch('https://api.openai.com/v1/models', {
|
|
97
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
98
|
+
});
|
|
99
|
+
const { data } = await res.json();
|
|
100
|
+
return data.map((m) => ({ id: m.id, provider: 'openai', created: m.created }));
|
|
101
|
+
});
|
|
102
|
+
const registry_2 = require("../registry");
|
|
103
|
+
(0, registry_2.registerCompletionHandler)('openai/', OpenAIHandler);
|
|
@@ -8,11 +8,19 @@ const openai_1 = __importDefault(require("openai"));
|
|
|
8
8
|
async function OpenAIEmbeddingHandler(params) {
|
|
9
9
|
const apiKey = params.apiKey ?? process.env.OPENAI_API_KEY;
|
|
10
10
|
const baseUrl = params.baseUrl;
|
|
11
|
+
const modelName = params.model.startsWith('openai/')
|
|
12
|
+
? params.model.slice(7)
|
|
13
|
+
: params.model;
|
|
11
14
|
const openai = new openai_1.default({
|
|
12
15
|
apiKey: apiKey,
|
|
13
16
|
baseURL: baseUrl,
|
|
14
17
|
});
|
|
15
|
-
|
|
18
|
+
try {
|
|
19
|
+
return await openai.embeddings.create({ input: params.input, model: modelName });
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
throw new Error(`OpenAI embedding API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
25
|
const registry_1 = require("../registry");
|
|
18
|
-
(0, registry_1.registerEmbeddingHandler)('
|
|
26
|
+
(0, registry_1.registerEmbeddingHandler)('openai/', OpenAIEmbeddingHandler);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Handler } from '../types';
|
|
2
2
|
import type { OpenAILikeConfig } from '../mappings/openaiLike';
|
|
3
|
-
export declare function createOpenAILikeHandler(config: OpenAILikeConfig): Handler;
|
|
3
|
+
export declare function createOpenAILikeHandler(prefix: string, config: OpenAILikeConfig): Handler;
|
|
@@ -2,21 +2,44 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createOpenAILikeHandler = createOpenAILikeHandler;
|
|
4
4
|
const openai_1 = require("./openai");
|
|
5
|
-
|
|
5
|
+
const registry_1 = require("../models/registry");
|
|
6
|
+
function createOpenAILikeHandler(prefix, config) {
|
|
6
7
|
return async (params) => {
|
|
7
8
|
const apiKey = params.apiKey ?? process.env[config.apiKeyEnv];
|
|
8
9
|
if (!apiKey) {
|
|
9
10
|
throw new Error(`${config.name} requires an API key. Set the ${config.apiKeyEnv} environment variable or pass apiKey in params.`);
|
|
10
11
|
}
|
|
12
|
+
const modelName = params.model.startsWith(prefix)
|
|
13
|
+
? params.model.slice(prefix.length)
|
|
14
|
+
: params.model;
|
|
11
15
|
return (0, openai_1.OpenAIHandler)({
|
|
12
16
|
...params,
|
|
17
|
+
model: modelName,
|
|
13
18
|
apiKey,
|
|
14
19
|
baseUrl: config.baseUrl,
|
|
15
20
|
});
|
|
16
21
|
};
|
|
17
22
|
}
|
|
18
23
|
const openaiLike_1 = require("../mappings/openaiLike");
|
|
19
|
-
const
|
|
24
|
+
const registry_2 = require("../registry");
|
|
20
25
|
for (const [prefix, config] of Object.entries(openaiLike_1.OPENAI_LIKE_MAPPINGS)) {
|
|
21
|
-
(0,
|
|
26
|
+
(0, registry_2.registerCompletionHandler)(prefix, createOpenAILikeHandler(prefix, config));
|
|
27
|
+
const provider = prefix.replace('/', '');
|
|
28
|
+
(0, registry_1.registerModelProvider)(provider, async ({ apiKey } = {}) => {
|
|
29
|
+
const key = apiKey ?? process.env[config.apiKeyEnv];
|
|
30
|
+
if (!key)
|
|
31
|
+
return [];
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetch(`${config.baseUrl}/models`, {
|
|
34
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
35
|
+
});
|
|
36
|
+
if (!res.ok)
|
|
37
|
+
return [];
|
|
38
|
+
const { data } = await res.json();
|
|
39
|
+
return (data ?? []).map((m) => ({ id: m.id, provider }));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
});
|
|
22
45
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { EmbeddingParams, EmbeddingResponse } from '../types';
|
|
2
2
|
import type { OpenAILikeConfig } from '../mappings/openaiLike';
|
|
3
|
-
export declare function createOpenAILikeEmbeddingHandler(config: OpenAILikeConfig): (params: EmbeddingParams) => Promise<EmbeddingResponse>;
|
|
3
|
+
export declare function createOpenAILikeEmbeddingHandler(prefix: string, config: OpenAILikeConfig): (params: EmbeddingParams) => Promise<EmbeddingResponse>;
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createOpenAILikeEmbeddingHandler = createOpenAILikeEmbeddingHandler;
|
|
4
4
|
const openaiEmbedding_1 = require("./openaiEmbedding");
|
|
5
|
-
function createOpenAILikeEmbeddingHandler(config) {
|
|
5
|
+
function createOpenAILikeEmbeddingHandler(prefix, config) {
|
|
6
6
|
return async (params) => {
|
|
7
7
|
const apiKey = params.apiKey ?? process.env[config.apiKeyEnv];
|
|
8
8
|
if (!apiKey) {
|
|
9
9
|
throw new Error(`${config.name} requires an API key. Set the ${config.apiKeyEnv} environment variable or pass apiKey in params.`);
|
|
10
10
|
}
|
|
11
|
+
const modelName = params.model.startsWith(prefix)
|
|
12
|
+
? params.model.slice(prefix.length)
|
|
13
|
+
: params.model;
|
|
11
14
|
return (0, openaiEmbedding_1.OpenAIEmbeddingHandler)({
|
|
12
15
|
...params,
|
|
16
|
+
model: modelName,
|
|
13
17
|
apiKey,
|
|
14
18
|
baseUrl: config.baseUrl,
|
|
15
19
|
});
|
|
@@ -18,5 +22,5 @@ function createOpenAILikeEmbeddingHandler(config) {
|
|
|
18
22
|
const openaiLike_1 = require("../mappings/openaiLike");
|
|
19
23
|
const registry_1 = require("../registry");
|
|
20
24
|
for (const [prefix, config] of Object.entries(openaiLike_1.OPENAI_LIKE_MAPPINGS)) {
|
|
21
|
-
(0, registry_1.registerEmbeddingHandler)(prefix, createOpenAILikeEmbeddingHandler(config));
|
|
25
|
+
(0, registry_1.registerEmbeddingHandler)(prefix, createOpenAILikeEmbeddingHandler(prefix, config));
|
|
22
26
|
}
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ReplicateHandler = ReplicateHandler;
|
|
7
7
|
const replicate_1 = __importDefault(require("replicate"));
|
|
8
|
-
const eventsource_1 =
|
|
8
|
+
const eventsource_1 = require("eventsource");
|
|
9
9
|
const combinePrompts_1 = require("../utils/combinePrompts");
|
|
10
10
|
const toUsage_1 = require("../utils/toUsage");
|
|
11
11
|
const getUnixTimestamp_1 = require("../utils/getUnixTimestamp");
|
|
@@ -16,10 +16,11 @@ async function sleep(time) {
|
|
|
16
16
|
}, time);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
async function handleNonStreamingPrediction(prompt, prediction, replicate) {
|
|
19
|
+
async function handleNonStreamingPrediction(prompt, prediction, replicate, modelName) {
|
|
20
20
|
const pred = await replicate.wait(prediction, {});
|
|
21
|
-
const output = pred.output.reduce((acc, curr) =>
|
|
21
|
+
const output = pred.output.reduce((acc, curr) => acc + curr, '');
|
|
22
22
|
return {
|
|
23
|
+
model: modelName,
|
|
23
24
|
usage: (0, toUsage_1.toUsage)(prompt, output),
|
|
24
25
|
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
25
26
|
choices: [
|
|
@@ -38,7 +39,7 @@ async function* handleStreamingPrediction(prompt, prediction) {
|
|
|
38
39
|
if (!prediction?.urls?.stream) {
|
|
39
40
|
throw new Error('Prediction does not support streaming');
|
|
40
41
|
}
|
|
41
|
-
const source = new eventsource_1.
|
|
42
|
+
const source = new eventsource_1.EventSource(prediction.urls.stream, {
|
|
42
43
|
withCredentials: true,
|
|
43
44
|
});
|
|
44
45
|
let results = [];
|
|
@@ -57,7 +58,7 @@ async function* handleStreamingPrediction(prompt, prediction) {
|
|
|
57
58
|
while (!done) {
|
|
58
59
|
await promise;
|
|
59
60
|
await sleep(500);
|
|
60
|
-
const combined = results.reduce((acc, curr) =>
|
|
61
|
+
const combined = results.reduce((acc, curr) => acc + curr, '');
|
|
61
62
|
yield {
|
|
62
63
|
created: (0, getUnixTimestamp_1.getUnixTimestamp)(),
|
|
63
64
|
usage: (0, toUsage_1.toUsage)(prompt, combined),
|
|
@@ -80,19 +81,43 @@ async function ReplicateHandler(params) {
|
|
|
80
81
|
const replicate = new replicate_1.default({
|
|
81
82
|
auth: apiKey,
|
|
82
83
|
});
|
|
83
|
-
const
|
|
84
|
-
|
|
84
|
+
const modelName = params.model.startsWith('replicate/')
|
|
85
|
+
? params.model.slice(10)
|
|
86
|
+
: params.model;
|
|
87
|
+
const version = modelName.split(':')[1];
|
|
88
|
+
if (!version) {
|
|
89
|
+
throw new Error(`Invalid Replicate model format: ${params.model}. Expected format: replicate/<owner>/<name>:<version>`);
|
|
90
|
+
}
|
|
85
91
|
const prompt = (0, combinePrompts_1.combinePrompts)(params.messages);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
let prediction;
|
|
93
|
+
try {
|
|
94
|
+
prediction = await replicate.predictions.create({
|
|
95
|
+
version: version,
|
|
96
|
+
input: {
|
|
97
|
+
prompt,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
throw new Error(`Replicate API error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
103
|
+
}
|
|
92
104
|
if (params.stream) {
|
|
93
105
|
return handleStreamingPrediction(prompt, prediction);
|
|
94
106
|
}
|
|
95
|
-
return handleNonStreamingPrediction(prompt, prediction, replicate);
|
|
107
|
+
return handleNonStreamingPrediction(prompt, prediction, replicate, modelName);
|
|
96
108
|
}
|
|
97
|
-
const registry_1 = require("../registry");
|
|
98
|
-
(0, registry_1.
|
|
109
|
+
const registry_1 = require("../models/registry");
|
|
110
|
+
(0, registry_1.registerModelProvider)('replicate', async ({ apiKey } = {}) => {
|
|
111
|
+
const key = apiKey ?? process.env.REPLICATE_API_KEY;
|
|
112
|
+
if (!key)
|
|
113
|
+
return [];
|
|
114
|
+
const res = await fetch('https://api.replicate.com/v1/models', {
|
|
115
|
+
headers: { Authorization: `Bearer ${key}` },
|
|
116
|
+
});
|
|
117
|
+
if (!res.ok)
|
|
118
|
+
return [];
|
|
119
|
+
const { results } = await res.json();
|
|
120
|
+
return (results ?? []).map((m) => ({ id: `${m.owner}/${m.name}`, provider: 'replicate' }));
|
|
121
|
+
});
|
|
122
|
+
const registry_2 = require("../registry");
|
|
123
|
+
(0, registry_2.registerCompletionHandler)('replicate/', ReplicateHandler);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VertexAnthropicHandler = VertexAnthropicHandler;
|
|
4
|
+
const vertex_sdk_1 = require("@anthropic-ai/vertex-sdk");
|
|
5
|
+
const anthropic_1 = require("../utils/anthropic");
|
|
6
|
+
async function VertexAnthropicHandler(params) {
|
|
7
|
+
const project = params.project ?? process.env.GCP_PROJECT;
|
|
8
|
+
if (!project)
|
|
9
|
+
throw new Error('Vertex AI Anthropic requires GCP_PROJECT environment variable or project in params.');
|
|
10
|
+
const region = params.location ?? process.env.CLOUD_ML_REGION ?? 'us-central1';
|
|
11
|
+
const modelName = params.model.startsWith('vertex/')
|
|
12
|
+
? params.model.slice(7)
|
|
13
|
+
: params.model;
|
|
14
|
+
const anthropic = new vertex_sdk_1.AnthropicVertex({
|
|
15
|
+
projectId: project,
|
|
16
|
+
region,
|
|
17
|
+
});
|
|
18
|
+
const { system, messages } = (0, anthropic_1.toAnthropicMessages)(params.messages);
|
|
19
|
+
try {
|
|
20
|
+
if (params.stream) {
|
|
21
|
+
const stream = await anthropic.messages.create({
|
|
22
|
+
model: modelName,
|
|
23
|
+
max_tokens: params.max_tokens ?? 300,
|
|
24
|
+
messages,
|
|
25
|
+
...(system ? { system } : {}),
|
|
26
|
+
stream: true,
|
|
27
|
+
});
|
|
28
|
+
return (0, anthropic_1.toAnthropicStreamingResponse)(stream);
|
|
29
|
+
}
|
|
30
|
+
const message = await anthropic.messages.create({
|
|
31
|
+
model: modelName,
|
|
32
|
+
max_tokens: params.max_tokens ?? 300,
|
|
33
|
+
messages,
|
|
34
|
+
...(system ? { system } : {}),
|
|
35
|
+
});
|
|
36
|
+
return (0, anthropic_1.toAnthropicResponse)(message);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
throw new Error(`Vertex Anthropic error: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const registry_1 = require("../registry");
|
|
43
|
+
(0, registry_1.registerCompletionHandler)('vertex/claude-', VertexAnthropicHandler);
|