@llumiverse/drivers 0.19.0 → 0.21.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/lib/cjs/azure/azure_foundry.js +379 -0
- package/lib/cjs/azure/azure_foundry.js.map +1 -0
- package/lib/cjs/bedrock/converse.js +181 -123
- package/lib/cjs/bedrock/converse.js.map +1 -1
- package/lib/cjs/bedrock/index.js +157 -72
- package/lib/cjs/bedrock/index.js.map +1 -1
- package/lib/cjs/groq/index.js +91 -10
- package/lib/cjs/groq/index.js.map +1 -1
- package/lib/cjs/index.js +2 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/mistral/index.js +2 -1
- package/lib/cjs/mistral/index.js.map +1 -1
- package/lib/cjs/openai/azure_openai.js +72 -0
- package/lib/cjs/openai/azure_openai.js.map +1 -0
- package/lib/cjs/openai/index.js +6 -9
- package/lib/cjs/openai/index.js.map +1 -1
- package/lib/cjs/openai/openai.js +2 -2
- package/lib/cjs/openai/openai.js.map +1 -1
- package/lib/cjs/openai/openai_format.js +138 -0
- package/lib/cjs/openai/openai_format.js.map +1 -0
- package/lib/cjs/vertexai/index.js +1 -0
- package/lib/cjs/vertexai/index.js.map +1 -1
- package/lib/cjs/vertexai/models/claude.js +229 -118
- package/lib/cjs/vertexai/models/claude.js.map +1 -1
- package/lib/cjs/vertexai/models/gemini.js +110 -70
- package/lib/cjs/vertexai/models/gemini.js.map +1 -1
- package/lib/cjs/vertexai/models/imagen.js +2 -2
- package/lib/cjs/vertexai/models/imagen.js.map +1 -1
- package/lib/cjs/watsonx/index.js +11 -11
- package/lib/cjs/watsonx/index.js.map +1 -1
- package/lib/cjs/xai/index.js +3 -3
- package/lib/cjs/xai/index.js.map +1 -1
- package/lib/esm/azure/azure_foundry.js +373 -0
- package/lib/esm/azure/azure_foundry.js.map +1 -0
- package/lib/esm/bedrock/converse.js +180 -122
- package/lib/esm/bedrock/converse.js.map +1 -1
- package/lib/esm/bedrock/index.js +158 -73
- package/lib/esm/bedrock/index.js.map +1 -1
- package/lib/esm/groq/index.js +91 -10
- package/lib/esm/groq/index.js.map +1 -1
- package/lib/esm/index.js +2 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/mistral/index.js +2 -1
- package/lib/esm/mistral/index.js.map +1 -1
- package/lib/esm/openai/azure_openai.js +68 -0
- package/lib/esm/openai/azure_openai.js.map +1 -0
- package/lib/esm/openai/index.js +5 -8
- package/lib/esm/openai/index.js.map +1 -1
- package/lib/esm/openai/openai.js +2 -2
- package/lib/esm/openai/openai.js.map +1 -1
- package/lib/esm/openai/openai_format.js +134 -0
- package/lib/esm/openai/openai_format.js.map +1 -0
- package/lib/esm/src/adobe/firefly.js +115 -0
- package/lib/esm/src/adobe/firefly.js.map +1 -0
- package/lib/esm/src/bedrock/converse.js +278 -0
- package/lib/esm/src/bedrock/converse.js.map +1 -0
- package/lib/esm/src/bedrock/index.js +797 -0
- package/lib/esm/src/bedrock/index.js.map +1 -0
- package/lib/esm/src/bedrock/nova-image-payload.js +203 -0
- package/lib/esm/src/bedrock/nova-image-payload.js.map +1 -0
- package/lib/esm/src/bedrock/payloads.js +2 -0
- package/lib/esm/src/bedrock/payloads.js.map +1 -0
- package/lib/esm/src/bedrock/s3.js +99 -0
- package/lib/esm/src/bedrock/s3.js.map +1 -0
- package/lib/esm/src/groq/index.js +130 -0
- package/lib/esm/src/groq/index.js.map +1 -0
- package/lib/esm/src/huggingface_ie.js +196 -0
- package/lib/esm/src/huggingface_ie.js.map +1 -0
- package/lib/esm/src/index.js +13 -0
- package/lib/esm/src/index.js.map +1 -0
- package/lib/esm/src/mistral/index.js +167 -0
- package/lib/esm/src/mistral/index.js.map +1 -0
- package/lib/esm/src/mistral/types.js +80 -0
- package/lib/esm/src/mistral/types.js.map +1 -0
- package/{src/openai/azure.ts → lib/esm/src/openai/azure.js} +7 -34
- package/lib/esm/src/openai/azure.js.map +1 -0
- package/lib/esm/src/openai/index.js +463 -0
- package/lib/esm/src/openai/index.js.map +1 -0
- package/lib/esm/src/openai/openai.js +14 -0
- package/lib/esm/src/openai/openai.js.map +1 -0
- package/lib/esm/src/replicate.js +268 -0
- package/lib/esm/src/replicate.js.map +1 -0
- package/lib/esm/src/test/TestErrorCompletionStream.js +16 -0
- package/lib/esm/src/test/TestErrorCompletionStream.js.map +1 -0
- package/lib/esm/src/test/TestValidationErrorCompletionStream.js +20 -0
- package/lib/esm/src/test/TestValidationErrorCompletionStream.js.map +1 -0
- package/lib/esm/src/test/index.js +91 -0
- package/lib/esm/src/test/index.js.map +1 -0
- package/lib/esm/src/test/utils.js +25 -0
- package/lib/esm/src/test/utils.js.map +1 -0
- package/lib/esm/src/togetherai/index.js +122 -0
- package/lib/esm/src/togetherai/index.js.map +1 -0
- package/lib/esm/src/togetherai/interfaces.js +2 -0
- package/lib/esm/src/togetherai/interfaces.js.map +1 -0
- package/lib/esm/src/vertexai/debug.js +6 -0
- package/lib/esm/src/vertexai/debug.js.map +1 -0
- package/lib/esm/src/vertexai/embeddings/embeddings-image.js +24 -0
- package/lib/esm/src/vertexai/embeddings/embeddings-image.js.map +1 -0
- package/lib/esm/src/vertexai/embeddings/embeddings-text.js +20 -0
- package/lib/esm/src/vertexai/embeddings/embeddings-text.js.map +1 -0
- package/lib/esm/src/vertexai/index.js +270 -0
- package/lib/esm/src/vertexai/index.js.map +1 -0
- package/lib/esm/src/vertexai/models/claude.js +370 -0
- package/lib/esm/src/vertexai/models/claude.js.map +1 -0
- package/lib/esm/src/vertexai/models/gemini.js +700 -0
- package/lib/esm/src/vertexai/models/gemini.js.map +1 -0
- package/lib/esm/src/vertexai/models/imagen.js +310 -0
- package/lib/esm/src/vertexai/models/imagen.js.map +1 -0
- package/lib/esm/src/vertexai/models/llama.js +178 -0
- package/lib/esm/src/vertexai/models/llama.js.map +1 -0
- package/lib/esm/src/vertexai/models.js +21 -0
- package/lib/esm/src/vertexai/models.js.map +1 -0
- package/lib/esm/src/watsonx/index.js +157 -0
- package/lib/esm/src/watsonx/index.js.map +1 -0
- package/lib/esm/src/watsonx/interfaces.js +2 -0
- package/lib/esm/src/watsonx/interfaces.js.map +1 -0
- package/lib/esm/src/xai/index.js +64 -0
- package/lib/esm/src/xai/index.js.map +1 -0
- package/lib/esm/tsconfig.tsbuildinfo +1 -0
- package/lib/esm/vertexai/index.js +1 -0
- package/lib/esm/vertexai/index.js.map +1 -1
- package/lib/esm/vertexai/models/claude.js +230 -119
- package/lib/esm/vertexai/models/claude.js.map +1 -1
- package/lib/esm/vertexai/models/gemini.js +109 -70
- package/lib/esm/vertexai/models/gemini.js.map +1 -1
- package/lib/esm/vertexai/models/imagen.js +2 -2
- package/lib/esm/vertexai/models/imagen.js.map +1 -1
- package/lib/esm/watsonx/index.js +11 -11
- package/lib/esm/watsonx/index.js.map +1 -1
- package/lib/esm/xai/index.js +2 -2
- package/lib/esm/xai/index.js.map +1 -1
- package/lib/types/azure/azure_foundry.d.ts +50 -0
- package/lib/types/azure/azure_foundry.d.ts.map +1 -0
- package/lib/types/bedrock/converse.d.ts +2 -2
- package/lib/types/bedrock/converse.d.ts.map +1 -1
- package/lib/types/bedrock/index.d.ts +5 -5
- package/lib/types/bedrock/index.d.ts.map +1 -1
- package/lib/types/groq/index.d.ts +5 -5
- package/lib/types/groq/index.d.ts.map +1 -1
- package/lib/types/index.d.ts +2 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/mistral/index.d.ts +2 -2
- package/lib/types/mistral/index.d.ts.map +1 -1
- package/lib/types/openai/azure_openai.d.ts +25 -0
- package/lib/types/openai/azure_openai.d.ts.map +1 -0
- package/lib/types/openai/index.d.ts +6 -7
- package/lib/types/openai/index.d.ts.map +1 -1
- package/lib/types/openai/openai.d.ts +2 -2
- package/lib/types/openai/openai.d.ts.map +1 -1
- package/lib/types/openai/openai_format.d.ts +19 -0
- package/lib/types/openai/openai_format.d.ts.map +1 -0
- package/lib/types/src/adobe/firefly.d.ts +29 -0
- package/lib/types/src/bedrock/converse.d.ts +8 -0
- package/lib/types/src/bedrock/index.d.ts +57 -0
- package/lib/types/src/bedrock/nova-image-payload.d.ts +73 -0
- package/lib/types/src/bedrock/payloads.d.ts +11 -0
- package/lib/types/src/bedrock/s3.d.ts +22 -0
- package/lib/types/src/groq/index.d.ts +23 -0
- package/lib/types/src/huggingface_ie.d.ts +31 -0
- package/lib/types/src/index.d.ts +12 -0
- package/lib/types/src/mistral/index.d.ts +24 -0
- package/lib/types/src/mistral/types.d.ts +131 -0
- package/lib/types/src/openai/azure.d.ts +19 -0
- package/lib/types/src/openai/index.d.ts +25 -0
- package/lib/types/src/openai/openai.d.ts +14 -0
- package/lib/types/src/replicate.d.ts +44 -0
- package/lib/types/src/test/TestErrorCompletionStream.d.ts +8 -0
- package/lib/types/src/test/TestValidationErrorCompletionStream.d.ts +8 -0
- package/lib/types/src/test/index.d.ts +23 -0
- package/lib/types/src/test/utils.d.ts +4 -0
- package/lib/types/src/togetherai/index.d.ts +22 -0
- package/lib/types/src/togetherai/interfaces.d.ts +95 -0
- package/lib/types/src/vertexai/debug.d.ts +1 -0
- package/lib/types/src/vertexai/embeddings/embeddings-image.d.ts +10 -0
- package/lib/types/src/vertexai/embeddings/embeddings-text.d.ts +9 -0
- package/lib/types/src/vertexai/index.d.ts +49 -0
- package/lib/types/src/vertexai/models/claude.d.ts +17 -0
- package/lib/types/src/vertexai/models/gemini.d.ts +16 -0
- package/lib/types/src/vertexai/models/imagen.d.ts +74 -0
- package/lib/types/src/vertexai/models/llama.d.ts +19 -0
- package/lib/types/src/vertexai/models.d.ts +14 -0
- package/lib/types/src/watsonx/index.d.ts +26 -0
- package/lib/types/src/watsonx/interfaces.d.ts +64 -0
- package/lib/types/src/xai/index.d.ts +18 -0
- package/lib/types/vertexai/index.d.ts +2 -3
- package/lib/types/vertexai/index.d.ts.map +1 -1
- package/lib/types/vertexai/models/claude.d.ts +5 -7
- package/lib/types/vertexai/models/claude.d.ts.map +1 -1
- package/lib/types/vertexai/models/gemini.d.ts +4 -2
- package/lib/types/vertexai/models/gemini.d.ts.map +1 -1
- package/lib/types/vertexai/models.d.ts +2 -2
- package/lib/types/vertexai/models.d.ts.map +1 -1
- package/lib/types/xai/index.d.ts.map +1 -1
- package/package.json +20 -16
- package/src/azure/azure_foundry.ts +450 -0
- package/src/bedrock/converse.ts +194 -129
- package/src/bedrock/index.ts +182 -84
- package/src/groq/index.ts +107 -16
- package/src/index.ts +2 -1
- package/src/mistral/index.ts +3 -2
- package/src/openai/azure_openai.ts +92 -0
- package/src/openai/index.ts +19 -22
- package/src/openai/openai.ts +2 -5
- package/src/openai/openai_format.ts +165 -0
- package/src/vertexai/index.ts +3 -3
- package/src/vertexai/models/claude.ts +270 -138
- package/src/vertexai/models/gemini.ts +120 -77
- package/src/vertexai/models/imagen.ts +3 -3
- package/src/vertexai/models.ts +2 -2
- package/src/watsonx/index.ts +17 -17
- package/src/xai/index.ts +2 -3
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
|
|
2
|
+
import { AIModel, DriverOptions, getModelCapabilities, modelModalitiesToArray, Providers } from "@llumiverse/core";
|
|
3
|
+
import OpenAI, { AzureOpenAI } from "openai";
|
|
4
|
+
import { BaseOpenAIDriver } from "./index.js";
|
|
5
|
+
|
|
6
|
+
export interface AzureOpenAIDriverOptions extends DriverOptions {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The credentials to use to access Azure OpenAI
|
|
10
|
+
*/
|
|
11
|
+
azureADTokenProvider?: any; //type with azure credentials
|
|
12
|
+
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
|
|
15
|
+
endpoint?: string;
|
|
16
|
+
|
|
17
|
+
apiVersion?: string
|
|
18
|
+
|
|
19
|
+
deployment?: string;
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class AzureOpenAIDriver extends BaseOpenAIDriver {
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
service: AzureOpenAI;
|
|
27
|
+
readonly provider = Providers.azure_openai;
|
|
28
|
+
|
|
29
|
+
//Overload to allow independent instantiation with AzureOpenAI service
|
|
30
|
+
constructor(serviceOrOpts: AzureOpenAI | AzureOpenAIDriverOptions) {
|
|
31
|
+
if (serviceOrOpts instanceof AzureOpenAI) {
|
|
32
|
+
super({});
|
|
33
|
+
this.service = serviceOrOpts;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const opts = serviceOrOpts ?? {};
|
|
37
|
+
super(opts);
|
|
38
|
+
if (!opts.azureADTokenProvider && !opts.apiKey) {
|
|
39
|
+
opts.azureADTokenProvider = this.getDefaultCognitiveServicesAuth();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.service = new AzureOpenAI({
|
|
43
|
+
apiKey: opts.apiKey,
|
|
44
|
+
azureADTokenProvider: opts.azureADTokenProvider,
|
|
45
|
+
endpoint: opts.endpoint,
|
|
46
|
+
apiVersion: opts.apiVersion ?? "2024-10-21",
|
|
47
|
+
deployment: opts.deployment
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get default authentication for Azure Cognitive Services API
|
|
53
|
+
*/
|
|
54
|
+
getDefaultCognitiveServicesAuth() {
|
|
55
|
+
const scope = "https://cognitiveservices.azure.com/.default";
|
|
56
|
+
const azureADTokenProvider = getBearerTokenProvider(new DefaultAzureCredential(), scope);
|
|
57
|
+
return azureADTokenProvider;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async listModels(): Promise<AIModel[]> {
|
|
61
|
+
return this._listModels();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async _listModels(_filter?: (m: OpenAI.Models.Model) => boolean): Promise<AIModel[]> {
|
|
65
|
+
if (!this.service.deploymentName) {
|
|
66
|
+
throw new Error("A specific deployment is not set. Azure OpenAI cannot list deployments. Update your endpoint URL to include the deployment name, e.g., https://your-resource.openai.azure.com/openai/deployments/your-deployment/chat/completions");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//Do a test execution to check if the model works and to get the model ID.
|
|
70
|
+
let modelID = this.service.deploymentName;
|
|
71
|
+
try {
|
|
72
|
+
const testResponse = await this.service.chat.completions.create({
|
|
73
|
+
model: this.service.deploymentName,
|
|
74
|
+
messages: [{ role: "user", content: "Hi" }],
|
|
75
|
+
max_tokens: 1,
|
|
76
|
+
});
|
|
77
|
+
modelID = testResponse.model;
|
|
78
|
+
} catch (error) {
|
|
79
|
+
this.logger.error("Failed to test model for Azure OpenAI listing :", error);
|
|
80
|
+
}
|
|
81
|
+
const modelCapability = getModelCapabilities(modelID, "openai");
|
|
82
|
+
return [{
|
|
83
|
+
id: modelID,
|
|
84
|
+
name: this.service.deploymentName,
|
|
85
|
+
provider: this.provider,
|
|
86
|
+
owner: "openai",
|
|
87
|
+
input_modalities: modelModalitiesToArray(modelCapability.input),
|
|
88
|
+
output_modalities: modelModalitiesToArray(modelCapability.output),
|
|
89
|
+
tool_support: modelCapability.tool_support,
|
|
90
|
+
} satisfies AIModel<string>];
|
|
91
|
+
}
|
|
92
|
+
}
|
package/src/openai/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
ExecutionTokenUsage,
|
|
12
12
|
JSONSchema,
|
|
13
13
|
ModelType,
|
|
14
|
+
Providers,
|
|
14
15
|
ToolDefinition,
|
|
15
16
|
ToolUse,
|
|
16
17
|
TrainingJob,
|
|
@@ -22,13 +23,11 @@ import {
|
|
|
22
23
|
supportsToolUse,
|
|
23
24
|
} from "@llumiverse/core";
|
|
24
25
|
import { asyncMap } from "@llumiverse/core/async";
|
|
25
|
-
import { formatOpenAILikeMultimodalPrompt } from "
|
|
26
|
+
import { formatOpenAILikeMultimodalPrompt } from "./openai_format.js";
|
|
26
27
|
import OpenAI, { AzureOpenAI } from "openai";
|
|
28
|
+
import { ChatCompletionMessageParam } from "openai/resources/chat/completions";
|
|
27
29
|
import { Stream } from "openai/streaming";
|
|
28
30
|
|
|
29
|
-
//For code readability
|
|
30
|
-
type OpenAIMessageBlock = OpenAI.Chat.Completions.ChatCompletionMessageParam;
|
|
31
|
-
|
|
32
31
|
//TODO: Do we need a list?, replace with if statements and modernise?
|
|
33
32
|
const supportFineTunning = new Set([
|
|
34
33
|
"gpt-3.5-turbo-1106",
|
|
@@ -43,14 +42,15 @@ export interface BaseOpenAIDriverOptions extends DriverOptions {
|
|
|
43
42
|
|
|
44
43
|
export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
45
44
|
BaseOpenAIDriverOptions,
|
|
46
|
-
|
|
45
|
+
ChatCompletionMessageParam[]
|
|
47
46
|
> {
|
|
48
|
-
abstract provider: "azure_openai" | "openai" | "xai";
|
|
47
|
+
//abstract provider: "azure_openai" | "openai" | "xai" | "azure_foundry";
|
|
48
|
+
abstract provider: Providers.openai | Providers.azure_openai | "xai" | Providers.azure_foundry;
|
|
49
49
|
abstract service: OpenAI | AzureOpenAI;
|
|
50
50
|
|
|
51
51
|
constructor(opts: BaseOpenAIDriverOptions) {
|
|
52
52
|
super(opts);
|
|
53
|
-
this.formatPrompt = formatOpenAILikeMultimodalPrompt
|
|
53
|
+
this.formatPrompt = formatOpenAILikeMultimodalPrompt
|
|
54
54
|
//TODO: better type, we send back OpenAI.Chat.Completions.ChatCompletionMessageParam[] but just not compatible with Function call that we don't use here
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -82,7 +82,7 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
async requestTextCompletionStream(prompt:
|
|
85
|
+
async requestTextCompletionStream(prompt: ChatCompletionMessageParam[], options: ExecutionOptions): Promise<AsyncIterable<Completion>> {
|
|
86
86
|
if (options.model_options?._option_id !== "openai-text" && options.model_options?._option_id !== "openai-thinking") {
|
|
87
87
|
this.logger.warn("Invalid model options", { options: options.model_options });
|
|
88
88
|
}
|
|
@@ -157,7 +157,7 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
157
157
|
return asyncMap(stream, mapFn);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
async requestTextCompletion(prompt:
|
|
160
|
+
async requestTextCompletion(prompt: ChatCompletionMessageParam[], options: ExecutionOptions): Promise<Completion> {
|
|
161
161
|
if (options.model_options?._option_id !== "openai-text" && options.model_options?._option_id !== "openai-thinking") {
|
|
162
162
|
this.logger.warn("Invalid model options", { options: options.model_options });
|
|
163
163
|
}
|
|
@@ -170,7 +170,7 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
170
170
|
const toolDefs = getToolDefinitions(options.tools);
|
|
171
171
|
const useTools: boolean = toolDefs ? supportsToolUse(options.model, "openai") : false;
|
|
172
172
|
|
|
173
|
-
let conversation = updateConversation(options.conversation as
|
|
173
|
+
let conversation = updateConversation(options.conversation as ChatCompletionMessageParam[], prompt);
|
|
174
174
|
|
|
175
175
|
let parsedSchema: JSONSchema | undefined = undefined;
|
|
176
176
|
let strictMode = false;
|
|
@@ -293,12 +293,6 @@ export abstract class BaseOpenAIDriver extends AbstractDriver<
|
|
|
293
293
|
const wordBlacklist = ["embed", "whisper", "transcribe", "audio", "moderation", "tts",
|
|
294
294
|
"realtime", "dall-e", "babbage", "davinci", "codex", "o1-pro"];
|
|
295
295
|
|
|
296
|
-
if (this.provider === "azure_openai") {
|
|
297
|
-
//Azure OpenAI has additional information about the models
|
|
298
|
-
result = result.filter((m) => {
|
|
299
|
-
return !(m as any)?.capabilities?.embeddings;
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
296
|
|
|
303
297
|
//OpenAI has very little information, filtering based on name.
|
|
304
298
|
result = result.filter((m) => {
|
|
@@ -377,7 +371,7 @@ function jobInfo(job: OpenAI.FineTuning.Jobs.FineTuningJob): TrainingJob {
|
|
|
377
371
|
}
|
|
378
372
|
}
|
|
379
373
|
|
|
380
|
-
function insert_image_detail(messages:
|
|
374
|
+
function insert_image_detail(messages: ChatCompletionMessageParam[], detail_level: string): ChatCompletionMessageParam[] {
|
|
381
375
|
if (detail_level == "auto" || detail_level == "low" || detail_level == "high") {
|
|
382
376
|
for (const message of messages) {
|
|
383
377
|
if (message.role !== 'assistant' && message.content) {
|
|
@@ -395,7 +389,7 @@ function insert_image_detail(messages: OpenAIMessageBlock[], detail_level: strin
|
|
|
395
389
|
return messages;
|
|
396
390
|
}
|
|
397
391
|
|
|
398
|
-
function convertRoles(messages:
|
|
392
|
+
function convertRoles(messages: ChatCompletionMessageParam[], model: string): ChatCompletionMessageParam[] {
|
|
399
393
|
//New openai models use developer role instead of system
|
|
400
394
|
if (model.includes("o1") || model.includes("o3")) {
|
|
401
395
|
if (model.includes("o1-mini") || model.includes("o1-preview")) {
|
|
@@ -462,7 +456,7 @@ function openAiFinishReason(finish_reason?: string): string | undefined {
|
|
|
462
456
|
return finish_reason;
|
|
463
457
|
}
|
|
464
458
|
|
|
465
|
-
function updateConversation(conversation:
|
|
459
|
+
function updateConversation(conversation: ChatCompletionMessageParam[], message: ChatCompletionMessageParam[]): ChatCompletionMessageParam[] {
|
|
466
460
|
if (!message) {
|
|
467
461
|
return conversation;
|
|
468
462
|
}
|
|
@@ -489,12 +483,15 @@ export function collectTools(toolCalls?: OpenAI.Chat.Completions.ChatCompletionM
|
|
|
489
483
|
return tools.length > 0 ? tools : undefined;
|
|
490
484
|
}
|
|
491
485
|
|
|
492
|
-
function createPromptFromResponse(response: OpenAI.Chat.Completions.ChatCompletionMessage)
|
|
493
|
-
const messages:
|
|
486
|
+
function createPromptFromResponse(response: OpenAI.Chat.Completions.ChatCompletionMessage): ChatCompletionMessageParam[] {
|
|
487
|
+
const messages: ChatCompletionMessageParam[] = [];
|
|
494
488
|
if (response) {
|
|
495
489
|
messages.push({
|
|
496
490
|
role: response.role,
|
|
497
|
-
content:
|
|
491
|
+
content: [{
|
|
492
|
+
type: "text",
|
|
493
|
+
text: response.content ?? ""
|
|
494
|
+
}],
|
|
498
495
|
tool_calls: response.tool_calls,
|
|
499
496
|
});
|
|
500
497
|
}
|
package/src/openai/openai.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
import { DriverOptions } from "@llumiverse/core";
|
|
3
|
+
import { DriverOptions, Providers } from "@llumiverse/core";
|
|
4
4
|
import OpenAI from "openai";
|
|
5
5
|
import { BaseOpenAIDriver } from "./index.js";
|
|
6
6
|
|
|
@@ -19,15 +19,12 @@ export interface OpenAIDriverOptions extends DriverOptions {
|
|
|
19
19
|
export class OpenAIDriver extends BaseOpenAIDriver {
|
|
20
20
|
|
|
21
21
|
service: OpenAI;
|
|
22
|
-
provider
|
|
22
|
+
readonly provider = Providers.openai;
|
|
23
23
|
|
|
24
24
|
constructor(opts: OpenAIDriverOptions) {
|
|
25
25
|
super(opts);
|
|
26
26
|
this.service = new OpenAI({
|
|
27
27
|
apiKey: opts.apiKey
|
|
28
28
|
});
|
|
29
|
-
this.provider = "openai";
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
30
|
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// This file is used by multiple drivers
|
|
2
|
+
// to format prompts in a way that is compatible with OpenAI's API.
|
|
3
|
+
|
|
4
|
+
import { PromptRole, PromptOptions, PromptSegment } from "@llumiverse/common";
|
|
5
|
+
import { readStreamAsBase64 } from "@llumiverse/core";
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
ChatCompletionMessageParam,
|
|
9
|
+
ChatCompletionContentPartText,
|
|
10
|
+
ChatCompletionContentPartImage,
|
|
11
|
+
ChatCompletionUserMessageParam,
|
|
12
|
+
ChatCompletionSystemMessageParam,
|
|
13
|
+
ChatCompletionAssistantMessageParam,
|
|
14
|
+
ChatCompletionToolMessageParam
|
|
15
|
+
} from 'openai/resources/chat/completions';
|
|
16
|
+
|
|
17
|
+
export interface OpenAITextMessage {
|
|
18
|
+
content: string;
|
|
19
|
+
role: 'system' | 'user' | 'assistant' | 'developer';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* OpenAI text only prompts
|
|
24
|
+
* @param segments
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
export function formatOpenAILikeTextPrompt(segments: PromptSegment[]): OpenAITextMessage[] {
|
|
28
|
+
const system: OpenAITextMessage[] = [];
|
|
29
|
+
const safety: OpenAITextMessage[] = [];
|
|
30
|
+
const user: OpenAITextMessage[] = [];
|
|
31
|
+
|
|
32
|
+
for (const msg of segments) {
|
|
33
|
+
if (msg.role === PromptRole.system) {
|
|
34
|
+
system.push({ content: msg.content, role: "system" });
|
|
35
|
+
} else if (msg.role === PromptRole.safety) {
|
|
36
|
+
safety.push({ content: "IMPORTANT: " + msg.content, role: "system" });
|
|
37
|
+
} else if (msg.role !== PromptRole.negative && msg.role !== PromptRole.mask && msg.role !== PromptRole.tool) {
|
|
38
|
+
user.push({
|
|
39
|
+
content: msg.content,
|
|
40
|
+
role: msg.role || 'user',
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// put system messages first and safety last
|
|
46
|
+
return system.concat(user).concat(safety);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
export async function formatOpenAILikeMultimodalPrompt(segments: PromptSegment[], opts: PromptOptions & OpenAIPromptFormatterOptions): Promise<ChatCompletionMessageParam[]> {
|
|
51
|
+
const system: ChatCompletionMessageParam[] = [];
|
|
52
|
+
const safety: ChatCompletionMessageParam[] = [];
|
|
53
|
+
const others: ChatCompletionMessageParam[] = [];
|
|
54
|
+
|
|
55
|
+
for (const msg of segments) {
|
|
56
|
+
|
|
57
|
+
const parts: (ChatCompletionContentPartImage | ChatCompletionContentPartText)[] = [];
|
|
58
|
+
|
|
59
|
+
//generate the parts based on PromptSegment
|
|
60
|
+
if (msg.files) {
|
|
61
|
+
for (const file of msg.files) {
|
|
62
|
+
const stream = await file.getStream();
|
|
63
|
+
const data = await readStreamAsBase64(stream);
|
|
64
|
+
parts.push({
|
|
65
|
+
type: "image_url",
|
|
66
|
+
image_url: {
|
|
67
|
+
url: `data:${file.mime_type || "image/jpeg"};base64,${data}`,
|
|
68
|
+
//detail: "auto" //This is modified just before execution to "low" | "high" | "auto"
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (msg.content) {
|
|
75
|
+
parts.push({
|
|
76
|
+
text: msg.content,
|
|
77
|
+
type: "text"
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if (msg.role === PromptRole.system) {
|
|
83
|
+
// For system messages, filter to only text parts
|
|
84
|
+
const textParts = parts.filter((part): part is ChatCompletionContentPartText => part.type === 'text');
|
|
85
|
+
const systemMsg: ChatCompletionSystemMessageParam = {
|
|
86
|
+
role: "system",
|
|
87
|
+
content: textParts.length === 1 && !msg.files ? textParts[0].text : textParts
|
|
88
|
+
};
|
|
89
|
+
system.push(systemMsg);
|
|
90
|
+
|
|
91
|
+
if (opts.useToolForFormatting && opts.schema) {
|
|
92
|
+
system.forEach(s => {
|
|
93
|
+
if (typeof s.content === 'string') {
|
|
94
|
+
s.content = "TOOL: " + s.content;
|
|
95
|
+
} else if (Array.isArray(s.content)) {
|
|
96
|
+
s.content.forEach((c: any) => {
|
|
97
|
+
if (c.type === "text") c.text = "TOOL: " + c.text;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
} else if (msg.role === PromptRole.safety) {
|
|
104
|
+
const textParts = parts.filter((part): part is ChatCompletionContentPartText => part.type === 'text');
|
|
105
|
+
const safetyMsg: ChatCompletionSystemMessageParam = {
|
|
106
|
+
role: "system",
|
|
107
|
+
content: textParts
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
if (Array.isArray(safetyMsg.content)) {
|
|
111
|
+
safetyMsg.content.forEach((c: any) => {
|
|
112
|
+
if (c.type === "text") c.text = "DO NOT IGNORE - IMPORTANT: " + c.text;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
system.push(safetyMsg);
|
|
117
|
+
} else if (msg.role === PromptRole.tool) {
|
|
118
|
+
if (!msg.tool_use_id) {
|
|
119
|
+
throw new Error("Tool use id is required for tool messages")
|
|
120
|
+
}
|
|
121
|
+
const toolMsg: ChatCompletionToolMessageParam = {
|
|
122
|
+
role: "tool",
|
|
123
|
+
tool_call_id: msg.tool_use_id,
|
|
124
|
+
content: msg.content || ""
|
|
125
|
+
};
|
|
126
|
+
others.push(toolMsg);
|
|
127
|
+
} else if (msg.role !== PromptRole.negative && msg.role !== PromptRole.mask) {
|
|
128
|
+
if (msg.role === 'assistant') {
|
|
129
|
+
const assistantMsg: ChatCompletionAssistantMessageParam = {
|
|
130
|
+
role: 'assistant',
|
|
131
|
+
content: parts as (ChatCompletionContentPartText)[]
|
|
132
|
+
};
|
|
133
|
+
others.push(assistantMsg);
|
|
134
|
+
} else {
|
|
135
|
+
const userMsg: ChatCompletionUserMessageParam = {
|
|
136
|
+
role: 'user',
|
|
137
|
+
content: parts
|
|
138
|
+
};
|
|
139
|
+
others.push(userMsg);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (opts.result_schema && !opts.useToolForFormatting) {
|
|
146
|
+
const schemaMsg: ChatCompletionSystemMessageParam = {
|
|
147
|
+
role: "system",
|
|
148
|
+
content: [{
|
|
149
|
+
type: "text",
|
|
150
|
+
text: "IMPORTANT: only answer using JSON, and respecting the schema included below, between the <response_schema> tags. " + `<response_schema>${JSON.stringify(opts.result_schema)}</response_schema>`
|
|
151
|
+
}]
|
|
152
|
+
};
|
|
153
|
+
system.push(schemaMsg);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// put system messages first and safety last
|
|
157
|
+
return ([] as ChatCompletionMessageParam[]).concat(system).concat(others).concat(safety);
|
|
158
|
+
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface OpenAIPromptFormatterOptions {
|
|
162
|
+
multimodal?: boolean
|
|
163
|
+
useToolForFormatting?: boolean
|
|
164
|
+
schema?: Object
|
|
165
|
+
}
|
package/src/vertexai/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { getEmbeddingsForImages } from "./embeddings/embeddings-image.js";
|
|
|
23
23
|
import { v1beta1 } from "@google-cloud/aiplatform";
|
|
24
24
|
import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";
|
|
25
25
|
import { ImagenModelDefinition, ImagenPrompt } from "./models/imagen.js";
|
|
26
|
-
import { GoogleGenAI, Content
|
|
26
|
+
import { GoogleGenAI, Content } from "@google/genai";
|
|
27
27
|
|
|
28
28
|
export interface VertexAIDriverOptions extends DriverOptions {
|
|
29
29
|
project: string;
|
|
@@ -33,8 +33,7 @@ export interface VertexAIDriverOptions extends DriverOptions {
|
|
|
33
33
|
|
|
34
34
|
export interface GenerateContentPrompt {
|
|
35
35
|
contents: Content[];
|
|
36
|
-
system?:
|
|
37
|
-
tools?: Tool[];
|
|
36
|
+
system?: Content;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
//General Prompt type for VertexAI
|
|
@@ -123,6 +122,7 @@ export class VertexAIDriver extends AbstractDriver<VertexAIDriverOptions, Vertex
|
|
|
123
122
|
//Lazy initialisation
|
|
124
123
|
if (!this.anthropicClient) {
|
|
125
124
|
this.anthropicClient = new AnthropicVertex({
|
|
125
|
+
timeout: 20 * 60 * 10000, // Set to 20 minutes, 10 minute default, setting this disables long request error: https://github.com/anthropics/anthropic-sdk-typescript?#long-requests
|
|
126
126
|
region: "us-east5",
|
|
127
127
|
projectId: process.env.GOOGLE_PROJECT_ID,
|
|
128
128
|
});
|