@llumiverse/drivers 0.14.0 → 0.16.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 +3 -3
- package/lib/cjs/adobe/firefly.js +119 -0
- package/lib/cjs/adobe/firefly.js.map +1 -0
- package/lib/cjs/bedrock/converse.js +177 -0
- package/lib/cjs/bedrock/converse.js.map +1 -0
- package/lib/cjs/bedrock/index.js +329 -228
- package/lib/cjs/bedrock/index.js.map +1 -1
- package/lib/cjs/bedrock/nova-image-payload.js +207 -0
- package/lib/cjs/bedrock/nova-image-payload.js.map +1 -0
- package/lib/cjs/groq/index.js +34 -9
- package/lib/cjs/groq/index.js.map +1 -1
- package/lib/cjs/huggingface_ie.js +28 -12
- package/lib/cjs/huggingface_ie.js.map +1 -1
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/mistral/index.js +31 -12
- package/lib/cjs/mistral/index.js.map +1 -1
- package/lib/cjs/mistral/types.js.map +1 -1
- package/lib/cjs/openai/index.js +149 -27
- package/lib/cjs/openai/index.js.map +1 -1
- package/lib/cjs/replicate.js +16 -18
- package/lib/cjs/replicate.js.map +1 -1
- package/lib/cjs/test/TestValidationErrorCompletionStream.js.map +1 -1
- package/lib/cjs/test/index.js.map +1 -1
- package/lib/cjs/togetherai/index.js +40 -10
- package/lib/cjs/togetherai/index.js.map +1 -1
- package/lib/cjs/vertexai/embeddings/embeddings-image.js +26 -0
- package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +1 -0
- package/lib/cjs/vertexai/embeddings/embeddings-text.js +1 -1
- package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +1 -1
- package/lib/cjs/vertexai/index.js +92 -25
- package/lib/cjs/vertexai/index.js.map +1 -1
- package/lib/cjs/vertexai/models/claude.js +252 -0
- package/lib/cjs/vertexai/models/claude.js.map +1 -0
- package/lib/cjs/vertexai/models/gemini.js +169 -27
- package/lib/cjs/vertexai/models/gemini.js.map +1 -1
- package/lib/cjs/vertexai/models/imagen.js +317 -0
- package/lib/cjs/vertexai/models/imagen.js.map +1 -0
- package/lib/cjs/vertexai/models.js +12 -107
- package/lib/cjs/vertexai/models.js.map +1 -1
- package/lib/cjs/watsonx/index.js +39 -8
- package/lib/cjs/watsonx/index.js.map +1 -1
- package/lib/cjs/xai/index.js +71 -0
- package/lib/cjs/xai/index.js.map +1 -0
- package/lib/esm/adobe/firefly.js +115 -0
- package/lib/esm/adobe/firefly.js.map +1 -0
- package/lib/esm/bedrock/converse.js +171 -0
- package/lib/esm/bedrock/converse.js.map +1 -0
- package/lib/esm/bedrock/index.js +331 -230
- package/lib/esm/bedrock/index.js.map +1 -1
- package/lib/esm/bedrock/nova-image-payload.js +203 -0
- package/lib/esm/bedrock/nova-image-payload.js.map +1 -0
- package/lib/esm/groq/index.js +34 -9
- package/lib/esm/groq/index.js.map +1 -1
- package/lib/esm/huggingface_ie.js +29 -13
- package/lib/esm/huggingface_ie.js.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/mistral/index.js +31 -12
- package/lib/esm/mistral/index.js.map +1 -1
- package/lib/esm/mistral/types.js.map +1 -1
- package/lib/esm/openai/index.js +150 -28
- package/lib/esm/openai/index.js.map +1 -1
- package/lib/esm/replicate.js +17 -19
- package/lib/esm/replicate.js.map +1 -1
- package/lib/esm/test/TestValidationErrorCompletionStream.js.map +1 -1
- package/lib/esm/test/index.js.map +1 -1
- package/lib/esm/togetherai/index.js +40 -10
- package/lib/esm/togetherai/index.js.map +1 -1
- package/lib/esm/vertexai/embeddings/embeddings-image.js +23 -0
- package/lib/esm/vertexai/embeddings/embeddings-image.js.map +1 -0
- package/lib/esm/vertexai/embeddings/embeddings-text.js +1 -1
- package/lib/esm/vertexai/embeddings/embeddings-text.js.map +1 -1
- package/lib/esm/vertexai/index.js +93 -27
- package/lib/esm/vertexai/index.js.map +1 -1
- package/lib/esm/vertexai/models/claude.js +247 -0
- package/lib/esm/vertexai/models/claude.js.map +1 -0
- package/lib/esm/vertexai/models/gemini.js +170 -28
- package/lib/esm/vertexai/models/gemini.js.map +1 -1
- package/lib/esm/vertexai/models/imagen.js +310 -0
- package/lib/esm/vertexai/models/imagen.js.map +1 -0
- package/lib/esm/vertexai/models.js +12 -104
- package/lib/esm/vertexai/models.js.map +1 -1
- package/lib/esm/watsonx/index.js +39 -8
- package/lib/esm/watsonx/index.js.map +1 -1
- package/lib/esm/xai/index.js +64 -0
- package/lib/esm/xai/index.js.map +1 -0
- package/lib/types/adobe/firefly.d.ts +30 -0
- package/lib/types/adobe/firefly.d.ts.map +1 -0
- package/lib/types/bedrock/converse.d.ts +8 -0
- package/lib/types/bedrock/converse.d.ts.map +1 -0
- package/lib/types/bedrock/index.d.ts +26 -11
- package/lib/types/bedrock/index.d.ts.map +1 -1
- package/lib/types/bedrock/nova-image-payload.d.ts +74 -0
- package/lib/types/bedrock/nova-image-payload.d.ts.map +1 -0
- package/lib/types/bedrock/payloads.d.ts +9 -65
- package/lib/types/bedrock/payloads.d.ts.map +1 -1
- package/lib/types/groq/index.d.ts +3 -3
- package/lib/types/groq/index.d.ts.map +1 -1
- package/lib/types/huggingface_ie.d.ts +5 -7
- package/lib/types/huggingface_ie.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/mistral/index.d.ts +4 -4
- package/lib/types/mistral/index.d.ts.map +1 -1
- package/lib/types/mistral/types.d.ts +1 -0
- package/lib/types/mistral/types.d.ts.map +1 -1
- package/lib/types/openai/index.d.ts +5 -4
- package/lib/types/openai/index.d.ts.map +1 -1
- package/lib/types/replicate.d.ts +4 -9
- package/lib/types/replicate.d.ts.map +1 -1
- package/lib/types/test/index.d.ts +2 -2
- package/lib/types/test/index.d.ts.map +1 -1
- package/lib/types/togetherai/index.d.ts +4 -4
- package/lib/types/togetherai/index.d.ts.map +1 -1
- package/lib/types/vertexai/embeddings/embeddings-image.d.ts +11 -0
- package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +1 -0
- package/lib/types/vertexai/index.d.ts +19 -8
- package/lib/types/vertexai/index.d.ts.map +1 -1
- package/lib/types/vertexai/models/claude.d.ts +20 -0
- package/lib/types/vertexai/models/claude.d.ts.map +1 -0
- package/lib/types/vertexai/models/gemini.d.ts +4 -4
- package/lib/types/vertexai/models/gemini.d.ts.map +1 -1
- package/lib/types/vertexai/models/imagen.d.ts +75 -0
- package/lib/types/vertexai/models/imagen.d.ts.map +1 -0
- package/lib/types/vertexai/models.d.ts +3 -6
- package/lib/types/vertexai/models.d.ts.map +1 -1
- package/lib/types/watsonx/index.d.ts +3 -3
- package/lib/types/watsonx/index.d.ts.map +1 -1
- package/lib/types/xai/index.d.ts +19 -0
- package/lib/types/xai/index.d.ts.map +1 -0
- package/package.json +24 -23
- package/src/adobe/firefly.ts +207 -0
- package/src/bedrock/converse.ts +194 -0
- package/src/bedrock/index.ts +349 -237
- package/src/bedrock/nova-image-payload.ts +309 -0
- package/src/bedrock/payloads.ts +12 -66
- package/src/groq/index.ts +35 -12
- package/src/huggingface_ie.ts +34 -13
- package/src/index.ts +1 -0
- package/src/mistral/index.ts +34 -12
- package/src/mistral/types.ts +2 -1
- package/src/openai/index.ts +167 -33
- package/src/replicate.ts +21 -20
- package/src/test/TestValidationErrorCompletionStream.ts +2 -2
- package/src/test/index.ts +3 -2
- package/src/togetherai/index.ts +44 -12
- package/src/vertexai/embeddings/embeddings-image.ts +50 -0
- package/src/vertexai/embeddings/embeddings-text.ts +1 -1
- package/src/vertexai/index.ts +114 -37
- package/src/vertexai/models/claude.ts +281 -0
- package/src/vertexai/models/gemini.ts +181 -31
- package/src/vertexai/models/imagen.ts +401 -0
- package/src/vertexai/models.ts +16 -120
- package/src/watsonx/index.ts +42 -10
- package/src/xai/index.ts +110 -0
- package/lib/cjs/vertexai/models/codey-chat.js +0 -65
- package/lib/cjs/vertexai/models/codey-chat.js.map +0 -1
- package/lib/cjs/vertexai/models/codey-text.js +0 -35
- package/lib/cjs/vertexai/models/codey-text.js.map +0 -1
- package/lib/cjs/vertexai/models/palm-model-base.js +0 -59
- package/lib/cjs/vertexai/models/palm-model-base.js.map +0 -1
- package/lib/cjs/vertexai/models/palm2-chat.js +0 -65
- package/lib/cjs/vertexai/models/palm2-chat.js.map +0 -1
- package/lib/cjs/vertexai/models/palm2-text.js +0 -35
- package/lib/cjs/vertexai/models/palm2-text.js.map +0 -1
- package/lib/cjs/vertexai/utils/tensor.js +0 -86
- package/lib/cjs/vertexai/utils/tensor.js.map +0 -1
- package/lib/esm/vertexai/models/codey-chat.js +0 -61
- package/lib/esm/vertexai/models/codey-chat.js.map +0 -1
- package/lib/esm/vertexai/models/codey-text.js +0 -31
- package/lib/esm/vertexai/models/codey-text.js.map +0 -1
- package/lib/esm/vertexai/models/palm-model-base.js +0 -55
- package/lib/esm/vertexai/models/palm-model-base.js.map +0 -1
- package/lib/esm/vertexai/models/palm2-chat.js +0 -61
- package/lib/esm/vertexai/models/palm2-chat.js.map +0 -1
- package/lib/esm/vertexai/models/palm2-text.js +0 -31
- package/lib/esm/vertexai/models/palm2-text.js.map +0 -1
- package/lib/esm/vertexai/utils/tensor.js +0 -82
- package/lib/esm/vertexai/utils/tensor.js.map +0 -1
- package/lib/types/vertexai/models/codey-chat.d.ts +0 -51
- package/lib/types/vertexai/models/codey-chat.d.ts.map +0 -1
- package/lib/types/vertexai/models/codey-text.d.ts +0 -39
- package/lib/types/vertexai/models/codey-text.d.ts.map +0 -1
- package/lib/types/vertexai/models/palm-model-base.d.ts +0 -61
- package/lib/types/vertexai/models/palm-model-base.d.ts.map +0 -1
- package/lib/types/vertexai/models/palm2-chat.d.ts +0 -61
- package/lib/types/vertexai/models/palm2-chat.d.ts.map +0 -1
- package/lib/types/vertexai/models/palm2-text.d.ts +0 -39
- package/lib/types/vertexai/models/palm2-text.d.ts.map +0 -1
- package/lib/types/vertexai/utils/tensor.d.ts +0 -6
- package/lib/types/vertexai/utils/tensor.d.ts.map +0 -1
- package/src/vertexai/models/codey-chat.ts +0 -115
- package/src/vertexai/models/codey-text.ts +0 -69
- package/src/vertexai/models/palm-model-base.ts +0 -128
- package/src/vertexai/models/palm2-chat.ts +0 -119
- package/src/vertexai/models/palm2-text.ts +0 -69
- package/src/vertexai/utils/tensor.ts +0 -82
package/src/openai/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
AIModel,
|
|
3
3
|
AbstractDriver,
|
|
4
4
|
Completion,
|
|
5
|
+
CompletionChunkObject,
|
|
5
6
|
DataSource,
|
|
6
7
|
DriverOptions,
|
|
7
8
|
EmbeddingsOptions,
|
|
@@ -9,16 +10,18 @@ import {
|
|
|
9
10
|
ExecutionOptions,
|
|
10
11
|
ExecutionTokenUsage,
|
|
11
12
|
ModelType,
|
|
13
|
+
ToolDefinition,
|
|
12
14
|
TrainingJob,
|
|
13
15
|
TrainingJobStatus,
|
|
14
16
|
TrainingOptions,
|
|
15
|
-
TrainingPromptOptions
|
|
17
|
+
TrainingPromptOptions,
|
|
16
18
|
} from "@llumiverse/core";
|
|
17
19
|
import { asyncMap } from "@llumiverse/core/async";
|
|
18
20
|
import { formatOpenAILikeMultimodalPrompt } from "@llumiverse/core/formatters";
|
|
19
21
|
import OpenAI, { AzureOpenAI } from "openai";
|
|
20
22
|
import { Stream } from "openai/streaming";
|
|
21
23
|
|
|
24
|
+
//TODO: Do we need a list?, replace with if statements and modernise?
|
|
22
25
|
const supportFineTunning = new Set([
|
|
23
26
|
"gpt-3.5-turbo-1106",
|
|
24
27
|
"gpt-3.5-turbo-0613",
|
|
@@ -34,8 +37,8 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
34
37
|
BaseOpenAIDriverOptions,
|
|
35
38
|
OpenAI.Chat.Completions.ChatCompletionMessageParam[]
|
|
36
39
|
> {
|
|
37
|
-
abstract provider: "azure_openai" | "openai";
|
|
38
|
-
abstract service: OpenAI | AzureOpenAI
|
|
40
|
+
abstract provider: "azure_openai" | "openai" | "xai";
|
|
41
|
+
abstract service: OpenAI | AzureOpenAI;
|
|
39
42
|
|
|
40
43
|
constructor(opts: BaseOpenAIDriverOptions) {
|
|
41
44
|
super(opts);
|
|
@@ -54,19 +57,25 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
54
57
|
};
|
|
55
58
|
|
|
56
59
|
const choice = result.choices[0];
|
|
57
|
-
const finish_reason = choice.finish_reason;
|
|
58
60
|
|
|
59
61
|
//if no schema, return content
|
|
60
62
|
if (!options.result_schema) {
|
|
61
63
|
return {
|
|
62
|
-
result: choice.message.content
|
|
64
|
+
result: choice.message.content ?? undefined,
|
|
63
65
|
token_usage: tokenInfo,
|
|
64
|
-
finish_reason
|
|
66
|
+
finish_reason: choice.finish_reason, //Uses expected "stop" , "length" format
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
const useTools: boolean = !isNonStructureSupporting(options.model);
|
|
71
|
+
let data = undefined;
|
|
72
|
+
if (useTools) {
|
|
73
|
+
//we have a schema: get the content and return after validation
|
|
74
|
+
data = choice?.message.tool_calls?.[0].function.arguments ?? choice.message.content ?? undefined;
|
|
75
|
+
} else {
|
|
76
|
+
data = choice.message.content ?? undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
if (!data) {
|
|
71
80
|
this.logger?.error("[OpenAI] Response is not valid", result);
|
|
72
81
|
throw new Error("Response is not valid: no data");
|
|
@@ -75,29 +84,57 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
75
84
|
return {
|
|
76
85
|
result: data,
|
|
77
86
|
token_usage: tokenInfo,
|
|
78
|
-
finish_reason
|
|
87
|
+
finish_reason: choice.finish_reason,
|
|
79
88
|
};
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
async
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
async requestTextCompletionStream(prompt: OpenAI.Chat.Completions.ChatCompletionMessageParam[], options: ExecutionOptions): Promise<any> {
|
|
92
|
+
if (options.model_options?._option_id !== "openai-text" && options.model_options?._option_id !== "openai-thinking") {
|
|
93
|
+
this.logger.warn("Invalid model options", { options: options.model_options });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const useTools: boolean = !isNonStructureSupporting(options.model);
|
|
97
|
+
|
|
98
|
+
const mapFn = (chunk: OpenAI.Chat.Completions.ChatCompletionChunk) => {
|
|
99
|
+
let result = undefined
|
|
100
|
+
if (useTools && this.provider !== "xai" && options.result_schema) {
|
|
101
|
+
result = chunk.choices[0]?.delta?.tool_calls?.[0].function?.arguments ?? "";
|
|
102
|
+
} else {
|
|
103
|
+
result = chunk.choices[0]?.delta.content ?? "";
|
|
88
104
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
result: result,
|
|
108
|
+
finish_reason: chunk.choices[0]?.finish_reason, //Uses expected "stop" , "length" format
|
|
109
|
+
token_usage: {
|
|
110
|
+
prompt: chunk.usage?.prompt_tokens,
|
|
111
|
+
result: chunk.usage?.completion_tokens,
|
|
112
|
+
total: (chunk.usage?.prompt_tokens ?? 0) + (chunk.usage?.completion_tokens ?? 0),
|
|
113
|
+
}
|
|
114
|
+
} as CompletionChunkObject;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
convertRoles(prompt, options.model);
|
|
118
|
+
|
|
119
|
+
const model_options = options.model_options as any;
|
|
120
|
+
insert_image_detail(prompt, model_options?.image_detail ?? "auto");
|
|
92
121
|
|
|
93
122
|
const stream = (await this.service.chat.completions.create({
|
|
94
123
|
stream: true,
|
|
124
|
+
stream_options: { include_usage: true },
|
|
95
125
|
model: options.model,
|
|
96
126
|
messages: prompt,
|
|
97
|
-
|
|
127
|
+
reasoning_effort: model_options?.reasoning_effort,
|
|
128
|
+
temperature: model_options?.temperature,
|
|
129
|
+
top_p: model_options?.top_p,
|
|
130
|
+
//top_logprobs: options.top_logprobs, //Logprobs output currently not supported
|
|
131
|
+
//logprobs: options.top_logprobs ? true : false,
|
|
132
|
+
presence_penalty: model_options?.presence_penalty,
|
|
133
|
+
frequency_penalty: model_options?.frequency_penalty,
|
|
98
134
|
n: 1,
|
|
99
|
-
max_tokens:
|
|
100
|
-
tools: options.
|
|
135
|
+
max_completion_tokens: model_options?.max_tokens, //TODO: use max_tokens for older models, currently relying on OpenAI to handle it
|
|
136
|
+
//tools: getToolDefinitions(options.tools),
|
|
137
|
+
tools: useTools ? options.result_schema && this.provider.includes("openai")
|
|
101
138
|
? [
|
|
102
139
|
{
|
|
103
140
|
function: {
|
|
@@ -107,19 +144,24 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
107
144
|
type: "function"
|
|
108
145
|
} as OpenAI.Chat.ChatCompletionTool,
|
|
109
146
|
]
|
|
110
|
-
: undefined,
|
|
111
|
-
tool_choice: options.result_schema
|
|
147
|
+
: undefined : undefined,
|
|
148
|
+
tool_choice: useTools ? options.result_schema
|
|
112
149
|
? {
|
|
113
150
|
type: 'function',
|
|
114
151
|
function: { name: "format_output" }
|
|
115
|
-
} : undefined,
|
|
152
|
+
} : undefined : undefined,
|
|
153
|
+
stop: model_options?.stop_sequence,
|
|
116
154
|
})) as Stream<OpenAI.Chat.Completions.ChatCompletionChunk>;
|
|
117
155
|
|
|
118
156
|
return asyncMap(stream, mapFn);
|
|
119
157
|
}
|
|
120
158
|
|
|
121
|
-
async
|
|
122
|
-
|
|
159
|
+
async requestTextCompletion(prompt: OpenAI.Chat.Completions.ChatCompletionMessageParam[], options: ExecutionOptions): Promise<any> {
|
|
160
|
+
if (options.model_options?._option_id !== "openai-text" && options.model_options?._option_id !== "openai-thinking") {
|
|
161
|
+
this.logger.warn("Invalid model options", { options: options.model_options });
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const functions = options.result_schema && this.provider.includes("openai")
|
|
123
165
|
? [
|
|
124
166
|
{
|
|
125
167
|
function: {
|
|
@@ -131,19 +173,32 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
131
173
|
]
|
|
132
174
|
: undefined;
|
|
133
175
|
|
|
176
|
+
convertRoles(prompt, options.model);
|
|
177
|
+
const useTools: boolean = !isNonStructureSupporting(options.model);
|
|
178
|
+
const model_options = options.model_options as any;
|
|
179
|
+
insert_image_detail(prompt, model_options?.image_detail ?? "auto");
|
|
180
|
+
|
|
134
181
|
const res = await this.service.chat.completions.create({
|
|
135
182
|
stream: false,
|
|
136
183
|
model: options.model,
|
|
137
184
|
messages: prompt,
|
|
138
|
-
|
|
185
|
+
reasoning_effort: model_options?.reasoning_effort,
|
|
186
|
+
temperature: model_options?.temperature,
|
|
187
|
+
top_p: model_options?.top_p,
|
|
188
|
+
//top_logprobs: options.top_logprobs, //Logprobs output currently not supported
|
|
189
|
+
//logprobs: options.top_logprobs ? true : false,
|
|
190
|
+
presence_penalty: model_options?.presence_penalty,
|
|
191
|
+
frequency_penalty: model_options?.frequency_penalty,
|
|
139
192
|
n: 1,
|
|
140
|
-
max_tokens:
|
|
141
|
-
tools:
|
|
142
|
-
|
|
193
|
+
max_completion_tokens: model_options?.max_tokens, //TODO: use max_tokens for older models, currently relying on OpenAI to handle it
|
|
194
|
+
//tools: getToolDefinitions(options.tools),
|
|
195
|
+
tools: useTools ? functions : undefined,
|
|
196
|
+
tool_choice: useTools ? options.result_schema && this.provider.includes("openai")
|
|
143
197
|
? {
|
|
144
198
|
type: 'function',
|
|
145
199
|
function: { name: "format_output" }
|
|
146
|
-
} : undefined,
|
|
200
|
+
} : undefined : undefined,
|
|
201
|
+
stop: model_options?.stop_sequence,
|
|
147
202
|
// functions: functions,
|
|
148
203
|
// function_call: options.result_schema
|
|
149
204
|
// ? { name: "format_output" }
|
|
@@ -157,6 +212,16 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
157
212
|
return completion;
|
|
158
213
|
}
|
|
159
214
|
|
|
215
|
+
protected canStream(_options: ExecutionOptions): Promise<boolean> {
|
|
216
|
+
if (_options.model.includes("o1")
|
|
217
|
+
&& !(_options.model.includes("mini") || _options.model.includes("preview"))) {
|
|
218
|
+
//o1 full does not support streaming
|
|
219
|
+
//TODO: Update when OpenAI adds support for streaming, last check 16/02/2025
|
|
220
|
+
return Promise.resolve(false);
|
|
221
|
+
}
|
|
222
|
+
return Promise.resolve(true);
|
|
223
|
+
}
|
|
224
|
+
|
|
160
225
|
createTrainingPrompt(options: TrainingPromptOptions): Promise<string> {
|
|
161
226
|
if (options.model.includes("gpt")) {
|
|
162
227
|
return super.createTrainingPrompt(options);
|
|
@@ -226,9 +291,18 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
226
291
|
}
|
|
227
292
|
|
|
228
293
|
|
|
229
|
-
async generateEmbeddings({
|
|
294
|
+
async generateEmbeddings({ text, image, model = "text-embedding-3-small" }: EmbeddingsOptions): Promise<EmbeddingsResult> {
|
|
295
|
+
|
|
296
|
+
if (image) {
|
|
297
|
+
throw new Error("Image embeddings not supported by OpenAI");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (!text) {
|
|
301
|
+
throw new Error("No text provided");
|
|
302
|
+
}
|
|
303
|
+
|
|
230
304
|
const res = await this.service.embeddings.create({
|
|
231
|
-
input:
|
|
305
|
+
input: text,
|
|
232
306
|
model: model,
|
|
233
307
|
});
|
|
234
308
|
|
|
@@ -266,4 +340,64 @@ function jobInfo(job: OpenAI.FineTuning.Jobs.FineTuningJob): TrainingJob {
|
|
|
266
340
|
status,
|
|
267
341
|
details
|
|
268
342
|
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function insert_image_detail(messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[], detail_level: string): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {
|
|
346
|
+
if (detail_level == "auto" || detail_level == "low" || detail_level == "high") {
|
|
347
|
+
for (const message of messages) {
|
|
348
|
+
if (message.role !== 'assistant' && message.content) {
|
|
349
|
+
for (const part of message.content) {
|
|
350
|
+
if (typeof part === "string") {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (part.type === 'image_url') {
|
|
354
|
+
part.image_url = { ...part.image_url, detail: detail_level };
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return messages;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function convertRoles(messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[], model: string): OpenAI.Chat.Completions.ChatCompletionMessageParam[] {
|
|
364
|
+
//New openai models use developer role instead of system
|
|
365
|
+
if (model.includes("o1") || model.includes("o3")) {
|
|
366
|
+
if (model.includes("o1-mini") || model.includes("o1-preview")) {
|
|
367
|
+
//o1-mini and o1-preview support neither system nor developer
|
|
368
|
+
for (const message of messages) {
|
|
369
|
+
if (message.role === 'system') {
|
|
370
|
+
(message.role as any) = 'user';
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
} else {
|
|
374
|
+
//Models newer than o1 use developer role
|
|
375
|
+
for (const message of messages) {
|
|
376
|
+
if (message.role === 'system') {
|
|
377
|
+
(message.role as any) = 'developer';
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return messages
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function isNonStructureSupporting(model: string): boolean {
|
|
386
|
+
return model.includes("o1-mini") || model.includes("o1-preview")
|
|
387
|
+
|| model.includes("chatgpt-4o");
|
|
388
|
+
}
|
|
389
|
+
//@ts-ignore
|
|
390
|
+
function getToolDefinitions(tools: ToolDefinition[] | undefined | null): OpenAI.ChatCompletionTool[] | undefined {
|
|
391
|
+
return tools ? tools.map(getToolDefinition) : undefined;
|
|
392
|
+
}
|
|
393
|
+
function getToolDefinition(toolDef: ToolDefinition): OpenAI.ChatCompletionTool {
|
|
394
|
+
return {
|
|
395
|
+
type: "function",
|
|
396
|
+
function: {
|
|
397
|
+
name: toolDef.name,
|
|
398
|
+
description: toolDef.description,
|
|
399
|
+
parameters: toolDef.input_schema,
|
|
400
|
+
strict: true
|
|
401
|
+
},
|
|
402
|
+
} satisfies OpenAI.ChatCompletionTool;
|
|
269
403
|
}
|
package/src/replicate.ts
CHANGED
|
@@ -2,14 +2,16 @@ import {
|
|
|
2
2
|
AIModel,
|
|
3
3
|
AbstractDriver,
|
|
4
4
|
Completion,
|
|
5
|
+
CompletionChunk,
|
|
5
6
|
DataSource,
|
|
6
7
|
DriverOptions,
|
|
7
8
|
EmbeddingsResult,
|
|
8
9
|
ExecutionOptions,
|
|
9
10
|
ModelSearchPayload,
|
|
11
|
+
TextFallbackOptions,
|
|
10
12
|
TrainingJob,
|
|
11
13
|
TrainingJobStatus,
|
|
12
|
-
TrainingOptions
|
|
14
|
+
TrainingOptions,
|
|
13
15
|
} from "@llumiverse/core";
|
|
14
16
|
import { EventStream } from "@llumiverse/core/async";
|
|
15
17
|
import EventSource from "eventsource";
|
|
@@ -55,25 +57,25 @@ export class ReplicateDriver extends AbstractDriver<DriverOptions, string> {
|
|
|
55
57
|
});
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
extractDataFromResponse(
|
|
60
|
+
extractDataFromResponse(response: Prediction): Completion {
|
|
59
61
|
const text = response.output.join("");
|
|
60
62
|
return {
|
|
61
63
|
result: text,
|
|
62
|
-
token_usage: {
|
|
63
|
-
result: response.output.length,
|
|
64
|
-
prompt: prompt.length,
|
|
65
|
-
total: response.output.length + prompt.length,
|
|
66
|
-
},
|
|
67
64
|
};
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
async
|
|
67
|
+
async requestTextCompletionStream(prompt: string, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunk>> {
|
|
68
|
+
if (options.model_options?._option_id !== "text-fallback") {
|
|
69
|
+
this.logger.warn("Invalid model options", {options: options.model_options });
|
|
70
|
+
}
|
|
71
|
+
options.model_options = options.model_options as TextFallbackOptions;
|
|
72
|
+
|
|
71
73
|
const model = ReplicateDriver.parseModelId(options.model);
|
|
72
74
|
const predictionData = {
|
|
73
75
|
input: {
|
|
74
76
|
prompt: prompt,
|
|
75
|
-
max_new_tokens: options.max_tokens,
|
|
76
|
-
temperature: options.temperature,
|
|
77
|
+
max_new_tokens: options.model_options?.max_tokens,
|
|
78
|
+
temperature: options.model_options?.temperature,
|
|
77
79
|
},
|
|
78
80
|
version: model.version,
|
|
79
81
|
stream: true, //streaming described here https://replicate.com/blog/streaming
|
|
@@ -82,7 +84,7 @@ export class ReplicateDriver extends AbstractDriver<DriverOptions, string> {
|
|
|
82
84
|
const prediction =
|
|
83
85
|
await this.service.predictions.create(predictionData);
|
|
84
86
|
|
|
85
|
-
const stream = new EventStream<
|
|
87
|
+
const stream = new EventStream<CompletionChunk>();
|
|
86
88
|
|
|
87
89
|
const source = new EventSource(prediction.urls.stream!);
|
|
88
90
|
source.addEventListener("output", (e: any) => {
|
|
@@ -95,7 +97,7 @@ export class ReplicateDriver extends AbstractDriver<DriverOptions, string> {
|
|
|
95
97
|
} catch (error) {
|
|
96
98
|
error = JSON.stringify(e);
|
|
97
99
|
}
|
|
98
|
-
this.logger?.error(
|
|
100
|
+
this.logger?.error("Error in SSE stream", {e, error});
|
|
99
101
|
});
|
|
100
102
|
source.addEventListener("done", () => {
|
|
101
103
|
try {
|
|
@@ -107,13 +109,17 @@ export class ReplicateDriver extends AbstractDriver<DriverOptions, string> {
|
|
|
107
109
|
return stream;
|
|
108
110
|
}
|
|
109
111
|
|
|
110
|
-
async
|
|
112
|
+
async requestTextCompletion(prompt: string, options: ExecutionOptions) {
|
|
113
|
+
if (options.model_options?._option_id !== "text-fallback") {
|
|
114
|
+
this.logger.warn("Invalid model options", {options: options.model_options });
|
|
115
|
+
}
|
|
116
|
+
options.model_options = options.model_options as TextFallbackOptions;
|
|
111
117
|
const model = ReplicateDriver.parseModelId(options.model);
|
|
112
118
|
const predictionData = {
|
|
113
119
|
input: {
|
|
114
120
|
prompt: prompt,
|
|
115
|
-
max_new_tokens: options.max_tokens,
|
|
116
|
-
temperature: options.temperature,
|
|
121
|
+
max_new_tokens: options.model_options?.max_tokens,
|
|
122
|
+
temperature: options.model_options?.temperature,
|
|
117
123
|
},
|
|
118
124
|
version: model.version,
|
|
119
125
|
//TODO stream
|
|
@@ -133,11 +139,6 @@ export class ReplicateDriver extends AbstractDriver<DriverOptions, string> {
|
|
|
133
139
|
const text = res.output.join("");
|
|
134
140
|
return {
|
|
135
141
|
result: text,
|
|
136
|
-
token_usage: {
|
|
137
|
-
result: res.output.length,
|
|
138
|
-
prompt: prompt.length,
|
|
139
|
-
total: res.output.length + prompt.length,
|
|
140
|
-
},
|
|
141
142
|
original_response: options.include_original_response ? res : undefined,
|
|
142
143
|
};
|
|
143
144
|
}
|
|
@@ -12,9 +12,9 @@ export class TestValidationErrorCompletionStream implements CompletionStream<Pro
|
|
|
12
12
|
async *[Symbol.asyncIterator]() {
|
|
13
13
|
yield "Started TestValidationError.\n";
|
|
14
14
|
await sleep(1000);
|
|
15
|
-
yield "chunk1\n"
|
|
15
|
+
yield "chunk1\n";
|
|
16
16
|
await sleep(1000);
|
|
17
|
-
yield "chunk2\n"
|
|
17
|
+
yield "chunk2\n";
|
|
18
18
|
await sleep(1000);
|
|
19
19
|
this.completion = createValidationErrorCompletion(this.segments);
|
|
20
20
|
}
|
package/src/test/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AIModel, AIModelStatus, CompletionStream, Driver, EmbeddingsResult, ExecutionOptions, ExecutionResponse, ModelType,
|
|
1
|
+
import { AIModel, AIModelStatus, CompletionStream, Driver, EmbeddingsResult, ExecutionOptions, ExecutionResponse, ModelType, PromptSegment, TrainingJob } from "@llumiverse/core";
|
|
2
2
|
import { TestErrorCompletionStream } from "./TestErrorCompletionStream.js";
|
|
3
3
|
import { TestValidationErrorCompletionStream } from "./TestValidationErrorCompletionStream.js";
|
|
4
4
|
import { createValidationErrorCompletion, sleep, throwError } from "./utils.js";
|
|
@@ -30,9 +30,10 @@ export class TestDriver implements Driver<PromptSegment[]> {
|
|
|
30
30
|
throw new Error("Method not implemented.");
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
async createPrompt(segments: PromptSegment[], _opts:
|
|
33
|
+
async createPrompt(segments: PromptSegment[], _opts: ExecutionOptions): Promise<PromptSegment[]> {
|
|
34
34
|
return segments;
|
|
35
35
|
}
|
|
36
|
+
|
|
36
37
|
execute(segments: PromptSegment[], options: ExecutionOptions): Promise<ExecutionResponse<PromptSegment[]>> {
|
|
37
38
|
switch (options.model) {
|
|
38
39
|
case TestDriverModels.executionError:
|
package/src/togetherai/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AIModel, AbstractDriver, Completion, DriverOptions, EmbeddingsResult, ExecutionOptions } from "@llumiverse/core";
|
|
1
|
+
import { AIModel, AbstractDriver, Completion, CompletionChunk, DriverOptions, EmbeddingsResult, ExecutionOptions, TextFallbackOptions } from "@llumiverse/core";
|
|
2
2
|
import { transformSSEStream } from "@llumiverse/core/async";
|
|
3
3
|
import { FetchClient } from "api-fetch-client";
|
|
4
4
|
import { TextCompletion, TogetherModelInfo } from "./interfaces.js";
|
|
@@ -21,7 +21,7 @@ export class TogetherAIDriver extends AbstractDriver<TogetherAIDriverOptions, st
|
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
getResponseFormat = (options: ExecutionOptions) => {
|
|
24
|
+
getResponseFormat = (options: ExecutionOptions): { type: string; schema: any } | undefined => {
|
|
25
25
|
return options.result_schema ?
|
|
26
26
|
{
|
|
27
27
|
type: "json_object",
|
|
@@ -29,17 +29,30 @@ export class TogetherAIDriver extends AbstractDriver<TogetherAIDriverOptions, st
|
|
|
29
29
|
} : undefined;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async
|
|
32
|
+
async requestTextCompletion(prompt: string, options: ExecutionOptions): Promise<Completion<any>> {
|
|
33
|
+
if (options.model_options?._option_id !== "text-fallback") {
|
|
34
|
+
this.logger.warn("Invalid model options", {options: options.model_options });
|
|
35
|
+
}
|
|
36
|
+
options.model_options = options.model_options as TextFallbackOptions;
|
|
37
|
+
|
|
38
|
+
const stop_seq = options.model_options?.stop_sequence ?? [];
|
|
39
|
+
|
|
33
40
|
const res = await this.fetchClient.post('/v1/completions', {
|
|
34
41
|
payload: {
|
|
35
42
|
model: options.model,
|
|
36
43
|
prompt: prompt,
|
|
37
44
|
response_format: this.getResponseFormat(options),
|
|
38
|
-
max_tokens: options.max_tokens,
|
|
39
|
-
temperature: options.temperature,
|
|
45
|
+
max_tokens: options.model_options?.max_tokens,
|
|
46
|
+
temperature: options.model_options?.temperature,
|
|
47
|
+
top_p: options.model_options?.top_p,
|
|
48
|
+
top_k: options.model_options?.top_k,
|
|
49
|
+
//logprobs: options.top_logprobs, //Logprobs output currently not supported
|
|
50
|
+
frequency_penalty: options.model_options?.frequency_penalty,
|
|
51
|
+
presence_penalty: options.model_options?.presence_penalty,
|
|
40
52
|
stop: [
|
|
41
53
|
"</s>",
|
|
42
|
-
"[/INST]"
|
|
54
|
+
"[/INST]",
|
|
55
|
+
...stop_seq,
|
|
43
56
|
],
|
|
44
57
|
}
|
|
45
58
|
}) as TextCompletion;
|
|
@@ -53,24 +66,35 @@ export class TogetherAIDriver extends AbstractDriver<TogetherAIDriverOptions, st
|
|
|
53
66
|
result: usage.completion_tokens,
|
|
54
67
|
total: usage.total_tokens,
|
|
55
68
|
},
|
|
56
|
-
finish_reason: choice.finish_reason,
|
|
69
|
+
finish_reason: choice.finish_reason, //Uses expected "stop" , "length" format
|
|
57
70
|
original_response: options.include_original_response ? res : undefined,
|
|
58
71
|
}
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
async
|
|
74
|
+
async requestTextCompletionStream(prompt: string, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunk>> {
|
|
75
|
+
if (options.model_options?._option_id !== "text-fallback") {
|
|
76
|
+
this.logger.warn("Invalid model options", {options: options.model_options });
|
|
77
|
+
}
|
|
78
|
+
options.model_options = options.model_options as TextFallbackOptions;
|
|
62
79
|
|
|
80
|
+
const stop_seq = options.model_options?.stop_sequence ?? [];
|
|
63
81
|
const stream = await this.fetchClient.post('/v1/completions', {
|
|
64
82
|
payload: {
|
|
65
83
|
model: options.model,
|
|
66
84
|
prompt: prompt,
|
|
67
|
-
max_tokens: options.max_tokens,
|
|
68
|
-
temperature: options.temperature,
|
|
85
|
+
max_tokens: options.model_options?.max_tokens,
|
|
86
|
+
temperature: options.model_options?.temperature,
|
|
69
87
|
response_format: this.getResponseFormat(options),
|
|
88
|
+
top_p: options.model_options?.top_p,
|
|
89
|
+
top_k: options.model_options?.top_k,
|
|
90
|
+
//logprobs: options.top_logprobs, //Logprobs output currently not supported
|
|
91
|
+
frequency_penalty: options.model_options?.frequency_penalty,
|
|
92
|
+
presence_penalty: options.model_options?.presence_penalty,
|
|
70
93
|
stream: true,
|
|
71
94
|
stop: [
|
|
72
95
|
"</s>",
|
|
73
|
-
"[/INST]"
|
|
96
|
+
"[/INST]",
|
|
97
|
+
...stop_seq,
|
|
74
98
|
],
|
|
75
99
|
},
|
|
76
100
|
reader: 'sse'
|
|
@@ -78,7 +102,15 @@ export class TogetherAIDriver extends AbstractDriver<TogetherAIDriverOptions, st
|
|
|
78
102
|
|
|
79
103
|
return transformSSEStream(stream, (data: string) => {
|
|
80
104
|
const json = JSON.parse(data);
|
|
81
|
-
return
|
|
105
|
+
return {
|
|
106
|
+
result: json.choices[0]?.text ?? '',
|
|
107
|
+
finish_reason: json.choices[0]?.finish_reason, //Uses expected "stop" , "length" format
|
|
108
|
+
token_usage: {
|
|
109
|
+
prompt: json.usage?.prompt_tokens,
|
|
110
|
+
result: json.usage?.completion_tokens,
|
|
111
|
+
total: json.usage?.prompt_tokens + json.usage?.completion_tokens,
|
|
112
|
+
}
|
|
113
|
+
};
|
|
82
114
|
});
|
|
83
115
|
|
|
84
116
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
|
|
2
|
+
import { EmbeddingsOptions, EmbeddingsResult } from '@llumiverse/core';
|
|
3
|
+
import { VertexAIDriver } from '../index.js';
|
|
4
|
+
|
|
5
|
+
export interface ImageEmbeddingsOptions {
|
|
6
|
+
model?: string;
|
|
7
|
+
image?: {bytesBase64Encoded?: string}, // the image to generate embeddings for
|
|
8
|
+
text: string, // the text to generate embeddings for
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface EmbedingsForImagePrompt {
|
|
12
|
+
instances: ImageEmbeddingsOptions[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ImageEmbeddingsResult {
|
|
16
|
+
predictions: [
|
|
17
|
+
{
|
|
18
|
+
imageEmbedding: number[]
|
|
19
|
+
textEmbedding: number[]
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
deployedModelId: string,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//Currently we are only supporting either text or images sent to the multimodal model.
|
|
26
|
+
export async function getEmbeddingsForImages(driver: VertexAIDriver, options: EmbeddingsOptions): Promise<EmbeddingsResult> {
|
|
27
|
+
|
|
28
|
+
// API is returns a 400 Error if a property is empty, so you undefined and "as" to remove the property entirely.
|
|
29
|
+
const prompt = {
|
|
30
|
+
instances: [{
|
|
31
|
+
text: options.image ? undefined : options.text,
|
|
32
|
+
image: options.image ?
|
|
33
|
+
{
|
|
34
|
+
bytesBase64Encoded: options.image
|
|
35
|
+
}
|
|
36
|
+
: undefined,
|
|
37
|
+
}]
|
|
38
|
+
} as EmbedingsForImagePrompt;
|
|
39
|
+
|
|
40
|
+
const model = options.model || "multimodalembedding@001";
|
|
41
|
+
|
|
42
|
+
const result = await driver.fetchClient.post(`/publishers/google/models/${model}:predict`, {
|
|
43
|
+
payload: prompt
|
|
44
|
+
}) as ImageEmbeddingsResult;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
values: result.predictions[0].imageEmbedding ?? result.predictions[0].textEmbedding,
|
|
48
|
+
model: model,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -38,7 +38,7 @@ export async function getEmbeddingsForText(driver: VertexAIDriver, options: Text
|
|
|
38
38
|
}]
|
|
39
39
|
} as EmbedingsForTextPrompt;
|
|
40
40
|
|
|
41
|
-
const model = options.model || "
|
|
41
|
+
const model = options.model || "text-embedding-004";
|
|
42
42
|
|
|
43
43
|
const result = await driver.fetchClient.post(`/publishers/google/models/${model}:predict`, {
|
|
44
44
|
payload: prompt
|