@posthog/ai 3.2.0 → 3.3.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/CHANGELOG.md +11 -1
- package/lib/index.cjs.js +119 -19
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.esm.js +120 -20
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-ai/src/utils.d.ts +5 -1
- package/package.json +1 -1
- package/src/anthropic/index.ts +12 -1
- package/src/langchain/callbacks.ts +6 -0
- package/src/openai/azure.ts +10 -1
- package/src/openai/index.ts +13 -2
- package/src/utils.ts +17 -1
- package/src/vercel/middleware.ts +94 -16
- package/tests/openai.test.ts +36 -0
package/lib/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import OpenAIOrignal, { AzureOpenAI } from 'openai';
|
|
2
2
|
import * as uuid from 'uuid';
|
|
3
3
|
import { v4 } from 'uuid';
|
|
4
|
-
import {
|
|
4
|
+
import { experimental_wrapLanguageModel } from 'ai';
|
|
5
5
|
import AnthropicOriginal from '@anthropic-ai/sdk';
|
|
6
6
|
|
|
7
7
|
const getModelParams = params => {
|
|
@@ -73,7 +73,8 @@ const sendEventToPosthog = ({
|
|
|
73
73
|
httpStatus = 200,
|
|
74
74
|
usage = {},
|
|
75
75
|
isError = false,
|
|
76
|
-
error
|
|
76
|
+
error,
|
|
77
|
+
tools
|
|
77
78
|
}) => {
|
|
78
79
|
if (client.capture) {
|
|
79
80
|
let errorData = {};
|
|
@@ -93,6 +94,17 @@ const sendEventToPosthog = ({
|
|
|
93
94
|
$ai_total_cost_usd: inputCostUSD + outputCostUSD
|
|
94
95
|
};
|
|
95
96
|
}
|
|
97
|
+
let additionalTokenValues = {
|
|
98
|
+
...(usage.reasoningTokens ? {
|
|
99
|
+
$ai_reasoning_tokens: usage.reasoningTokens
|
|
100
|
+
} : {}),
|
|
101
|
+
...(usage.cacheReadInputTokens ? {
|
|
102
|
+
$ai_cache_read_input_tokens: usage.cacheReadInputTokens
|
|
103
|
+
} : {}),
|
|
104
|
+
...(usage.cacheCreationInputTokens ? {
|
|
105
|
+
$ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
|
|
106
|
+
} : {})
|
|
107
|
+
};
|
|
96
108
|
client.capture({
|
|
97
109
|
distinctId: distinctId ?? traceId,
|
|
98
110
|
event: '$ai_generation',
|
|
@@ -105,6 +117,7 @@ const sendEventToPosthog = ({
|
|
|
105
117
|
$ai_http_status: httpStatus,
|
|
106
118
|
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
107
119
|
$ai_output_tokens: usage.outputTokens ?? 0,
|
|
120
|
+
...additionalTokenValues,
|
|
108
121
|
$ai_latency: latency,
|
|
109
122
|
$ai_trace_id: traceId,
|
|
110
123
|
$ai_base_url: baseURL,
|
|
@@ -112,6 +125,9 @@ const sendEventToPosthog = ({
|
|
|
112
125
|
...(distinctId ? {} : {
|
|
113
126
|
$process_person_profile: false
|
|
114
127
|
}),
|
|
128
|
+
...(tools ? {
|
|
129
|
+
$ai_tools: tools
|
|
130
|
+
} : {}),
|
|
115
131
|
...errorData,
|
|
116
132
|
...costOverrideData
|
|
117
133
|
},
|
|
@@ -173,7 +189,9 @@ class WrappedCompletions$1 extends OpenAIOrignal.Chat.Completions {
|
|
|
173
189
|
if (chunk.usage) {
|
|
174
190
|
usage = {
|
|
175
191
|
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
176
|
-
outputTokens: chunk.usage.completion_tokens ?? 0
|
|
192
|
+
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
193
|
+
reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
194
|
+
cacheReadInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
|
|
177
195
|
};
|
|
178
196
|
}
|
|
179
197
|
}
|
|
@@ -240,7 +258,9 @@ class WrappedCompletions$1 extends OpenAIOrignal.Chat.Completions {
|
|
|
240
258
|
httpStatus: 200,
|
|
241
259
|
usage: {
|
|
242
260
|
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
243
|
-
outputTokens: result.usage?.completion_tokens ?? 0
|
|
261
|
+
outputTokens: result.usage?.completion_tokens ?? 0,
|
|
262
|
+
reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
263
|
+
cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
|
|
244
264
|
}
|
|
245
265
|
});
|
|
246
266
|
}
|
|
@@ -329,7 +349,9 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
329
349
|
}
|
|
330
350
|
usage = {
|
|
331
351
|
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
332
|
-
outputTokens: chunk.usage.completion_tokens ?? 0
|
|
352
|
+
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
353
|
+
reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
354
|
+
cacheReadInputTokens: chunk.usage.prompt_tokens_details?.cached_tokens ?? 0
|
|
333
355
|
};
|
|
334
356
|
}
|
|
335
357
|
}
|
|
@@ -401,7 +423,9 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
401
423
|
httpStatus: 200,
|
|
402
424
|
usage: {
|
|
403
425
|
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
404
|
-
outputTokens: result.usage?.completion_tokens ?? 0
|
|
426
|
+
outputTokens: result.usage?.completion_tokens ?? 0,
|
|
427
|
+
reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
428
|
+
cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
|
|
405
429
|
}
|
|
406
430
|
});
|
|
407
431
|
}
|
|
@@ -446,16 +470,60 @@ const mapVercelParams = params => {
|
|
|
446
470
|
};
|
|
447
471
|
const mapVercelPrompt = prompt => {
|
|
448
472
|
return prompt.map(p => {
|
|
449
|
-
let content =
|
|
473
|
+
let content = {};
|
|
450
474
|
if (Array.isArray(p.content)) {
|
|
451
475
|
content = p.content.map(c => {
|
|
452
476
|
if (c.type === 'text') {
|
|
453
|
-
return
|
|
477
|
+
return {
|
|
478
|
+
type: 'text',
|
|
479
|
+
content: c.text
|
|
480
|
+
};
|
|
481
|
+
} else if (c.type === 'image') {
|
|
482
|
+
return {
|
|
483
|
+
type: 'image',
|
|
484
|
+
content: {
|
|
485
|
+
// if image is a url use it, or use "none supported"
|
|
486
|
+
image: c.image instanceof URL ? c.image.toString() : 'raw images not supported',
|
|
487
|
+
mimeType: c.mimeType
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
} else if (c.type === 'file') {
|
|
491
|
+
return {
|
|
492
|
+
type: 'file',
|
|
493
|
+
content: {
|
|
494
|
+
file: c.data instanceof URL ? c.data.toString() : 'raw files not supported',
|
|
495
|
+
mimeType: c.mimeType
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
} else if (c.type === 'tool-call') {
|
|
499
|
+
return {
|
|
500
|
+
type: 'tool-call',
|
|
501
|
+
content: {
|
|
502
|
+
toolCallId: c.toolCallId,
|
|
503
|
+
toolName: c.toolName,
|
|
504
|
+
args: c.args
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
} else if (c.type === 'tool-result') {
|
|
508
|
+
return {
|
|
509
|
+
type: 'tool-result',
|
|
510
|
+
content: {
|
|
511
|
+
toolCallId: c.toolCallId,
|
|
512
|
+
toolName: c.toolName,
|
|
513
|
+
result: c.result,
|
|
514
|
+
isError: c.isError
|
|
515
|
+
}
|
|
516
|
+
};
|
|
454
517
|
}
|
|
455
|
-
return
|
|
456
|
-
|
|
518
|
+
return {
|
|
519
|
+
content: ''
|
|
520
|
+
};
|
|
521
|
+
});
|
|
457
522
|
} else {
|
|
458
|
-
content =
|
|
523
|
+
content = {
|
|
524
|
+
type: 'text',
|
|
525
|
+
text: p.content
|
|
526
|
+
};
|
|
459
527
|
}
|
|
460
528
|
return {
|
|
461
529
|
role: p.role,
|
|
@@ -486,11 +554,21 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
486
554
|
const modelId = options.posthogModelOverride ?? (result.response?.modelId ? result.response.modelId : model.modelId);
|
|
487
555
|
const provider = options.posthogProviderOverride ?? extractProvider(model);
|
|
488
556
|
const baseURL = ''; // cannot currently get baseURL from vercel
|
|
489
|
-
let content = result.text;
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
557
|
+
let content = result.text || JSON.stringify(result);
|
|
558
|
+
// let tools = result.toolCalls
|
|
559
|
+
let providerMetadata = result.providerMetadata;
|
|
560
|
+
let additionalTokenValues = {
|
|
561
|
+
...(providerMetadata?.openai?.reasoningTokens ? {
|
|
562
|
+
reasoningTokens: providerMetadata.openai.reasoningTokens
|
|
563
|
+
} : {}),
|
|
564
|
+
...(providerMetadata?.openai?.cachedPromptToken ? {
|
|
565
|
+
cacheReadInputTokens: providerMetadata.openai.cachedPromptTokens
|
|
566
|
+
} : {}),
|
|
567
|
+
...(providerMetadata?.anthropic ? {
|
|
568
|
+
cacheReadInputTokens: providerMetadata.anthropic.cacheReadInputTokens,
|
|
569
|
+
cacheCreationInputTokens: providerMetadata.anthropic.cacheCreationInputTokens
|
|
570
|
+
} : {})
|
|
571
|
+
};
|
|
494
572
|
sendEventToPosthog({
|
|
495
573
|
client: phClient,
|
|
496
574
|
distinctId: options.posthogDistinctId,
|
|
@@ -508,7 +586,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
508
586
|
httpStatus: 200,
|
|
509
587
|
usage: {
|
|
510
588
|
inputTokens: result.usage.promptTokens,
|
|
511
|
-
outputTokens: result.usage.completionTokens
|
|
589
|
+
outputTokens: result.usage.completionTokens,
|
|
590
|
+
...additionalTokenValues
|
|
512
591
|
}
|
|
513
592
|
});
|
|
514
593
|
return result;
|
|
@@ -565,6 +644,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
565
644
|
inputTokens: chunk.usage?.promptTokens,
|
|
566
645
|
outputTokens: chunk.usage?.completionTokens
|
|
567
646
|
};
|
|
647
|
+
if (chunk.providerMetadata?.openai?.reasoningTokens) {
|
|
648
|
+
usage.reasoningTokens = chunk.providerMetadata.openai.reasoningTokens;
|
|
649
|
+
}
|
|
650
|
+
if (chunk.providerMetadata?.openai?.cachedPromptToken) {
|
|
651
|
+
usage.cacheReadInputTokens = chunk.providerMetadata.openai.cachedPromptToken;
|
|
652
|
+
}
|
|
653
|
+
if (chunk.providerMetadata?.anthropic?.cacheReadInputTokens) {
|
|
654
|
+
usage.cacheReadInputTokens = chunk.providerMetadata.anthropic.cacheReadInputTokens;
|
|
655
|
+
}
|
|
656
|
+
if (chunk.providerMetadata?.anthropic?.cacheCreationInputTokens) {
|
|
657
|
+
usage.cacheCreationInputTokens = chunk.providerMetadata.anthropic.cacheCreationInputTokens;
|
|
658
|
+
}
|
|
568
659
|
}
|
|
569
660
|
controller.enqueue(chunk);
|
|
570
661
|
},
|
|
@@ -626,7 +717,7 @@ const wrapVercelLanguageModel = (model, phClient, options) => {
|
|
|
626
717
|
posthogTraceId: traceId,
|
|
627
718
|
posthogDistinctId: options.posthogDistinctId ?? traceId
|
|
628
719
|
});
|
|
629
|
-
const wrappedModel =
|
|
720
|
+
const wrappedModel = experimental_wrapLanguageModel({
|
|
630
721
|
model,
|
|
631
722
|
middleware
|
|
632
723
|
});
|
|
@@ -667,7 +758,9 @@ class WrappedMessages extends AnthropicOriginal.Messages {
|
|
|
667
758
|
let accumulatedContent = '';
|
|
668
759
|
const usage = {
|
|
669
760
|
inputTokens: 0,
|
|
670
|
-
outputTokens: 0
|
|
761
|
+
outputTokens: 0,
|
|
762
|
+
cacheCreationInputTokens: 0,
|
|
763
|
+
cacheReadInputTokens: 0
|
|
671
764
|
};
|
|
672
765
|
if ('tee' in value) {
|
|
673
766
|
const [stream1, stream2] = value.tee();
|
|
@@ -682,6 +775,8 @@ class WrappedMessages extends AnthropicOriginal.Messages {
|
|
|
682
775
|
}
|
|
683
776
|
if (chunk.type == 'message_start') {
|
|
684
777
|
usage.inputTokens = chunk.message.usage.input_tokens ?? 0;
|
|
778
|
+
usage.cacheCreationInputTokens = chunk.message.usage.cache_creation_input_tokens ?? 0;
|
|
779
|
+
usage.cacheReadInputTokens = chunk.message.usage.cache_read_input_tokens ?? 0;
|
|
685
780
|
}
|
|
686
781
|
if ('usage' in chunk) {
|
|
687
782
|
usage.outputTokens = chunk.usage.output_tokens ?? 0;
|
|
@@ -751,7 +846,9 @@ class WrappedMessages extends AnthropicOriginal.Messages {
|
|
|
751
846
|
httpStatus: 200,
|
|
752
847
|
usage: {
|
|
753
848
|
inputTokens: result.usage.input_tokens ?? 0,
|
|
754
|
-
outputTokens: result.usage.output_tokens ?? 0
|
|
849
|
+
outputTokens: result.usage.output_tokens ?? 0,
|
|
850
|
+
cacheCreationInputTokens: result.usage.cache_creation_input_tokens ?? 0,
|
|
851
|
+
cacheReadInputTokens: result.usage.cache_read_input_tokens ?? 0
|
|
755
852
|
}
|
|
756
853
|
});
|
|
757
854
|
}
|
|
@@ -1522,6 +1619,9 @@ class LangChainCallbackHandler extends BaseCallbackHandler {
|
|
|
1522
1619
|
$ai_latency: latency,
|
|
1523
1620
|
$ai_base_url: run.baseUrl
|
|
1524
1621
|
};
|
|
1622
|
+
if (run.tools) {
|
|
1623
|
+
eventProperties['$ai_tools'] = withPrivacyMode(this.client, this.privacyMode, run.tools);
|
|
1624
|
+
}
|
|
1525
1625
|
if (output instanceof Error) {
|
|
1526
1626
|
eventProperties['$ai_http_status'] = output.status || 500;
|
|
1527
1627
|
eventProperties['$ai_error'] = output.toString();
|