@llumiverse/drivers 0.20.0 → 0.22.0-dev.1
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/adobe/firefly.js +6 -5
- package/lib/cjs/adobe/firefly.js.map +1 -1
- package/lib/cjs/azure/azure_foundry.js +388 -0
- package/lib/cjs/azure/azure_foundry.js.map +1 -0
- package/lib/cjs/bedrock/index.js +62 -39
- package/lib/cjs/bedrock/index.js.map +1 -1
- package/lib/cjs/groq/index.js +178 -22
- package/lib/cjs/groq/index.js.map +1 -1
- package/lib/cjs/huggingface_ie.js +5 -4
- package/lib/cjs/huggingface_ie.js.map +1 -1
- package/lib/cjs/index.js +3 -2
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/mistral/index.js +5 -3
- 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 +13 -16
- 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/replicate.js +3 -3
- package/lib/cjs/replicate.js.map +1 -1
- package/lib/cjs/test/utils.js +1 -1
- package/lib/cjs/test/utils.js.map +1 -1
- package/lib/cjs/test-driver/TestErrorCompletionStream.js +20 -0
- package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +1 -0
- package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +24 -0
- package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
- package/lib/cjs/test-driver/index.js +109 -0
- package/lib/cjs/test-driver/index.js.map +1 -0
- package/lib/cjs/test-driver/utils.js +30 -0
- package/lib/cjs/test-driver/utils.js.map +1 -0
- package/lib/cjs/togetherai/index.js +2 -2
- package/lib/cjs/togetherai/index.js.map +1 -1
- 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 +90 -28
- package/lib/cjs/vertexai/index.js.map +1 -1
- package/lib/cjs/vertexai/models/claude.js +14 -12
- package/lib/cjs/vertexai/models/claude.js.map +1 -1
- package/lib/cjs/vertexai/models/gemini.js +158 -52
- package/lib/cjs/vertexai/models/gemini.js.map +1 -1
- package/lib/cjs/vertexai/models/imagen.js +11 -22
- package/lib/cjs/vertexai/models/imagen.js.map +1 -1
- package/lib/cjs/vertexai/models/llama.js +4 -3
- package/lib/cjs/vertexai/models/llama.js.map +1 -1
- package/lib/cjs/watsonx/index.js +3 -3
- package/lib/cjs/watsonx/index.js.map +1 -1
- package/lib/cjs/xai/index.js +4 -4
- package/lib/cjs/xai/index.js.map +1 -1
- package/lib/esm/adobe/firefly.js +6 -5
- package/lib/esm/adobe/firefly.js.map +1 -1
- package/lib/esm/azure/azure_foundry.js +382 -0
- package/lib/esm/azure/azure_foundry.js.map +1 -0
- package/lib/esm/bedrock/index.js +62 -39
- package/lib/esm/bedrock/index.js.map +1 -1
- package/lib/esm/groq/index.js +178 -22
- package/lib/esm/groq/index.js.map +1 -1
- package/lib/esm/huggingface_ie.js +6 -5
- package/lib/esm/huggingface_ie.js.map +1 -1
- package/lib/esm/index.js +3 -2
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/mistral/index.js +5 -3
- 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 +12 -15
- 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/replicate.js +3 -3
- package/lib/esm/replicate.js.map +1 -1
- package/lib/esm/src/adobe/firefly.js +116 -0
- package/lib/esm/src/adobe/firefly.js.map +1 -0
- package/lib/esm/src/azure/azure_foundry.js +382 -0
- package/lib/esm/src/azure/azure_foundry.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 +819 -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 +286 -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 +14 -0
- package/lib/esm/src/index.js.map +1 -0
- package/lib/esm/src/mistral/index.js +169 -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/lib/esm/src/openai/azure_openai.js +68 -0
- package/lib/esm/src/openai/azure_openai.js.map +1 -0
- package/lib/esm/src/openai/index.js +460 -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/openai/openai_format.js +134 -0
- package/lib/esm/src/openai/openai_format.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 +332 -0
- package/lib/esm/src/vertexai/index.js.map +1 -0
- package/lib/esm/src/vertexai/models/claude.js +372 -0
- package/lib/esm/src/vertexai/models/claude.js.map +1 -0
- package/lib/esm/src/vertexai/models/gemini.js +806 -0
- package/lib/esm/src/vertexai/models/gemini.js.map +1 -0
- package/lib/esm/src/vertexai/models/imagen.js +302 -0
- package/lib/esm/src/vertexai/models/imagen.js.map +1 -0
- package/lib/esm/src/vertexai/models/llama.js +179 -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/test/utils.js +1 -1
- package/lib/esm/test/utils.js.map +1 -1
- package/lib/esm/test-driver/TestErrorCompletionStream.js +16 -0
- package/lib/esm/test-driver/TestErrorCompletionStream.js.map +1 -0
- package/lib/esm/test-driver/TestValidationErrorCompletionStream.js +20 -0
- package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
- package/lib/esm/test-driver/index.js +91 -0
- package/lib/esm/test-driver/index.js.map +1 -0
- package/lib/esm/test-driver/utils.js +25 -0
- package/lib/esm/test-driver/utils.js.map +1 -0
- package/lib/esm/togetherai/index.js +2 -2
- package/lib/esm/togetherai/index.js.map +1 -1
- package/lib/esm/tsconfig.tsbuildinfo +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 +91 -29
- package/lib/esm/vertexai/index.js.map +1 -1
- package/lib/esm/vertexai/models/claude.js +14 -12
- package/lib/esm/vertexai/models/claude.js.map +1 -1
- package/lib/esm/vertexai/models/gemini.js +159 -53
- package/lib/esm/vertexai/models/gemini.js.map +1 -1
- package/lib/esm/vertexai/models/imagen.js +8 -16
- package/lib/esm/vertexai/models/imagen.js.map +1 -1
- package/lib/esm/vertexai/models/llama.js +4 -3
- package/lib/esm/vertexai/models/llama.js.map +1 -1
- package/lib/esm/vertexai/models.js.map +1 -1
- package/lib/esm/watsonx/index.js +3 -3
- package/lib/esm/watsonx/index.js.map +1 -1
- package/lib/esm/xai/index.js +3 -3
- package/lib/esm/xai/index.js.map +1 -1
- package/lib/types/adobe/firefly.d.ts +3 -3
- package/lib/types/adobe/firefly.d.ts.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/index.d.ts +4 -4
- package/lib/types/bedrock/index.d.ts.map +1 -1
- package/lib/types/groq/index.d.ts +8 -5
- package/lib/types/groq/index.d.ts.map +1 -1
- package/lib/types/huggingface_ie.d.ts +8 -5
- package/lib/types/huggingface_ie.d.ts.map +1 -1
- package/lib/types/index.d.ts +3 -2
- 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/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/replicate.d.ts +6 -3
- package/lib/types/replicate.d.ts.map +1 -1
- package/lib/types/src/adobe/firefly.d.ts +29 -0
- package/lib/types/src/azure/azure_foundry.d.ts +49 -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 +26 -0
- package/lib/types/src/huggingface_ie.d.ts +34 -0
- package/lib/types/src/index.d.ts +13 -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_openai.d.ts +24 -0
- package/lib/types/src/openai/index.d.ts +24 -0
- package/lib/types/src/openai/openai.d.ts +14 -0
- package/lib/types/src/openai/openai_format.d.ts +18 -0
- package/lib/types/src/replicate.d.ts +47 -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 +52 -0
- package/lib/types/src/vertexai/models/claude.d.ts +17 -0
- package/lib/types/src/vertexai/models/gemini.d.ts +17 -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/test-driver/TestErrorCompletionStream.d.ts +9 -0
- package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +1 -0
- package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts +9 -0
- package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +1 -0
- package/lib/types/test-driver/index.d.ts +24 -0
- package/lib/types/test-driver/index.d.ts.map +1 -0
- package/lib/types/test-driver/utils.d.ts +5 -0
- package/lib/types/test-driver/utils.d.ts.map +1 -0
- package/lib/types/togetherai/index.d.ts +3 -3
- package/lib/types/togetherai/index.d.ts.map +1 -1
- package/lib/types/vertexai/index.d.ts +10 -7
- package/lib/types/vertexai/index.d.ts.map +1 -1
- package/lib/types/vertexai/models/claude.d.ts.map +1 -1
- package/lib/types/vertexai/models/gemini.d.ts +3 -2
- package/lib/types/vertexai/models/gemini.d.ts.map +1 -1
- package/lib/types/vertexai/models/imagen.d.ts +2 -2
- package/lib/types/vertexai/models/imagen.d.ts.map +1 -1
- package/lib/types/vertexai/models/llama.d.ts +2 -2
- package/lib/types/vertexai/models/llama.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/watsonx/index.d.ts +3 -3
- package/lib/types/watsonx/index.d.ts.map +1 -1
- package/lib/types/xai/index.d.ts.map +1 -1
- package/package.json +29 -25
- package/src/adobe/firefly.ts +12 -20
- package/src/azure/azure_foundry.ts +458 -0
- package/src/bedrock/index.ts +65 -43
- package/src/groq/index.ts +219 -32
- package/src/huggingface_ie.ts +13 -14
- package/src/index.ts +3 -2
- package/src/mistral/index.ts +11 -9
- package/src/openai/azure_openai.ts +92 -0
- package/src/openai/index.ts +27 -28
- package/src/openai/openai.ts +2 -5
- package/src/openai/openai_format.ts +165 -0
- package/src/replicate.ts +12 -12
- package/src/{test → test-driver}/utils.ts +1 -1
- package/src/togetherai/index.ts +7 -7
- package/src/vertexai/embeddings/embeddings-text.ts +2 -2
- package/src/vertexai/index.ts +104 -38
- package/src/vertexai/models/claude.ts +18 -16
- package/src/vertexai/models/gemini.ts +195 -67
- package/src/vertexai/models/imagen.ts +15 -26
- package/src/vertexai/models/llama.ts +6 -5
- package/src/vertexai/models.ts +4 -4
- package/src/watsonx/index.ts +10 -10
- package/src/xai/index.ts +13 -15
- package/lib/cjs/openai/azure.js +0 -31
- package/lib/cjs/openai/azure.js.map +0 -1
- package/lib/esm/openai/azure.js +0 -27
- package/lib/esm/openai/azure.js.map +0 -1
- package/lib/types/openai/azure.d.ts +0 -20
- package/lib/types/openai/azure.d.ts.map +0 -1
- package/src/openai/azure.ts +0 -54
- /package/src/{test → test-driver}/TestErrorCompletionStream.ts +0 -0
- /package/src/{test → test-driver}/TestValidationErrorCompletionStream.ts +0 -0
- /package/src/{test → test-driver}/index.ts +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Content, FinishReason, FunctionCallingConfigMode, FunctionDeclaration, GenerateContentParameters,
|
|
2
|
+
Content, FinishReason, FunctionCallingConfigMode, FunctionDeclaration, GenerateContentConfig, GenerateContentParameters,
|
|
3
|
+
GenerateContentResponseUsageMetadata,
|
|
3
4
|
HarmBlockThreshold, HarmCategory, Part, SafetySetting, Schema, Tool, Type
|
|
4
5
|
} from "@google/genai";
|
|
5
6
|
import {
|
|
6
|
-
AIModel, Completion, CompletionChunkObject, ExecutionOptions,
|
|
7
|
-
ExecutionTokenUsage, JSONObject, JSONSchema, ModelType, PromptOptions, PromptRole,
|
|
8
|
-
PromptSegment, readStreamAsBase64, ToolDefinition, ToolUse
|
|
7
|
+
AIModel, Completion, CompletionChunkObject, CompletionResult, ExecutionOptions,
|
|
8
|
+
ExecutionTokenUsage, getMaxTokensLimitVertexAi, JSONObject, JSONSchema, ModelType, PromptOptions, PromptRole,
|
|
9
|
+
PromptSegment, readStreamAsBase64, StatelessExecutionOptions, ToolDefinition, ToolUse,
|
|
10
|
+
VertexAIGeminiOptions
|
|
9
11
|
} from "@llumiverse/core";
|
|
10
12
|
import { asyncMap } from "@llumiverse/core/async";
|
|
11
13
|
import { VertexAIDriver, GenerateContentPrompt } from "../index.js";
|
|
@@ -44,42 +46,52 @@ const geminiSafetySettings: SafetySetting[] = [
|
|
|
44
46
|
];
|
|
45
47
|
|
|
46
48
|
function getGeminiPayload(options: ExecutionOptions, prompt: GenerateContentPrompt): GenerateContentParameters {
|
|
47
|
-
const model_options = options.model_options as
|
|
49
|
+
const model_options = options.model_options as VertexAIGeminiOptions | undefined;
|
|
48
50
|
const tools = getToolDefinitions(options.tools);
|
|
49
51
|
|
|
50
52
|
const useStructuredOutput = supportsStructuredOutput(options) && !tools;
|
|
51
53
|
|
|
54
|
+
const thinkingConfigNeeded = model_options?.include_thoughts
|
|
55
|
+
|| model_options?.thinking_budget_tokens
|
|
56
|
+
|| options.model.includes("gemini-2.5");
|
|
57
|
+
|
|
58
|
+
const configNanoBanana: GenerateContentConfig = {
|
|
59
|
+
responseModalities: ["TEXT", "IMAGE"]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const config: GenerateContentConfig = {
|
|
63
|
+
systemInstruction: prompt.system,
|
|
64
|
+
safetySettings: geminiSafetySettings,
|
|
65
|
+
tools: tools ? [tools] : undefined,
|
|
66
|
+
toolConfig: tools ? {
|
|
67
|
+
functionCallingConfig: {
|
|
68
|
+
mode: FunctionCallingConfigMode.AUTO,
|
|
69
|
+
}
|
|
70
|
+
} : undefined,
|
|
71
|
+
candidateCount: 1,
|
|
72
|
+
//JSON/Structured output
|
|
73
|
+
responseMimeType: useStructuredOutput ? "application/json" : undefined,
|
|
74
|
+
responseSchema: useStructuredOutput ? parseJSONtoSchema(options.result_schema, true) : undefined,
|
|
75
|
+
//Model options
|
|
76
|
+
temperature: model_options?.temperature,
|
|
77
|
+
topP: model_options?.top_p,
|
|
78
|
+
topK: model_options?.top_k,
|
|
79
|
+
maxOutputTokens: geminiMaxTokens(options),
|
|
80
|
+
stopSequences: model_options?.stop_sequence,
|
|
81
|
+
presencePenalty: model_options?.presence_penalty,
|
|
82
|
+
frequencyPenalty: model_options?.frequency_penalty,
|
|
83
|
+
seed: model_options?.seed,
|
|
84
|
+
thinkingConfig: thinkingConfigNeeded ?
|
|
85
|
+
{
|
|
86
|
+
includeThoughts: model_options?.include_thoughts ?? false,
|
|
87
|
+
thinkingBudget: geminiThinkingBudget(options),
|
|
88
|
+
} : undefined,
|
|
89
|
+
}
|
|
90
|
+
|
|
52
91
|
return {
|
|
53
92
|
model: options.model,
|
|
54
93
|
contents: prompt.contents,
|
|
55
|
-
config:
|
|
56
|
-
systemInstruction: prompt.system,
|
|
57
|
-
safetySettings: geminiSafetySettings,
|
|
58
|
-
tools: tools ? [tools] : undefined,
|
|
59
|
-
toolConfig: tools ? {
|
|
60
|
-
functionCallingConfig: {
|
|
61
|
-
mode: FunctionCallingConfigMode.AUTO,
|
|
62
|
-
}
|
|
63
|
-
} : undefined,
|
|
64
|
-
candidateCount: 1,
|
|
65
|
-
//JSON/Structured output
|
|
66
|
-
responseMimeType: useStructuredOutput ? "application/json" : undefined,
|
|
67
|
-
responseSchema: useStructuredOutput ? parseJSONtoSchema(options.result_schema, true) : undefined,
|
|
68
|
-
//Model options
|
|
69
|
-
temperature: model_options?.temperature,
|
|
70
|
-
topP: model_options?.top_p,
|
|
71
|
-
topK: model_options?.top_k,
|
|
72
|
-
maxOutputTokens: model_options?.max_tokens,
|
|
73
|
-
stopSequences: model_options?.stop_sequence,
|
|
74
|
-
presencePenalty: model_options?.presence_penalty,
|
|
75
|
-
frequencyPenalty: model_options?.frequency_penalty,
|
|
76
|
-
seed: model_options?.seed,
|
|
77
|
-
thinkingConfig: model_options?.include_thoughts || model_options?.thinking_budget_tokens ?
|
|
78
|
-
{
|
|
79
|
-
includeThoughts: model_options?.include_thoughts,
|
|
80
|
-
thinkingBudget: model_options?.thinking_budget_tokens,
|
|
81
|
-
} : undefined,
|
|
82
|
-
}
|
|
94
|
+
config: options.model.toLowerCase().includes("image") ? configNanoBanana : config,
|
|
83
95
|
};
|
|
84
96
|
}
|
|
85
97
|
|
|
@@ -335,7 +347,7 @@ function cleanEmptyFieldsContent(content: Content, result_schema?: JSONSchema):
|
|
|
335
347
|
const jsonText = JSON.parse(part.text);
|
|
336
348
|
// Skip cleaning if not an object
|
|
337
349
|
if (typeof jsonText === 'object' && jsonText !== null && !Array.isArray(jsonText)) {
|
|
338
|
-
const cleanedJson = removeEmptyFields(jsonText, result_schema);
|
|
350
|
+
const cleanedJson = removeEmptyFields(jsonText, result_schema);
|
|
339
351
|
newPart.text = JSON.stringify(cleanedJson);
|
|
340
352
|
} else {
|
|
341
353
|
// Keep original if not an object (string, number, array, etc.)
|
|
@@ -370,14 +382,14 @@ function removeEmptyFields(object: JSONObject | any[], schema: JSONSchema): JSON
|
|
|
370
382
|
if (typeof object == 'object' || object === null) {
|
|
371
383
|
return removeEmptyJSONObject(object, schema);
|
|
372
384
|
}
|
|
373
|
-
|
|
385
|
+
|
|
374
386
|
return object;
|
|
375
387
|
}
|
|
376
388
|
|
|
377
389
|
function removeEmptyJSONObject(object: JSONObject, schema: JSONSchema): JSONObject {
|
|
378
390
|
// Get the original required properties from schema
|
|
379
391
|
const requiredProps = schema.required || [];
|
|
380
|
-
const cleanedResult: JSONObject = {...object};
|
|
392
|
+
const cleanedResult: JSONObject = { ...object };
|
|
381
393
|
|
|
382
394
|
// Process each property
|
|
383
395
|
for (const [key, value] of Object.entries(object)) {
|
|
@@ -401,24 +413,46 @@ function removeEmptyJSONObject(object: JSONObject, schema: JSONSchema): JSONObje
|
|
|
401
413
|
|
|
402
414
|
function removeEmptyJSONArray(array: any[], schema: JSONSchema): any[] {
|
|
403
415
|
const cleanedArray = array.map(item => {
|
|
404
|
-
return removeEmptyFields(item, schema);
|
|
416
|
+
return removeEmptyFields(item, schema);
|
|
405
417
|
});
|
|
406
418
|
|
|
407
419
|
// Filter out empty objects from the array
|
|
408
420
|
return cleanedArray.filter(item => !isEmpty(item));
|
|
409
421
|
}
|
|
410
422
|
|
|
411
|
-
function collectTextParts(content: Content) {
|
|
412
|
-
const
|
|
423
|
+
function collectTextParts(content: Content): CompletionResult[] {
|
|
424
|
+
const results: CompletionResult[] = [];
|
|
413
425
|
const parts = content.parts;
|
|
414
426
|
if (parts) {
|
|
415
427
|
for (const part of parts) {
|
|
416
428
|
if (part.text) {
|
|
417
|
-
|
|
429
|
+
results.push({
|
|
430
|
+
type: "text",
|
|
431
|
+
value: part.text
|
|
432
|
+
});
|
|
418
433
|
}
|
|
419
434
|
}
|
|
420
435
|
}
|
|
421
|
-
return
|
|
436
|
+
return results;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function collectInlineDataParts(content: Content): CompletionResult[] {
|
|
440
|
+
const results: CompletionResult[] = [];
|
|
441
|
+
const parts = content.parts;
|
|
442
|
+
if (parts) {
|
|
443
|
+
for (const part of parts) {
|
|
444
|
+
if (part.inlineData) {
|
|
445
|
+
const base64ImageBytes: string = part.inlineData.data ?? "";
|
|
446
|
+
const mimeType = part.inlineData.mimeType ?? "image/png";
|
|
447
|
+
const imageUrl = `data:${mimeType};base64,${base64ImageBytes}`;
|
|
448
|
+
results.push({
|
|
449
|
+
type: "image",
|
|
450
|
+
value: imageUrl
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return results;
|
|
422
456
|
}
|
|
423
457
|
|
|
424
458
|
function collectToolUseParts(content: Content): ToolUse[] | undefined {
|
|
@@ -439,7 +473,7 @@ function collectToolUseParts(content: Content): ToolUse[] | undefined {
|
|
|
439
473
|
export function mergeConsecutiveRole(contents: Content[] | undefined): Content[] {
|
|
440
474
|
if (!contents || contents.length === 0) return [];
|
|
441
475
|
|
|
442
|
-
const needsMerging = contents.some((content, i) =>
|
|
476
|
+
const needsMerging = contents.some((content, i) =>
|
|
443
477
|
i < contents.length - 1 && content.role === contents[i + 1].role
|
|
444
478
|
);
|
|
445
479
|
// If no merging needed, return original array
|
|
@@ -465,6 +499,41 @@ export function mergeConsecutiveRole(contents: Content[] | undefined): Content[]
|
|
|
465
499
|
return result;
|
|
466
500
|
}
|
|
467
501
|
|
|
502
|
+
const supportedFinishReasons: FinishReason[] = [
|
|
503
|
+
FinishReason.MAX_TOKENS,
|
|
504
|
+
FinishReason.STOP,
|
|
505
|
+
FinishReason.FINISH_REASON_UNSPECIFIED
|
|
506
|
+
]
|
|
507
|
+
|
|
508
|
+
function geminiMaxTokens(option: StatelessExecutionOptions) {
|
|
509
|
+
const model_options = option.model_options as VertexAIGeminiOptions | undefined;
|
|
510
|
+
if (model_options?.max_tokens) {
|
|
511
|
+
return model_options.max_tokens;
|
|
512
|
+
}
|
|
513
|
+
if (option.model.includes("gemini-2.5")) {
|
|
514
|
+
const maxSupportedTokens = getMaxTokensLimitVertexAi(option.model);
|
|
515
|
+
const thinkingBudget = geminiThinkingBudget(option) ?? 0;
|
|
516
|
+
return Math.min(maxSupportedTokens, 16000 + thinkingBudget);
|
|
517
|
+
}
|
|
518
|
+
return undefined;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function geminiThinkingBudget(option: StatelessExecutionOptions) {
|
|
522
|
+
const model_options = option.model_options as VertexAIGeminiOptions | undefined;
|
|
523
|
+
if (model_options?.thinking_budget_tokens) {
|
|
524
|
+
return model_options.thinking_budget_tokens;
|
|
525
|
+
}
|
|
526
|
+
// Set minimum thinking level by default.
|
|
527
|
+
// Docs: https://ai.google.dev/gemini-api/docs/thinking#set-budget
|
|
528
|
+
if (option.model.includes("gemini-2.5")) {
|
|
529
|
+
if (option.model.includes("pro")) {
|
|
530
|
+
return 128;
|
|
531
|
+
}
|
|
532
|
+
return 0;
|
|
533
|
+
}
|
|
534
|
+
return undefined;
|
|
535
|
+
}
|
|
536
|
+
|
|
468
537
|
export class GeminiModelDefinition implements ModelDefinition<GenerateContentPrompt> {
|
|
469
538
|
|
|
470
539
|
model: AIModel
|
|
@@ -485,8 +554,16 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
485
554
|
return { result, options };
|
|
486
555
|
}
|
|
487
556
|
try {
|
|
488
|
-
|
|
489
|
-
result.result
|
|
557
|
+
// Extract text content for JSON processing - only process first text result
|
|
558
|
+
const textResult = result.result.find(r => r.type === 'text')?.value;
|
|
559
|
+
if (textResult) {
|
|
560
|
+
const jsonResult = JSON.parse(textResult);
|
|
561
|
+
const cleanedJson = JSON.stringify(removeEmptyFields(jsonResult, options.result_schema));
|
|
562
|
+
// Replace the text result with cleaned version
|
|
563
|
+
result.result = result.result.map(r =>
|
|
564
|
+
r.type === 'text' ? { ...r, value: cleanedJson } : r
|
|
565
|
+
);
|
|
566
|
+
}
|
|
490
567
|
return { result, options };
|
|
491
568
|
} catch (error) {
|
|
492
569
|
// Log error during processing but don't fail the completion
|
|
@@ -504,7 +581,7 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
504
581
|
const schema = options.result_schema;
|
|
505
582
|
let contents: Content[] = [];
|
|
506
583
|
let system: Content | undefined = { role: "user", parts: [] }; // Single content block for system messages
|
|
507
|
-
|
|
584
|
+
|
|
508
585
|
const safety: Content[] = [];
|
|
509
586
|
|
|
510
587
|
for (const msg of segments) {
|
|
@@ -517,7 +594,7 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
517
594
|
|
|
518
595
|
if (msg.content) {
|
|
519
596
|
system.parts?.push({
|
|
520
|
-
|
|
597
|
+
text: msg.content
|
|
521
598
|
});
|
|
522
599
|
}
|
|
523
600
|
} else if (msg.role === PromptRole.tool) {
|
|
@@ -591,7 +668,7 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
591
668
|
}
|
|
592
669
|
}
|
|
593
670
|
}
|
|
594
|
-
|
|
671
|
+
|
|
595
672
|
// If no system messages, set system to undefined.
|
|
596
673
|
if (!system.parts || system.parts.length === 0) {
|
|
597
674
|
system = undefined;
|
|
@@ -604,29 +681,58 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
604
681
|
|
|
605
682
|
// Merge consecutive messages with the same role. Note: this may not be necessary, works without it, keeping to match previous behavior.
|
|
606
683
|
contents = mergeConsecutiveRole(contents);
|
|
607
|
-
|
|
684
|
+
|
|
608
685
|
return { contents, system };
|
|
609
686
|
}
|
|
610
687
|
|
|
688
|
+
usageMetadataToTokenUsage(usageMetadata: GenerateContentResponseUsageMetadata | undefined): ExecutionTokenUsage {
|
|
689
|
+
if (!usageMetadata || !usageMetadata.totalTokenCount) {
|
|
690
|
+
return {};
|
|
691
|
+
}
|
|
692
|
+
const tokenUsage: ExecutionTokenUsage = { total: usageMetadata.totalTokenCount, prompt: usageMetadata.promptTokenCount };
|
|
693
|
+
|
|
694
|
+
//Output/Response side
|
|
695
|
+
tokenUsage.result = (usageMetadata.candidatesTokenCount ?? 0)
|
|
696
|
+
+ (usageMetadata.thoughtsTokenCount ?? 0)
|
|
697
|
+
+ (usageMetadata.toolUsePromptTokenCount ?? 0);
|
|
698
|
+
|
|
699
|
+
if ((tokenUsage.total ?? 0) != (tokenUsage.prompt ?? 0) + tokenUsage.result) {
|
|
700
|
+
console.warn("[VertexAI] Gemini token usage mismatch: total does not equal prompt + result", {
|
|
701
|
+
total: tokenUsage.total,
|
|
702
|
+
prompt: tokenUsage.prompt,
|
|
703
|
+
result: tokenUsage.result
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (!tokenUsage.result) {
|
|
708
|
+
tokenUsage.result = undefined; // If no result, mark as undefined
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return tokenUsage;
|
|
712
|
+
}
|
|
713
|
+
|
|
611
714
|
async requestTextCompletion(driver: VertexAIDriver, prompt: GenerateContentPrompt, options: ExecutionOptions): Promise<Completion> {
|
|
612
715
|
const splits = options.model.split("/");
|
|
716
|
+
let region: string | undefined = undefined;
|
|
717
|
+
if (splits[0] === "locations" && splits.length >= 2) {
|
|
718
|
+
region = splits[1];
|
|
719
|
+
}
|
|
613
720
|
const modelName = splits[splits.length - 1];
|
|
614
721
|
options = { ...options, model: modelName };
|
|
615
722
|
|
|
616
723
|
let conversation = updateConversation(options.conversation as Content[], prompt.contents);
|
|
617
724
|
prompt.contents = conversation;
|
|
618
725
|
|
|
619
|
-
|
|
726
|
+
if (options.model.includes("gemini-2.5-flash-image")) {
|
|
727
|
+
region = "global"; // Gemini Flash Image only available in global region, this is for nano-banana model
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
const client = driver.getGoogleGenAIClient(region);
|
|
620
731
|
|
|
621
732
|
const payload = getGeminiPayload(options, prompt);
|
|
622
733
|
const response = await client.models.generateContent(payload);
|
|
623
734
|
|
|
624
|
-
const
|
|
625
|
-
const token_usage: ExecutionTokenUsage = {
|
|
626
|
-
prompt: usage?.promptTokenCount,
|
|
627
|
-
result: usage?.candidatesTokenCount,
|
|
628
|
-
total: usage?.totalTokenCount,
|
|
629
|
-
}
|
|
735
|
+
const token_usage: ExecutionTokenUsage = this.usageMetadataToTokenUsage(response.usageMetadata);
|
|
630
736
|
|
|
631
737
|
let tool_use: ToolUse[] | undefined;
|
|
632
738
|
let finish_reason: string | undefined, result: any;
|
|
@@ -638,22 +744,33 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
638
744
|
default: finish_reason = candidate.finishReason;
|
|
639
745
|
}
|
|
640
746
|
const content = candidate.content;
|
|
747
|
+
|
|
748
|
+
if (candidate.finishReason && !supportedFinishReasons.includes(candidate.finishReason)) {
|
|
749
|
+
throw new Error(`Unsupported finish reason: ${candidate.finishReason}, `
|
|
750
|
+
+ `finish message: ${candidate.finishMessage}, `
|
|
751
|
+
+ `content: ${JSON.stringify(content, null, 2)}, safety: ${JSON.stringify(candidate.safetyRatings, null, 2)}`);
|
|
752
|
+
}
|
|
753
|
+
|
|
641
754
|
if (content) {
|
|
642
755
|
tool_use = collectToolUseParts(content);
|
|
643
756
|
|
|
644
757
|
// We clean the content before validation, so we can update the conversation.
|
|
645
758
|
const cleanedContent = cleanEmptyFieldsContent(content, options.result_schema);
|
|
646
|
-
|
|
759
|
+
const textResults = collectTextParts(cleanedContent);
|
|
760
|
+
const imageResults = collectInlineDataParts(cleanedContent);
|
|
761
|
+
result = [...textResults, ...imageResults];
|
|
647
762
|
conversation = updateConversation(conversation, [cleanedContent]);
|
|
648
763
|
}
|
|
649
764
|
}
|
|
650
765
|
|
|
766
|
+
|
|
767
|
+
|
|
651
768
|
if (tool_use) {
|
|
652
769
|
finish_reason = "tool_use";
|
|
653
770
|
}
|
|
654
771
|
|
|
655
772
|
return {
|
|
656
|
-
result: result
|
|
773
|
+
result: result && result.length > 0 ? result : [{ type: "text" as const, value: '' }],
|
|
657
774
|
token_usage: token_usage,
|
|
658
775
|
finish_reason: finish_reason,
|
|
659
776
|
original_response: options.include_original_response ? response : undefined,
|
|
@@ -664,21 +781,24 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
664
781
|
|
|
665
782
|
async requestTextCompletionStream(driver: VertexAIDriver, prompt: GenerateContentPrompt, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>> {
|
|
666
783
|
const splits = options.model.split("/");
|
|
784
|
+
let region: string | undefined = undefined;
|
|
785
|
+
if (splits[0] === "locations" && splits.length >= 2) {
|
|
786
|
+
region = splits[1];
|
|
787
|
+
}
|
|
667
788
|
const modelName = splits[splits.length - 1];
|
|
668
789
|
options = { ...options, model: modelName };
|
|
669
790
|
|
|
670
|
-
|
|
791
|
+
if (options.model.includes("gemini-2.5-flash-image")) {
|
|
792
|
+
region = "global"; // Gemini Flash Image only available in global region, this is for nano-banana model
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const client = driver.getGoogleGenAIClient(region);
|
|
671
796
|
|
|
672
797
|
const payload = getGeminiPayload(options, prompt);
|
|
673
798
|
const response = await client.models.generateContentStream(payload);
|
|
674
799
|
|
|
675
800
|
const stream = asyncMap(response, async (item) => {
|
|
676
|
-
const
|
|
677
|
-
const token_usage: ExecutionTokenUsage = {
|
|
678
|
-
prompt: usage?.promptTokenCount,
|
|
679
|
-
result: usage?.candidatesTokenCount,
|
|
680
|
-
total: usage?.totalTokenCount,
|
|
681
|
-
}
|
|
801
|
+
const token_usage: ExecutionTokenUsage = this.usageMetadataToTokenUsage(item.usageMetadata);
|
|
682
802
|
if (item.candidates && item.candidates.length > 0) {
|
|
683
803
|
for (const candidate of item.candidates) {
|
|
684
804
|
let tool_use: ToolUse[] | undefined;
|
|
@@ -688,14 +808,21 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
688
808
|
case FinishReason.STOP: finish_reason = "stop"; break;
|
|
689
809
|
default: finish_reason = candidate.finishReason;
|
|
690
810
|
}
|
|
811
|
+
if (candidate.finishReason && !supportedFinishReasons.includes(candidate.finishReason)) {
|
|
812
|
+
throw new Error(`Unsupported finish reason: ${candidate.finishReason}, `
|
|
813
|
+
+ `finish message: ${candidate.finishMessage}, `
|
|
814
|
+
+ `content: ${JSON.stringify(candidate.content, null, 2)}, safety: ${JSON.stringify(candidate.safetyRatings, null, 2)}`);
|
|
815
|
+
}
|
|
691
816
|
if (candidate.content?.role === 'model') {
|
|
692
|
-
const
|
|
817
|
+
const textResults = collectTextParts(candidate.content);
|
|
818
|
+
const imageResults = collectInlineDataParts(candidate.content);
|
|
819
|
+
const combinedResults = [...textResults, ...imageResults];
|
|
693
820
|
tool_use = collectToolUseParts(candidate.content);
|
|
694
821
|
if (tool_use) {
|
|
695
822
|
finish_reason = "tool_use";
|
|
696
823
|
}
|
|
697
824
|
return {
|
|
698
|
-
result:
|
|
825
|
+
result: combinedResults.length > 0 ? combinedResults : [],
|
|
699
826
|
token_usage: token_usage,
|
|
700
827
|
finish_reason: finish_reason,
|
|
701
828
|
tool_use,
|
|
@@ -705,8 +832,9 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
|
|
|
705
832
|
}
|
|
706
833
|
//No normal output, returning block reason if it exists.
|
|
707
834
|
return {
|
|
708
|
-
result: item.promptFeedback?.blockReasonMessage
|
|
835
|
+
result: item.promptFeedback?.blockReasonMessage ? [{ type: "text" as const, value: item.promptFeedback.blockReasonMessage }] : [],
|
|
709
836
|
finish_reason: item.promptFeedback?.blockReason ?? "",
|
|
837
|
+
token_usage: token_usage,
|
|
710
838
|
};
|
|
711
839
|
});
|
|
712
840
|
|
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AIModel, Completion, ExecutionOptions,
|
|
2
|
+
AIModel, Completion, ExecutionOptions, Modalities,
|
|
3
3
|
ModelType, PromptRole, PromptSegment, readStreamAsBase64, ImagenOptions
|
|
4
4
|
} from "@llumiverse/core";
|
|
5
5
|
import { VertexAIDriver } from "../index.js";
|
|
6
6
|
|
|
7
|
-
const projectId = process.env.GOOGLE_PROJECT_ID;
|
|
8
|
-
const location = 'us-central1';
|
|
9
|
-
|
|
10
|
-
import aiplatform, { protos } from '@google-cloud/aiplatform';
|
|
11
|
-
|
|
12
|
-
// Imports the Google Cloud Prediction Service Client library
|
|
13
|
-
const { PredictionServiceClient } = aiplatform.v1;
|
|
14
|
-
|
|
15
7
|
// Import the helper module for converting arbitrary protobuf.Value objects
|
|
16
|
-
import { helpers } from '@google-cloud/aiplatform';
|
|
8
|
+
import { protos, helpers } from '@google-cloud/aiplatform';
|
|
9
|
+
|
|
17
10
|
interface ImagenBaseReference {
|
|
18
11
|
referenceType: "REFERENCE_TYPE_RAW" | "REFERENCE_TYPE_MASK" | "REFERENCE_TYPE_SUBJECT" |
|
|
19
12
|
"REFERENCE_TYPE_CONTROL" | "REFERENCE_TYPE_STYLE";
|
|
@@ -90,14 +83,6 @@ export interface ImagenPrompt {
|
|
|
90
83
|
negativePrompt?: string; //Used for negative prompts
|
|
91
84
|
}
|
|
92
85
|
|
|
93
|
-
// Specifies the location of the api endpoint
|
|
94
|
-
const clientOptions = {
|
|
95
|
-
apiEndpoint: `${location}-aiplatform.googleapis.com`,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// Instantiates a client
|
|
99
|
-
const predictionServiceClient = new PredictionServiceClient(clientOptions);
|
|
100
|
-
|
|
101
86
|
function getImagenParameters(taskType: string, options: ImagenOptions) {
|
|
102
87
|
const commonParameters = {
|
|
103
88
|
sampleCount: options?.number_of_images,
|
|
@@ -337,9 +322,9 @@ export class ImagenModelDefinition {
|
|
|
337
322
|
return prompt
|
|
338
323
|
}
|
|
339
324
|
|
|
340
|
-
async requestImageGeneration(driver: VertexAIDriver, prompt: ImagenPrompt, options: ExecutionOptions): Promise<Completion
|
|
325
|
+
async requestImageGeneration(driver: VertexAIDriver, prompt: ImagenPrompt, options: ExecutionOptions): Promise<Completion> {
|
|
341
326
|
if (options.model_options?._option_id !== "vertexai-imagen") {
|
|
342
|
-
driver.logger.warn("Invalid model options", {options: options.model_options });
|
|
327
|
+
driver.logger.warn("Invalid model options", { options: options.model_options });
|
|
343
328
|
}
|
|
344
329
|
options.model_options = options.model_options as ImagenOptions | undefined;
|
|
345
330
|
|
|
@@ -351,10 +336,11 @@ export class ImagenModelDefinition {
|
|
|
351
336
|
|
|
352
337
|
driver.logger.info("Task type: " + taskType);
|
|
353
338
|
|
|
354
|
-
|
|
339
|
+
const modelName = options.model.split("/").pop() ?? '';
|
|
355
340
|
|
|
356
341
|
// Configure the parent resource
|
|
357
|
-
|
|
342
|
+
// TODO: make location configurable, fixed to us-central1 for now
|
|
343
|
+
const endpoint = `projects/${driver.options.project}/locations/us-central1/publishers/google/models/${modelName}`;
|
|
358
344
|
|
|
359
345
|
const instanceValue = helpers.toValue(prompt);
|
|
360
346
|
if (!instanceValue) {
|
|
@@ -380,8 +366,10 @@ export class ImagenModelDefinition {
|
|
|
380
366
|
parameters,
|
|
381
367
|
};
|
|
382
368
|
|
|
369
|
+
const client = driver.getImagenClient();
|
|
370
|
+
|
|
383
371
|
// Predict request
|
|
384
|
-
const [response] = await
|
|
372
|
+
const [response] = await client.predict(request, { timeout: 120000 * numberOfImages }); //Extended timeout for image generation
|
|
385
373
|
const predictions = response.predictions;
|
|
386
374
|
|
|
387
375
|
if (!predictions) {
|
|
@@ -394,9 +382,10 @@ export class ImagenModelDefinition {
|
|
|
394
382
|
);
|
|
395
383
|
|
|
396
384
|
return {
|
|
397
|
-
result: {
|
|
398
|
-
|
|
399
|
-
|
|
385
|
+
result: images.map(image => ({
|
|
386
|
+
type: "image" as const,
|
|
387
|
+
value: image
|
|
388
|
+
})),
|
|
400
389
|
};
|
|
401
390
|
}
|
|
402
391
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AIModel, Completion,
|
|
2
|
+
AIModel, Completion, CompletionChunkObject, ExecutionOptions, ModelType,
|
|
3
3
|
PromptOptions, PromptRole, PromptSegment,
|
|
4
4
|
TextFallbackOptions
|
|
5
5
|
} from "@llumiverse/core";
|
|
@@ -195,7 +195,7 @@ export class LLamaModelDefinition implements ModelDefinition<LLamaPrompt> {
|
|
|
195
195
|
});
|
|
196
196
|
|
|
197
197
|
return {
|
|
198
|
-
result: text,
|
|
198
|
+
result: [{ type: "text", value: text }],
|
|
199
199
|
token_usage: {
|
|
200
200
|
prompt: result.usage.prompt_tokens,
|
|
201
201
|
result: result.usage.completion_tokens,
|
|
@@ -206,11 +206,11 @@ export class LLamaModelDefinition implements ModelDefinition<LLamaPrompt> {
|
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
async requestTextCompletionStream(driver: VertexAIDriver, prompt: LLamaPrompt, options: ExecutionOptions): Promise<AsyncIterable<
|
|
209
|
+
async requestTextCompletionStream(driver: VertexAIDriver, prompt: LLamaPrompt, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>> {
|
|
210
210
|
const splits = options.model.split("/");
|
|
211
211
|
const modelName = splits[splits.length - 1];
|
|
212
212
|
|
|
213
|
-
|
|
213
|
+
const conversation = updateConversation(options.conversation as LLamaPrompt, prompt);
|
|
214
214
|
|
|
215
215
|
const modelOptions = options.model_options as TextFallbackOptions;
|
|
216
216
|
|
|
@@ -247,8 +247,9 @@ export class LLamaModelDefinition implements ModelDefinition<LLamaPrompt> {
|
|
|
247
247
|
return transformSSEStream(stream, (data: string): CompletionChunkObject => {
|
|
248
248
|
const json = JSON.parse(data) as LLamaStreamResponse;
|
|
249
249
|
const choice = json.choices?.[0];
|
|
250
|
+
const content = choice?.delta?.content ?? '';
|
|
250
251
|
return {
|
|
251
|
-
result:
|
|
252
|
+
result: content ? [{ type: "text", value: content }] : [],
|
|
252
253
|
finish_reason: choice?.finish_reason,
|
|
253
254
|
token_usage: json.usage ? {
|
|
254
255
|
prompt: json.usage.prompt_tokens,
|
package/src/vertexai/models.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AIModel, Completion, PromptSegment, ExecutionOptions,
|
|
2
|
-
import { VertexAIDriver
|
|
1
|
+
import { AIModel, Completion, PromptSegment, ExecutionOptions, CompletionChunkObject } from "@llumiverse/core";
|
|
2
|
+
import { VertexAIDriver, trimModelName } from "./index.js";
|
|
3
3
|
import { GeminiModelDefinition } from "./models/gemini.js";
|
|
4
4
|
import { ClaudeModelDefinition } from "./models/claude.js";
|
|
5
5
|
import { LLamaModelDefinition } from "./models/llama.js";
|
|
@@ -9,7 +9,7 @@ export interface ModelDefinition<PromptT = any> {
|
|
|
9
9
|
versions?: string[]; // the versions of the model that are available. ex: ['001', '002']
|
|
10
10
|
createPrompt: (driver: VertexAIDriver, segments: PromptSegment[], options: ExecutionOptions) => Promise<PromptT>;
|
|
11
11
|
requestTextCompletion: (driver: VertexAIDriver, prompt: PromptT, options: ExecutionOptions) => Promise<Completion>;
|
|
12
|
-
requestTextCompletionStream: (driver: VertexAIDriver, prompt: PromptT, options: ExecutionOptions) => Promise<AsyncIterable<
|
|
12
|
+
requestTextCompletionStream: (driver: VertexAIDriver, prompt: PromptT, options: ExecutionOptions) => Promise<AsyncIterable<CompletionChunkObject>>;
|
|
13
13
|
preValidationProcessing?(result: Completion, options: ExecutionOptions): { result: Completion, options: ExecutionOptions };
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ export function getModelDefinition(model: string): ModelDefinition {
|
|
|
17
17
|
const splits = model.split("/");
|
|
18
18
|
const publisher = splits[1];
|
|
19
19
|
const modelName = trimModelName(splits[splits.length - 1]);
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
if (publisher?.includes("anthropic")) {
|
|
22
22
|
return new ClaudeModelDefinition(modelName);
|
|
23
23
|
} else if (publisher?.includes("google")) {
|
package/src/watsonx/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AIModel, AbstractDriver, Completion,
|
|
1
|
+
import { AIModel, AbstractDriver, Completion, CompletionChunkObject, DriverOptions, EmbeddingsOptions, EmbeddingsResult, ExecutionOptions, TextFallbackOptions } from "@llumiverse/core";
|
|
2
2
|
import { transformSSEStream } from "@llumiverse/core/async";
|
|
3
3
|
import { FetchClient } from "@vertesia/api-fetch-client";
|
|
4
4
|
import { GenerateEmbeddingPayload, GenerateEmbeddingResponse, WatsonAuthToken, WatsonxListModelResponse, WatsonxModelSpec, WatsonxTextGenerationPayload, WatsonxTextGenerationResponse } from "./interfaces.js";
|
|
@@ -29,12 +29,12 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
|
|
|
29
29
|
this.fetchClient = new FetchClient(this.endpoint_url).withAuthCallback(async () => this.getAuthToken().then(token => `Bearer ${token}`));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
async requestTextCompletion(prompt: string, options: ExecutionOptions): Promise<Completion
|
|
32
|
+
async requestTextCompletion(prompt: string, options: ExecutionOptions): Promise<Completion> {
|
|
33
33
|
if (options.model_options?._option_id !== "text-fallback") {
|
|
34
|
-
this.logger.warn("Invalid model options", {options: options.model_options });
|
|
34
|
+
this.logger.warn("Invalid model options", { options: options.model_options });
|
|
35
35
|
}
|
|
36
36
|
options.model_options = options.model_options as TextFallbackOptions | undefined;
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
const payload: WatsonxTextGenerationPayload = {
|
|
39
39
|
model_id: options.model,
|
|
40
40
|
input: prompt + "\n",
|
|
@@ -53,7 +53,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
|
|
|
53
53
|
const result = res.results[0];
|
|
54
54
|
|
|
55
55
|
return {
|
|
56
|
-
result: result.generated_text,
|
|
56
|
+
result: [{ type: "text", value: result.generated_text }],
|
|
57
57
|
token_usage: {
|
|
58
58
|
prompt: result.input_token_count,
|
|
59
59
|
result: result.generated_token_count,
|
|
@@ -64,9 +64,9 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
async requestTextCompletionStream(prompt: string, options: ExecutionOptions): Promise<AsyncIterable<
|
|
67
|
+
async requestTextCompletionStream(prompt: string, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>> {
|
|
68
68
|
if (options.model_options?._option_id !== "text-fallback") {
|
|
69
|
-
this.logger.warn("Invalid model options", {options: options.model_options });
|
|
69
|
+
this.logger.warn("Invalid model options", { options: options.model_options });
|
|
70
70
|
}
|
|
71
71
|
options.model_options = options.model_options as TextFallbackOptions | undefined;
|
|
72
72
|
const payload: WatsonxTextGenerationPayload = {
|
|
@@ -90,7 +90,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
|
|
|
90
90
|
return transformSSEStream(stream, (data: string) => {
|
|
91
91
|
const json = JSON.parse(data) as WatsonxTextGenerationResponse;
|
|
92
92
|
return {
|
|
93
|
-
result: json.results[0]?.generated_text
|
|
93
|
+
result: json.results[0]?.generated_text ? [{ type: "text", value: json.results[0].generated_text }] : [],
|
|
94
94
|
finish_reason: watsonFinishReason(json.results[0]?.stop_reason),
|
|
95
95
|
token_usage: {
|
|
96
96
|
prompt: json.results[0].input_token_count,
|
|
@@ -132,7 +132,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
|
|
|
132
132
|
if (now < this.authToken.expiration) {
|
|
133
133
|
return this.authToken.access_token;
|
|
134
134
|
} else {
|
|
135
|
-
this.logger.debug("Token expired, refetching"
|
|
135
|
+
this.logger.debug("Token expired, refetching")
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
const authToken = await fetch('https://iam.cloud.ibm.com/identity/token', {
|
|
@@ -163,7 +163,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
if (!options.text) {
|
|
166
|
-
throw new Error
|
|
166
|
+
throw new Error("No text provided");
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
const payload: GenerateEmbeddingPayload = {
|