@gammatech/aijsx 0.9.0-dev.2024-05-28 → 0.9.1-dev.2024-05-28
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/dist/index.d.mts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +264 -5
- package/dist/index.mjs +264 -5
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -6,6 +6,8 @@ export { OpenAI as OpenAIClient } from 'openai';
|
|
|
6
6
|
import { ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam, ChatCompletionAssistantMessageParam, ChatCompletionCreateParams } from 'openai/resources';
|
|
7
7
|
import AnthropicClient from '@anthropic-ai/sdk';
|
|
8
8
|
export { default as AnthropicClient } from '@anthropic-ai/sdk';
|
|
9
|
+
import { GenerateContentRequest, VertexAI } from '@google-cloud/vertexai';
|
|
10
|
+
export { VertexAI } from '@google-cloud/vertexai';
|
|
9
11
|
|
|
10
12
|
declare class ChatCompletionError extends Error {
|
|
11
13
|
readonly chatCompletionRequest: LogChatCompletionRequest;
|
|
@@ -273,4 +275,22 @@ declare function AnthropicChatCompletion(props: AnthropicChatCompletionProps, ct
|
|
|
273
275
|
|
|
274
276
|
declare const anthropicTokenizer: TokenizerFn;
|
|
275
277
|
|
|
276
|
-
|
|
278
|
+
type GoogleChatCompletionRequest = GenerateContentRequest;
|
|
279
|
+
declare module '@gammatech/aijsx' {
|
|
280
|
+
interface ChatCompletionRequestPayloads {
|
|
281
|
+
google: GoogleChatCompletionRequest;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
type ValidGoogleChatModel = 'gemini-1.5-pro' | 'gemini-1.5-flash';
|
|
285
|
+
declare const GoogleClientContext: Context<() => ChatCompletionClientAndProvider<VertexAI>>;
|
|
286
|
+
type GoogleChatCompletionProps = {
|
|
287
|
+
model: ValidGoogleChatModel;
|
|
288
|
+
maxTokens?: number;
|
|
289
|
+
temperature?: number;
|
|
290
|
+
stop?: string | string[];
|
|
291
|
+
maxRetries?: number;
|
|
292
|
+
children: AINode;
|
|
293
|
+
};
|
|
294
|
+
declare function GoogleChatCompletion(props: GoogleChatCompletionProps, ctx: RenderContext): JSX.Element;
|
|
295
|
+
|
|
296
|
+
export { AIComponent, AINode, AISpanAttributes, AISpanProcessor, AnthropicChatCompletion, type AnthropicChatCompletionRequest, AnthropicClientContext, AssistantMessage, type ChatCompletionClientAndProvider, ChatCompletionError, type ChatCompletionRequestPayloads, ChatMessage, Context, type CostFn, DebugMessage, DefaultMaxRetriesContext, EnrichingSpanProcessor, EvaluatorFn, EvaluatorResult, Fallback, FunctionChain, GoogleChatCompletion, type GoogleChatCompletionRequest, GoogleClientContext, LogChatCompletionRequest, LogImplementation, NotAsyncGenerator, OpenAIChatCompletion, type OpenAIChatCompletionRequest, type OpenAIChatMessage, OpenAIClientContext, ParseVariablesError, ProcessedAISpanAttributes, type Prompt, PromptInvalidOutputError, PromptParsed, ReadableSpan, RenderContext, Retry, RetryCountContext, SpanAttributes, SpanExporter, SpanProcessor, StreamChain, SystemMessage, type TokenizerFn, Trace, Tracer, UserMessage, type ValidAnthropicChatModel, type ValidGoogleChatModel, type ValidOpenAIChatModel, type ValidOpenAIVisionModel, anthropicTokenizer, computeUsage, createFunctionChain, createPrompt, createRenderContext, createStreamChain, evaluatePrompt, openaiTokenizer, tracing };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export { OpenAI as OpenAIClient } from 'openai';
|
|
|
6
6
|
import { ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam, ChatCompletionAssistantMessageParam, ChatCompletionCreateParams } from 'openai/resources';
|
|
7
7
|
import AnthropicClient from '@anthropic-ai/sdk';
|
|
8
8
|
export { default as AnthropicClient } from '@anthropic-ai/sdk';
|
|
9
|
+
import { GenerateContentRequest, VertexAI } from '@google-cloud/vertexai';
|
|
10
|
+
export { VertexAI } from '@google-cloud/vertexai';
|
|
9
11
|
|
|
10
12
|
declare class ChatCompletionError extends Error {
|
|
11
13
|
readonly chatCompletionRequest: LogChatCompletionRequest;
|
|
@@ -273,4 +275,22 @@ declare function AnthropicChatCompletion(props: AnthropicChatCompletionProps, ct
|
|
|
273
275
|
|
|
274
276
|
declare const anthropicTokenizer: TokenizerFn;
|
|
275
277
|
|
|
276
|
-
|
|
278
|
+
type GoogleChatCompletionRequest = GenerateContentRequest;
|
|
279
|
+
declare module '@gammatech/aijsx' {
|
|
280
|
+
interface ChatCompletionRequestPayloads {
|
|
281
|
+
google: GoogleChatCompletionRequest;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
type ValidGoogleChatModel = 'gemini-1.5-pro' | 'gemini-1.5-flash';
|
|
285
|
+
declare const GoogleClientContext: Context<() => ChatCompletionClientAndProvider<VertexAI>>;
|
|
286
|
+
type GoogleChatCompletionProps = {
|
|
287
|
+
model: ValidGoogleChatModel;
|
|
288
|
+
maxTokens?: number;
|
|
289
|
+
temperature?: number;
|
|
290
|
+
stop?: string | string[];
|
|
291
|
+
maxRetries?: number;
|
|
292
|
+
children: AINode;
|
|
293
|
+
};
|
|
294
|
+
declare function GoogleChatCompletion(props: GoogleChatCompletionProps, ctx: RenderContext): JSX.Element;
|
|
295
|
+
|
|
296
|
+
export { AIComponent, AINode, AISpanAttributes, AISpanProcessor, AnthropicChatCompletion, type AnthropicChatCompletionRequest, AnthropicClientContext, AssistantMessage, type ChatCompletionClientAndProvider, ChatCompletionError, type ChatCompletionRequestPayloads, ChatMessage, Context, type CostFn, DebugMessage, DefaultMaxRetriesContext, EnrichingSpanProcessor, EvaluatorFn, EvaluatorResult, Fallback, FunctionChain, GoogleChatCompletion, type GoogleChatCompletionRequest, GoogleClientContext, LogChatCompletionRequest, LogImplementation, NotAsyncGenerator, OpenAIChatCompletion, type OpenAIChatCompletionRequest, type OpenAIChatMessage, OpenAIClientContext, ParseVariablesError, ProcessedAISpanAttributes, type Prompt, PromptInvalidOutputError, PromptParsed, ReadableSpan, RenderContext, Retry, RetryCountContext, SpanAttributes, SpanExporter, SpanProcessor, StreamChain, SystemMessage, type TokenizerFn, Trace, Tracer, UserMessage, type ValidAnthropicChatModel, type ValidGoogleChatModel, type ValidOpenAIChatModel, type ValidOpenAIVisionModel, anthropicTokenizer, computeUsage, createFunctionChain, createPrompt, createRenderContext, createStreamChain, evaluatePrompt, openaiTokenizer, tracing };
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,8 @@ __export(src_exports, {
|
|
|
42
42
|
DefaultMaxRetriesContext: () => DefaultMaxRetriesContext,
|
|
43
43
|
EnrichingSpanProcessor: () => EnrichingSpanProcessor,
|
|
44
44
|
Fallback: () => Fallback,
|
|
45
|
+
GoogleChatCompletion: () => GoogleChatCompletion,
|
|
46
|
+
GoogleClientContext: () => GoogleClientContext,
|
|
45
47
|
ImagePart: () => ImagePart,
|
|
46
48
|
LogImplementation: () => LogImplementation,
|
|
47
49
|
NoopLogImplementation: () => NoopLogImplementation,
|
|
@@ -55,6 +57,7 @@ __export(src_exports, {
|
|
|
55
57
|
SystemMessage: () => SystemMessage,
|
|
56
58
|
Trace: () => Trace,
|
|
57
59
|
UserMessage: () => UserMessage,
|
|
60
|
+
VertexAI: () => import_vertexai2.VertexAI,
|
|
58
61
|
anthropicTokenizer: () => anthropicTokenizer,
|
|
59
62
|
attachedContextSymbol: () => attachedContextSymbol,
|
|
60
63
|
computeUsage: () => computeUsage,
|
|
@@ -73,11 +76,11 @@ module.exports = __toCommonJS(src_exports);
|
|
|
73
76
|
|
|
74
77
|
// src/chat/errors.ts
|
|
75
78
|
var ChatCompletionError = class extends Error {
|
|
76
|
-
constructor(message, chatCompletionRequest, status,
|
|
79
|
+
constructor(message, chatCompletionRequest, status, shouldRetry4 = false) {
|
|
77
80
|
super(message);
|
|
78
81
|
this.chatCompletionRequest = chatCompletionRequest;
|
|
79
82
|
this.status = status;
|
|
80
|
-
this.shouldRetry =
|
|
83
|
+
this.shouldRetry = shouldRetry4;
|
|
81
84
|
}
|
|
82
85
|
name = "ChatCompletionError";
|
|
83
86
|
};
|
|
@@ -1599,7 +1602,7 @@ function renderCloseTag(element) {
|
|
|
1599
1602
|
// src/retry.tsx
|
|
1600
1603
|
var RetryCountContext = createContext(0);
|
|
1601
1604
|
var DefaultMaxRetriesContext = createContext(0);
|
|
1602
|
-
async function* Retry({ shouldRetry:
|
|
1605
|
+
async function* Retry({ shouldRetry: shouldRetry4, retries = 0, maxRetries = 3, children }, ctx) {
|
|
1603
1606
|
const { render } = ctx;
|
|
1604
1607
|
let hasYieldedData = false;
|
|
1605
1608
|
try {
|
|
@@ -1611,12 +1614,12 @@ async function* Retry({ shouldRetry: shouldRetry3, retries = 0, maxRetries = 3,
|
|
|
1611
1614
|
yield value;
|
|
1612
1615
|
}
|
|
1613
1616
|
} catch (e) {
|
|
1614
|
-
if (hasYieldedData || retries >= maxRetries || !
|
|
1617
|
+
if (hasYieldedData || retries >= maxRetries || !shouldRetry4(e)) {
|
|
1615
1618
|
throw e;
|
|
1616
1619
|
}
|
|
1617
1620
|
await backoff(retries);
|
|
1618
1621
|
yield* Retry(
|
|
1619
|
-
{ shouldRetry:
|
|
1622
|
+
{ shouldRetry: shouldRetry4, retries: retries + 1, maxRetries, children },
|
|
1620
1623
|
ctx
|
|
1621
1624
|
);
|
|
1622
1625
|
}
|
|
@@ -2527,6 +2530,259 @@ function cleanChatCompletionRequest2(chatCompletionRequest) {
|
|
|
2527
2530
|
|
|
2528
2531
|
// src/lib/anthropic/index.ts
|
|
2529
2532
|
var import_sdk2 = __toESM(require("@anthropic-ai/sdk"));
|
|
2533
|
+
|
|
2534
|
+
// src/lib/google/Google.tsx
|
|
2535
|
+
var import_vertexai = require("@google-cloud/vertexai");
|
|
2536
|
+
var GoogleClientContext = createContext(() => {
|
|
2537
|
+
if (defaultClient3) {
|
|
2538
|
+
return defaultClient3;
|
|
2539
|
+
}
|
|
2540
|
+
const project = process.env.GOOGLE_PROJECT_ID || "";
|
|
2541
|
+
const client = new import_vertexai.VertexAI({ project });
|
|
2542
|
+
defaultClient3 = {
|
|
2543
|
+
client,
|
|
2544
|
+
provider: "google"
|
|
2545
|
+
};
|
|
2546
|
+
return defaultClient3;
|
|
2547
|
+
});
|
|
2548
|
+
var defaultClient3 = null;
|
|
2549
|
+
var buildGoogleMessages = (chatMesssages) => {
|
|
2550
|
+
let systemInstruction;
|
|
2551
|
+
const messages = [];
|
|
2552
|
+
chatMesssages.forEach(({ role, content }) => {
|
|
2553
|
+
if (role === "system") {
|
|
2554
|
+
systemInstruction = content;
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
if (role === "user") {
|
|
2558
|
+
const userContent = content;
|
|
2559
|
+
if (userContent.length === 1 && userContent[0].type === "text") {
|
|
2560
|
+
messages.push({
|
|
2561
|
+
role,
|
|
2562
|
+
parts: [{ text: userContent[0].text }]
|
|
2563
|
+
});
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
const c = userContent.map((part) => {
|
|
2567
|
+
if (part.type === "text") {
|
|
2568
|
+
return { text: part.text };
|
|
2569
|
+
} else if (part.type === "image") {
|
|
2570
|
+
const imagePart = {
|
|
2571
|
+
inlineData: {
|
|
2572
|
+
mimeType: part.image.mediaType,
|
|
2573
|
+
data: part.image.data
|
|
2574
|
+
}
|
|
2575
|
+
};
|
|
2576
|
+
return imagePart;
|
|
2577
|
+
}
|
|
2578
|
+
throw new Error("Invalid part");
|
|
2579
|
+
});
|
|
2580
|
+
messages.push({
|
|
2581
|
+
role,
|
|
2582
|
+
parts: c
|
|
2583
|
+
});
|
|
2584
|
+
return;
|
|
2585
|
+
}
|
|
2586
|
+
if (role === "assistant") {
|
|
2587
|
+
messages.push({
|
|
2588
|
+
role,
|
|
2589
|
+
parts: [{ text: content }]
|
|
2590
|
+
});
|
|
2591
|
+
return;
|
|
2592
|
+
}
|
|
2593
|
+
throw new Error(`Invalid role: ${role}`);
|
|
2594
|
+
});
|
|
2595
|
+
return {
|
|
2596
|
+
systemInstruction,
|
|
2597
|
+
messages
|
|
2598
|
+
};
|
|
2599
|
+
};
|
|
2600
|
+
var shouldRetry3 = (error) => {
|
|
2601
|
+
return error instanceof ChatCompletionError && error.shouldRetry;
|
|
2602
|
+
};
|
|
2603
|
+
function GoogleChatCompletion(props, ctx) {
|
|
2604
|
+
const defaultMaxRetries = ctx.getContext(DefaultMaxRetriesContext);
|
|
2605
|
+
return /* @__PURE__ */ jsx(
|
|
2606
|
+
Retry,
|
|
2607
|
+
{
|
|
2608
|
+
maxRetries: props.maxRetries || defaultMaxRetries,
|
|
2609
|
+
shouldRetry: shouldRetry3,
|
|
2610
|
+
children: /* @__PURE__ */ jsx(Trace, { name: "ai.chatCompletion", children: /* @__PURE__ */ jsx(GoogleChatCompletionInner, { ...props }) })
|
|
2611
|
+
}
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
async function* GoogleChatCompletionInner(props, ctx) {
|
|
2615
|
+
const startTime = performance.now();
|
|
2616
|
+
const { logger, tracer, getContext } = ctx;
|
|
2617
|
+
const retryCount = getContext(RetryCountContext);
|
|
2618
|
+
const span = tracer.getActiveSpan();
|
|
2619
|
+
const { client, provider, providerRegion, costFn } = getContext(GoogleClientContext)();
|
|
2620
|
+
if (!client) {
|
|
2621
|
+
throw new Error(
|
|
2622
|
+
"[GoogleChatCompletion] must supply GoogleClient via context"
|
|
2623
|
+
);
|
|
2624
|
+
}
|
|
2625
|
+
const chatMessages = await buildChatMessages(ctx, props.children, {
|
|
2626
|
+
useBase64Images: true
|
|
2627
|
+
});
|
|
2628
|
+
const { systemInstruction, messages } = buildGoogleMessages(chatMessages);
|
|
2629
|
+
const inputMessages = chatMessages.map((m) => toDebugMessage(m));
|
|
2630
|
+
let stopSequences;
|
|
2631
|
+
if (props.stop && typeof props.stop === "string") {
|
|
2632
|
+
stopSequences = [props.stop];
|
|
2633
|
+
} else if (Array.isArray(props.stop)) {
|
|
2634
|
+
stopSequences = props.stop;
|
|
2635
|
+
}
|
|
2636
|
+
const googleCompletionRequest = {
|
|
2637
|
+
systemInstruction,
|
|
2638
|
+
contents: messages,
|
|
2639
|
+
generationConfig: {
|
|
2640
|
+
maxOutputTokens: props.maxTokens,
|
|
2641
|
+
temperature: props.temperature,
|
|
2642
|
+
stopSequences
|
|
2643
|
+
}
|
|
2644
|
+
};
|
|
2645
|
+
const chatCompletionRequestToLog = cleanChatCompletionRequest3(
|
|
2646
|
+
googleCompletionRequest
|
|
2647
|
+
);
|
|
2648
|
+
const logRequestData = {
|
|
2649
|
+
startTime,
|
|
2650
|
+
model: props.model,
|
|
2651
|
+
provider,
|
|
2652
|
+
providerRegion,
|
|
2653
|
+
inputMessages,
|
|
2654
|
+
request: chatCompletionRequestToLog
|
|
2655
|
+
};
|
|
2656
|
+
logger.chatCompletionRequest("google", logRequestData);
|
|
2657
|
+
span.setAttributes({
|
|
2658
|
+
model: props.model,
|
|
2659
|
+
provider,
|
|
2660
|
+
providerRegion,
|
|
2661
|
+
requestType: "google",
|
|
2662
|
+
chatCompletionRequest: chatCompletionRequestToLog,
|
|
2663
|
+
inputMessages,
|
|
2664
|
+
retryCount
|
|
2665
|
+
});
|
|
2666
|
+
const model = client.getGenerativeModel({ model: props.model });
|
|
2667
|
+
let response;
|
|
2668
|
+
try {
|
|
2669
|
+
response = await model.generateContentStream(googleCompletionRequest);
|
|
2670
|
+
} catch (err) {
|
|
2671
|
+
if (err instanceof import_vertexai.GoogleGenerativeAIError) {
|
|
2672
|
+
throw new ChatCompletionError(
|
|
2673
|
+
err.message,
|
|
2674
|
+
logRequestData,
|
|
2675
|
+
void 0,
|
|
2676
|
+
// always retry on GoogleGenerativeAIError errors, they represent non 4xx error cases
|
|
2677
|
+
true
|
|
2678
|
+
);
|
|
2679
|
+
} else if (err instanceof Error) {
|
|
2680
|
+
const status = void 0;
|
|
2681
|
+
const retry = false;
|
|
2682
|
+
throw new ChatCompletionError(err.message, logRequestData, status, retry);
|
|
2683
|
+
}
|
|
2684
|
+
throw err;
|
|
2685
|
+
}
|
|
2686
|
+
let content = "";
|
|
2687
|
+
let outputUsage = 0;
|
|
2688
|
+
let inputUsage = 0;
|
|
2689
|
+
let finishReason = null;
|
|
2690
|
+
try {
|
|
2691
|
+
for await (const event of response.stream) {
|
|
2692
|
+
if (event.candidates) {
|
|
2693
|
+
const chunk = event.candidates[0].content;
|
|
2694
|
+
if (event.candidates[0]?.finishReason) {
|
|
2695
|
+
finishReason = event.candidates[0].finishReason;
|
|
2696
|
+
}
|
|
2697
|
+
if (event.usageMetadata) {
|
|
2698
|
+
if (event.usageMetadata.promptTokenCount) {
|
|
2699
|
+
inputUsage = event.usageMetadata.promptTokenCount;
|
|
2700
|
+
}
|
|
2701
|
+
if (event.usageMetadata.candidatesTokenCount) {
|
|
2702
|
+
outputUsage = event.usageMetadata.candidatesTokenCount;
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
for (const block of chunk.parts) {
|
|
2706
|
+
if (block.text) {
|
|
2707
|
+
content += block.text;
|
|
2708
|
+
yield block.text;
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
}
|
|
2713
|
+
} catch (err) {
|
|
2714
|
+
if (err instanceof import_vertexai.GoogleGenerativeAIError) {
|
|
2715
|
+
throw new ChatCompletionError(
|
|
2716
|
+
err.message,
|
|
2717
|
+
logRequestData,
|
|
2718
|
+
void 0,
|
|
2719
|
+
// always retry these errors they represent non 4xx error cases
|
|
2720
|
+
true
|
|
2721
|
+
);
|
|
2722
|
+
} else if (err instanceof Error) {
|
|
2723
|
+
const status = void 0;
|
|
2724
|
+
const retry = false;
|
|
2725
|
+
throw new ChatCompletionError(err.message, logRequestData, status, retry);
|
|
2726
|
+
}
|
|
2727
|
+
throw err;
|
|
2728
|
+
}
|
|
2729
|
+
const outputMessage = {
|
|
2730
|
+
role: "assistant",
|
|
2731
|
+
content
|
|
2732
|
+
};
|
|
2733
|
+
const tokensUsed = {
|
|
2734
|
+
prompt: inputUsage,
|
|
2735
|
+
completion: outputUsage,
|
|
2736
|
+
total: inputUsage + outputUsage
|
|
2737
|
+
};
|
|
2738
|
+
const cost = costFn?.(props.model, tokensUsed) ?? void 0;
|
|
2739
|
+
const responseData = {
|
|
2740
|
+
...logRequestData,
|
|
2741
|
+
finishReason,
|
|
2742
|
+
latency: performance.now() - startTime,
|
|
2743
|
+
inputMessages,
|
|
2744
|
+
outputMessage,
|
|
2745
|
+
tokensUsed
|
|
2746
|
+
};
|
|
2747
|
+
logger.chatCompletionResponse("google", responseData);
|
|
2748
|
+
span.setAttributes({
|
|
2749
|
+
tokensUsed,
|
|
2750
|
+
output: content,
|
|
2751
|
+
cost,
|
|
2752
|
+
finishReason
|
|
2753
|
+
});
|
|
2754
|
+
}
|
|
2755
|
+
function cleanChatCompletionRequest3(chatCompletionRequest) {
|
|
2756
|
+
const { contents, ...rest } = chatCompletionRequest;
|
|
2757
|
+
return {
|
|
2758
|
+
...rest,
|
|
2759
|
+
contents: contents.map((message) => {
|
|
2760
|
+
if (message.role !== "user") {
|
|
2761
|
+
return message;
|
|
2762
|
+
}
|
|
2763
|
+
return {
|
|
2764
|
+
...message,
|
|
2765
|
+
parts: message.parts.map((part) => {
|
|
2766
|
+
if ("text" in part) {
|
|
2767
|
+
return part;
|
|
2768
|
+
} else if ("inlineData" in part) {
|
|
2769
|
+
return {
|
|
2770
|
+
inlineData: {
|
|
2771
|
+
...part.inlineData,
|
|
2772
|
+
mimeType: part.inlineData?.mimeType || "",
|
|
2773
|
+
data: part.inlineData?.data?.slice(0, 22) + "..."
|
|
2774
|
+
}
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
return part;
|
|
2778
|
+
})
|
|
2779
|
+
};
|
|
2780
|
+
})
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
// src/lib/google/index.ts
|
|
2785
|
+
var import_vertexai2 = require("@google-cloud/vertexai");
|
|
2530
2786
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2531
2787
|
0 && (module.exports = {
|
|
2532
2788
|
AIFragment,
|
|
@@ -2542,6 +2798,8 @@ var import_sdk2 = __toESM(require("@anthropic-ai/sdk"));
|
|
|
2542
2798
|
DefaultMaxRetriesContext,
|
|
2543
2799
|
EnrichingSpanProcessor,
|
|
2544
2800
|
Fallback,
|
|
2801
|
+
GoogleChatCompletion,
|
|
2802
|
+
GoogleClientContext,
|
|
2545
2803
|
ImagePart,
|
|
2546
2804
|
LogImplementation,
|
|
2547
2805
|
NoopLogImplementation,
|
|
@@ -2555,6 +2813,7 @@ var import_sdk2 = __toESM(require("@anthropic-ai/sdk"));
|
|
|
2555
2813
|
SystemMessage,
|
|
2556
2814
|
Trace,
|
|
2557
2815
|
UserMessage,
|
|
2816
|
+
VertexAI,
|
|
2558
2817
|
anthropicTokenizer,
|
|
2559
2818
|
attachedContextSymbol,
|
|
2560
2819
|
computeUsage,
|
package/dist/index.mjs
CHANGED
|
@@ -8,11 +8,11 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/chat/errors.ts
|
|
10
10
|
var ChatCompletionError = class extends Error {
|
|
11
|
-
constructor(message, chatCompletionRequest, status,
|
|
11
|
+
constructor(message, chatCompletionRequest, status, shouldRetry4 = false) {
|
|
12
12
|
super(message);
|
|
13
13
|
this.chatCompletionRequest = chatCompletionRequest;
|
|
14
14
|
this.status = status;
|
|
15
|
-
this.shouldRetry =
|
|
15
|
+
this.shouldRetry = shouldRetry4;
|
|
16
16
|
}
|
|
17
17
|
name = "ChatCompletionError";
|
|
18
18
|
};
|
|
@@ -1501,7 +1501,7 @@ function renderCloseTag(element) {
|
|
|
1501
1501
|
// src/retry.tsx
|
|
1502
1502
|
var RetryCountContext = createContext(0);
|
|
1503
1503
|
var DefaultMaxRetriesContext = createContext(0);
|
|
1504
|
-
async function* Retry({ shouldRetry:
|
|
1504
|
+
async function* Retry({ shouldRetry: shouldRetry4, retries = 0, maxRetries = 3, children }, ctx) {
|
|
1505
1505
|
const { render } = ctx;
|
|
1506
1506
|
let hasYieldedData = false;
|
|
1507
1507
|
try {
|
|
@@ -1513,12 +1513,12 @@ async function* Retry({ shouldRetry: shouldRetry3, retries = 0, maxRetries = 3,
|
|
|
1513
1513
|
yield value;
|
|
1514
1514
|
}
|
|
1515
1515
|
} catch (e) {
|
|
1516
|
-
if (hasYieldedData || retries >= maxRetries || !
|
|
1516
|
+
if (hasYieldedData || retries >= maxRetries || !shouldRetry4(e)) {
|
|
1517
1517
|
throw e;
|
|
1518
1518
|
}
|
|
1519
1519
|
await backoff(retries);
|
|
1520
1520
|
yield* Retry(
|
|
1521
|
-
{ shouldRetry:
|
|
1521
|
+
{ shouldRetry: shouldRetry4, retries: retries + 1, maxRetries, children },
|
|
1522
1522
|
ctx
|
|
1523
1523
|
);
|
|
1524
1524
|
}
|
|
@@ -2429,6 +2429,262 @@ function cleanChatCompletionRequest2(chatCompletionRequest) {
|
|
|
2429
2429
|
|
|
2430
2430
|
// src/lib/anthropic/index.ts
|
|
2431
2431
|
import AnthropicClient2 from "@anthropic-ai/sdk";
|
|
2432
|
+
|
|
2433
|
+
// src/lib/google/Google.tsx
|
|
2434
|
+
import {
|
|
2435
|
+
VertexAI,
|
|
2436
|
+
GoogleGenerativeAIError
|
|
2437
|
+
} from "@google-cloud/vertexai";
|
|
2438
|
+
var GoogleClientContext = createContext(() => {
|
|
2439
|
+
if (defaultClient3) {
|
|
2440
|
+
return defaultClient3;
|
|
2441
|
+
}
|
|
2442
|
+
const project = process.env.GOOGLE_PROJECT_ID || "";
|
|
2443
|
+
const client = new VertexAI({ project });
|
|
2444
|
+
defaultClient3 = {
|
|
2445
|
+
client,
|
|
2446
|
+
provider: "google"
|
|
2447
|
+
};
|
|
2448
|
+
return defaultClient3;
|
|
2449
|
+
});
|
|
2450
|
+
var defaultClient3 = null;
|
|
2451
|
+
var buildGoogleMessages = (chatMesssages) => {
|
|
2452
|
+
let systemInstruction;
|
|
2453
|
+
const messages = [];
|
|
2454
|
+
chatMesssages.forEach(({ role, content }) => {
|
|
2455
|
+
if (role === "system") {
|
|
2456
|
+
systemInstruction = content;
|
|
2457
|
+
return;
|
|
2458
|
+
}
|
|
2459
|
+
if (role === "user") {
|
|
2460
|
+
const userContent = content;
|
|
2461
|
+
if (userContent.length === 1 && userContent[0].type === "text") {
|
|
2462
|
+
messages.push({
|
|
2463
|
+
role,
|
|
2464
|
+
parts: [{ text: userContent[0].text }]
|
|
2465
|
+
});
|
|
2466
|
+
return;
|
|
2467
|
+
}
|
|
2468
|
+
const c = userContent.map((part) => {
|
|
2469
|
+
if (part.type === "text") {
|
|
2470
|
+
return { text: part.text };
|
|
2471
|
+
} else if (part.type === "image") {
|
|
2472
|
+
const imagePart = {
|
|
2473
|
+
inlineData: {
|
|
2474
|
+
mimeType: part.image.mediaType,
|
|
2475
|
+
data: part.image.data
|
|
2476
|
+
}
|
|
2477
|
+
};
|
|
2478
|
+
return imagePart;
|
|
2479
|
+
}
|
|
2480
|
+
throw new Error("Invalid part");
|
|
2481
|
+
});
|
|
2482
|
+
messages.push({
|
|
2483
|
+
role,
|
|
2484
|
+
parts: c
|
|
2485
|
+
});
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
if (role === "assistant") {
|
|
2489
|
+
messages.push({
|
|
2490
|
+
role,
|
|
2491
|
+
parts: [{ text: content }]
|
|
2492
|
+
});
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2495
|
+
throw new Error(`Invalid role: ${role}`);
|
|
2496
|
+
});
|
|
2497
|
+
return {
|
|
2498
|
+
systemInstruction,
|
|
2499
|
+
messages
|
|
2500
|
+
};
|
|
2501
|
+
};
|
|
2502
|
+
var shouldRetry3 = (error) => {
|
|
2503
|
+
return error instanceof ChatCompletionError && error.shouldRetry;
|
|
2504
|
+
};
|
|
2505
|
+
function GoogleChatCompletion(props, ctx) {
|
|
2506
|
+
const defaultMaxRetries = ctx.getContext(DefaultMaxRetriesContext);
|
|
2507
|
+
return /* @__PURE__ */ jsx(
|
|
2508
|
+
Retry,
|
|
2509
|
+
{
|
|
2510
|
+
maxRetries: props.maxRetries || defaultMaxRetries,
|
|
2511
|
+
shouldRetry: shouldRetry3,
|
|
2512
|
+
children: /* @__PURE__ */ jsx(Trace, { name: "ai.chatCompletion", children: /* @__PURE__ */ jsx(GoogleChatCompletionInner, { ...props }) })
|
|
2513
|
+
}
|
|
2514
|
+
);
|
|
2515
|
+
}
|
|
2516
|
+
async function* GoogleChatCompletionInner(props, ctx) {
|
|
2517
|
+
const startTime = performance.now();
|
|
2518
|
+
const { logger, tracer, getContext } = ctx;
|
|
2519
|
+
const retryCount = getContext(RetryCountContext);
|
|
2520
|
+
const span = tracer.getActiveSpan();
|
|
2521
|
+
const { client, provider, providerRegion, costFn } = getContext(GoogleClientContext)();
|
|
2522
|
+
if (!client) {
|
|
2523
|
+
throw new Error(
|
|
2524
|
+
"[GoogleChatCompletion] must supply GoogleClient via context"
|
|
2525
|
+
);
|
|
2526
|
+
}
|
|
2527
|
+
const chatMessages = await buildChatMessages(ctx, props.children, {
|
|
2528
|
+
useBase64Images: true
|
|
2529
|
+
});
|
|
2530
|
+
const { systemInstruction, messages } = buildGoogleMessages(chatMessages);
|
|
2531
|
+
const inputMessages = chatMessages.map((m) => toDebugMessage(m));
|
|
2532
|
+
let stopSequences;
|
|
2533
|
+
if (props.stop && typeof props.stop === "string") {
|
|
2534
|
+
stopSequences = [props.stop];
|
|
2535
|
+
} else if (Array.isArray(props.stop)) {
|
|
2536
|
+
stopSequences = props.stop;
|
|
2537
|
+
}
|
|
2538
|
+
const googleCompletionRequest = {
|
|
2539
|
+
systemInstruction,
|
|
2540
|
+
contents: messages,
|
|
2541
|
+
generationConfig: {
|
|
2542
|
+
maxOutputTokens: props.maxTokens,
|
|
2543
|
+
temperature: props.temperature,
|
|
2544
|
+
stopSequences
|
|
2545
|
+
}
|
|
2546
|
+
};
|
|
2547
|
+
const chatCompletionRequestToLog = cleanChatCompletionRequest3(
|
|
2548
|
+
googleCompletionRequest
|
|
2549
|
+
);
|
|
2550
|
+
const logRequestData = {
|
|
2551
|
+
startTime,
|
|
2552
|
+
model: props.model,
|
|
2553
|
+
provider,
|
|
2554
|
+
providerRegion,
|
|
2555
|
+
inputMessages,
|
|
2556
|
+
request: chatCompletionRequestToLog
|
|
2557
|
+
};
|
|
2558
|
+
logger.chatCompletionRequest("google", logRequestData);
|
|
2559
|
+
span.setAttributes({
|
|
2560
|
+
model: props.model,
|
|
2561
|
+
provider,
|
|
2562
|
+
providerRegion,
|
|
2563
|
+
requestType: "google",
|
|
2564
|
+
chatCompletionRequest: chatCompletionRequestToLog,
|
|
2565
|
+
inputMessages,
|
|
2566
|
+
retryCount
|
|
2567
|
+
});
|
|
2568
|
+
const model = client.getGenerativeModel({ model: props.model });
|
|
2569
|
+
let response;
|
|
2570
|
+
try {
|
|
2571
|
+
response = await model.generateContentStream(googleCompletionRequest);
|
|
2572
|
+
} catch (err) {
|
|
2573
|
+
if (err instanceof GoogleGenerativeAIError) {
|
|
2574
|
+
throw new ChatCompletionError(
|
|
2575
|
+
err.message,
|
|
2576
|
+
logRequestData,
|
|
2577
|
+
void 0,
|
|
2578
|
+
// always retry on GoogleGenerativeAIError errors, they represent non 4xx error cases
|
|
2579
|
+
true
|
|
2580
|
+
);
|
|
2581
|
+
} else if (err instanceof Error) {
|
|
2582
|
+
const status = void 0;
|
|
2583
|
+
const retry = false;
|
|
2584
|
+
throw new ChatCompletionError(err.message, logRequestData, status, retry);
|
|
2585
|
+
}
|
|
2586
|
+
throw err;
|
|
2587
|
+
}
|
|
2588
|
+
let content = "";
|
|
2589
|
+
let outputUsage = 0;
|
|
2590
|
+
let inputUsage = 0;
|
|
2591
|
+
let finishReason = null;
|
|
2592
|
+
try {
|
|
2593
|
+
for await (const event of response.stream) {
|
|
2594
|
+
if (event.candidates) {
|
|
2595
|
+
const chunk = event.candidates[0].content;
|
|
2596
|
+
if (event.candidates[0]?.finishReason) {
|
|
2597
|
+
finishReason = event.candidates[0].finishReason;
|
|
2598
|
+
}
|
|
2599
|
+
if (event.usageMetadata) {
|
|
2600
|
+
if (event.usageMetadata.promptTokenCount) {
|
|
2601
|
+
inputUsage = event.usageMetadata.promptTokenCount;
|
|
2602
|
+
}
|
|
2603
|
+
if (event.usageMetadata.candidatesTokenCount) {
|
|
2604
|
+
outputUsage = event.usageMetadata.candidatesTokenCount;
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
for (const block of chunk.parts) {
|
|
2608
|
+
if (block.text) {
|
|
2609
|
+
content += block.text;
|
|
2610
|
+
yield block.text;
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
} catch (err) {
|
|
2616
|
+
if (err instanceof GoogleGenerativeAIError) {
|
|
2617
|
+
throw new ChatCompletionError(
|
|
2618
|
+
err.message,
|
|
2619
|
+
logRequestData,
|
|
2620
|
+
void 0,
|
|
2621
|
+
// always retry these errors they represent non 4xx error cases
|
|
2622
|
+
true
|
|
2623
|
+
);
|
|
2624
|
+
} else if (err instanceof Error) {
|
|
2625
|
+
const status = void 0;
|
|
2626
|
+
const retry = false;
|
|
2627
|
+
throw new ChatCompletionError(err.message, logRequestData, status, retry);
|
|
2628
|
+
}
|
|
2629
|
+
throw err;
|
|
2630
|
+
}
|
|
2631
|
+
const outputMessage = {
|
|
2632
|
+
role: "assistant",
|
|
2633
|
+
content
|
|
2634
|
+
};
|
|
2635
|
+
const tokensUsed = {
|
|
2636
|
+
prompt: inputUsage,
|
|
2637
|
+
completion: outputUsage,
|
|
2638
|
+
total: inputUsage + outputUsage
|
|
2639
|
+
};
|
|
2640
|
+
const cost = costFn?.(props.model, tokensUsed) ?? void 0;
|
|
2641
|
+
const responseData = {
|
|
2642
|
+
...logRequestData,
|
|
2643
|
+
finishReason,
|
|
2644
|
+
latency: performance.now() - startTime,
|
|
2645
|
+
inputMessages,
|
|
2646
|
+
outputMessage,
|
|
2647
|
+
tokensUsed
|
|
2648
|
+
};
|
|
2649
|
+
logger.chatCompletionResponse("google", responseData);
|
|
2650
|
+
span.setAttributes({
|
|
2651
|
+
tokensUsed,
|
|
2652
|
+
output: content,
|
|
2653
|
+
cost,
|
|
2654
|
+
finishReason
|
|
2655
|
+
});
|
|
2656
|
+
}
|
|
2657
|
+
function cleanChatCompletionRequest3(chatCompletionRequest) {
|
|
2658
|
+
const { contents, ...rest } = chatCompletionRequest;
|
|
2659
|
+
return {
|
|
2660
|
+
...rest,
|
|
2661
|
+
contents: contents.map((message) => {
|
|
2662
|
+
if (message.role !== "user") {
|
|
2663
|
+
return message;
|
|
2664
|
+
}
|
|
2665
|
+
return {
|
|
2666
|
+
...message,
|
|
2667
|
+
parts: message.parts.map((part) => {
|
|
2668
|
+
if ("text" in part) {
|
|
2669
|
+
return part;
|
|
2670
|
+
} else if ("inlineData" in part) {
|
|
2671
|
+
return {
|
|
2672
|
+
inlineData: {
|
|
2673
|
+
...part.inlineData,
|
|
2674
|
+
mimeType: part.inlineData?.mimeType || "",
|
|
2675
|
+
data: part.inlineData?.data?.slice(0, 22) + "..."
|
|
2676
|
+
}
|
|
2677
|
+
};
|
|
2678
|
+
}
|
|
2679
|
+
return part;
|
|
2680
|
+
})
|
|
2681
|
+
};
|
|
2682
|
+
})
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
// src/lib/google/index.ts
|
|
2687
|
+
import { VertexAI as VertexAI2 } from "@google-cloud/vertexai";
|
|
2432
2688
|
export {
|
|
2433
2689
|
AIFragment,
|
|
2434
2690
|
AISpanProcessor,
|
|
@@ -2443,6 +2699,8 @@ export {
|
|
|
2443
2699
|
DefaultMaxRetriesContext,
|
|
2444
2700
|
EnrichingSpanProcessor,
|
|
2445
2701
|
Fallback,
|
|
2702
|
+
GoogleChatCompletion,
|
|
2703
|
+
GoogleClientContext,
|
|
2446
2704
|
ImagePart,
|
|
2447
2705
|
LogImplementation,
|
|
2448
2706
|
NoopLogImplementation,
|
|
@@ -2456,6 +2714,7 @@ export {
|
|
|
2456
2714
|
SystemMessage,
|
|
2457
2715
|
Trace,
|
|
2458
2716
|
UserMessage,
|
|
2717
|
+
VertexAI2 as VertexAI,
|
|
2459
2718
|
anthropicTokenizer,
|
|
2460
2719
|
attachedContextSymbol,
|
|
2461
2720
|
computeUsage,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gammatech/aijsx",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1-dev.2024-05-28",
|
|
4
4
|
"description": "Rewrite of aijsx",
|
|
5
5
|
"author": "Jordan Garcia",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@anthropic-ai/sdk": "0.19.1",
|
|
22
22
|
"@anthropic-ai/tokenizer": "^0.0.4",
|
|
23
|
-
"
|
|
23
|
+
"@google-cloud/vertexai": "^1.2.0",
|
|
24
24
|
"fast-xml-parser": "^4.3.4",
|
|
25
25
|
"js-tiktoken": "^1.0.8",
|
|
26
26
|
"nanoid": "^3.1.23",
|