@posthog/ai 5.0.1 → 5.2.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 +7 -1
- package/lib/anthropic/index.cjs +4 -4
- package/lib/anthropic/index.cjs.map +1 -1
- package/lib/anthropic/index.mjs +4 -4
- package/lib/anthropic/index.mjs.map +1 -1
- package/lib/gemini/index.cjs +364 -0
- package/lib/gemini/index.cjs.map +1 -0
- package/lib/gemini/index.d.ts +60 -0
- package/lib/gemini/index.mjs +357 -0
- package/lib/gemini/index.mjs.map +1 -0
- package/lib/index.cjs +445 -39
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.ts +23 -11
- package/lib/index.mjs +445 -39
- package/lib/index.mjs.map +1 -1
- package/lib/langchain/index.cjs.map +1 -1
- package/lib/langchain/index.mjs.map +1 -1
- package/lib/openai/index.cjs +226 -4
- package/lib/openai/index.cjs.map +1 -1
- package/lib/openai/index.d.ts +16 -4
- package/lib/openai/index.mjs +226 -5
- package/lib/openai/index.mjs.map +1 -1
- package/lib/vercel/index.cjs +5 -5
- package/lib/vercel/index.cjs.map +1 -1
- package/lib/vercel/index.mjs +5 -5
- package/lib/vercel/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/anthropic/index.ts +4 -4
- package/src/gemini/index.ts +4 -4
- package/src/openai/azure.ts +287 -33
- package/src/openai/index.ts +280 -6
- package/src/utils.ts +3 -2
- package/src/vercel/middleware.ts +7 -7
- package/tests/gemini.test.ts +31 -0
- package/tests/openai.test.ts +124 -48
package/src/openai/azure.ts
CHANGED
|
@@ -2,14 +2,18 @@ import OpenAIOrignal, { AzureOpenAI } from 'openai'
|
|
|
2
2
|
import { PostHog } from 'posthog-node'
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid'
|
|
4
4
|
import { formatResponseOpenAI, MonitoringParams, sendEventToPosthog } from '../utils'
|
|
5
|
+
import type { APIPromise } from 'openai'
|
|
6
|
+
import type { Stream } from 'openai/streaming'
|
|
7
|
+
import type { ParsedResponse } from 'openai/resources/responses/responses'
|
|
5
8
|
|
|
6
9
|
type ChatCompletion = OpenAIOrignal.ChatCompletion
|
|
7
10
|
type ChatCompletionChunk = OpenAIOrignal.ChatCompletionChunk
|
|
8
11
|
type ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams
|
|
9
12
|
type ChatCompletionCreateParamsNonStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsNonStreaming
|
|
10
13
|
type ChatCompletionCreateParamsStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsStreaming
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
type ResponsesCreateParamsBase = OpenAIOrignal.Responses.ResponseCreateParams
|
|
15
|
+
type ResponsesCreateParamsNonStreaming = OpenAIOrignal.Responses.ResponseCreateParamsNonStreaming
|
|
16
|
+
type ResponsesCreateParamsStreaming = OpenAIOrignal.Responses.ResponseCreateParamsStreaming
|
|
13
17
|
|
|
14
18
|
interface MonitoringOpenAIConfig {
|
|
15
19
|
apiKey: string
|
|
@@ -17,6 +21,8 @@ interface MonitoringOpenAIConfig {
|
|
|
17
21
|
baseURL?: string
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
type RequestOptions = Record<string, any>
|
|
25
|
+
|
|
20
26
|
export class PostHogAzureOpenAI extends AzureOpenAI {
|
|
21
27
|
private readonly phClient: PostHog
|
|
22
28
|
public chat: WrappedChat
|
|
@@ -82,32 +88,30 @@ export class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
82
88
|
|
|
83
89
|
const traceId = posthogTraceId ?? uuidv4()
|
|
84
90
|
const startTime = Date.now()
|
|
91
|
+
|
|
85
92
|
const parentPromise = super.create(openAIParams, options)
|
|
86
93
|
|
|
87
94
|
if (openAIParams.stream) {
|
|
88
95
|
return parentPromise.then((value) => {
|
|
89
|
-
let accumulatedContent = ''
|
|
90
|
-
let usage: {
|
|
91
|
-
inputTokens: number
|
|
92
|
-
outputTokens: number
|
|
93
|
-
reasoningTokens?: number
|
|
94
|
-
cacheReadInputTokens?: number
|
|
95
|
-
} = {
|
|
96
|
-
inputTokens: 0,
|
|
97
|
-
outputTokens: 0,
|
|
98
|
-
}
|
|
99
|
-
let model = openAIParams.model
|
|
100
96
|
if ('tee' in value) {
|
|
101
97
|
const [stream1, stream2] = value.tee()
|
|
102
98
|
;(async () => {
|
|
103
99
|
try {
|
|
100
|
+
let accumulatedContent = ''
|
|
101
|
+
let usage: {
|
|
102
|
+
inputTokens?: number
|
|
103
|
+
outputTokens?: number
|
|
104
|
+
reasoningTokens?: number
|
|
105
|
+
cacheReadInputTokens?: number
|
|
106
|
+
} = {
|
|
107
|
+
inputTokens: 0,
|
|
108
|
+
outputTokens: 0,
|
|
109
|
+
}
|
|
110
|
+
|
|
104
111
|
for await (const chunk of stream1) {
|
|
105
112
|
const delta = chunk?.choices?.[0]?.delta?.content ?? ''
|
|
106
113
|
accumulatedContent += delta
|
|
107
114
|
if (chunk.usage) {
|
|
108
|
-
if (chunk.model != model) {
|
|
109
|
-
model = chunk.model
|
|
110
|
-
}
|
|
111
115
|
usage = {
|
|
112
116
|
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
113
117
|
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
@@ -116,12 +120,13 @@ export class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
}
|
|
123
|
+
|
|
119
124
|
const latency = (Date.now() - startTime) / 1000
|
|
120
125
|
await sendEventToPosthog({
|
|
121
126
|
client: this.phClient,
|
|
122
|
-
distinctId: posthogDistinctId
|
|
127
|
+
distinctId: posthogDistinctId,
|
|
123
128
|
traceId,
|
|
124
|
-
model,
|
|
129
|
+
model: openAIParams.model,
|
|
125
130
|
provider: 'azure',
|
|
126
131
|
input: openAIParams.messages,
|
|
127
132
|
output: [{ content: accumulatedContent, role: 'assistant' }],
|
|
@@ -133,23 +138,19 @@ export class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
133
138
|
captureImmediate: posthogCaptureImmediate,
|
|
134
139
|
})
|
|
135
140
|
} catch (error: any) {
|
|
136
|
-
// error handling
|
|
137
141
|
await sendEventToPosthog({
|
|
138
142
|
client: this.phClient,
|
|
139
|
-
distinctId: posthogDistinctId
|
|
143
|
+
distinctId: posthogDistinctId,
|
|
140
144
|
traceId,
|
|
141
|
-
model,
|
|
145
|
+
model: openAIParams.model,
|
|
142
146
|
provider: 'azure',
|
|
143
147
|
input: openAIParams.messages,
|
|
144
|
-
output:
|
|
148
|
+
output: [],
|
|
145
149
|
latency: 0,
|
|
146
150
|
baseURL: (this as any).baseURL ?? '',
|
|
147
151
|
params: body,
|
|
148
152
|
httpStatus: error?.status ? error.status : 500,
|
|
149
|
-
usage: {
|
|
150
|
-
inputTokens: 0,
|
|
151
|
-
outputTokens: 0,
|
|
152
|
-
},
|
|
153
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
153
154
|
isError: true,
|
|
154
155
|
error: JSON.stringify(error),
|
|
155
156
|
captureImmediate: posthogCaptureImmediate,
|
|
@@ -167,15 +168,11 @@ export class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
167
168
|
async (result) => {
|
|
168
169
|
if ('choices' in result) {
|
|
169
170
|
const latency = (Date.now() - startTime) / 1000
|
|
170
|
-
let model = openAIParams.model
|
|
171
|
-
if (result.model != model) {
|
|
172
|
-
model = result.model
|
|
173
|
-
}
|
|
174
171
|
await sendEventToPosthog({
|
|
175
172
|
client: this.phClient,
|
|
176
|
-
distinctId: posthogDistinctId
|
|
173
|
+
distinctId: posthogDistinctId,
|
|
177
174
|
traceId,
|
|
178
|
-
model,
|
|
175
|
+
model: openAIParams.model,
|
|
179
176
|
provider: 'azure',
|
|
180
177
|
input: openAIParams.messages,
|
|
181
178
|
output: formatResponseOpenAI(result),
|
|
@@ -197,7 +194,7 @@ export class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
197
194
|
async (error: any) => {
|
|
198
195
|
await sendEventToPosthog({
|
|
199
196
|
client: this.phClient,
|
|
200
|
-
distinctId: posthogDistinctId
|
|
197
|
+
distinctId: posthogDistinctId,
|
|
201
198
|
traceId,
|
|
202
199
|
model: openAIParams.model,
|
|
203
200
|
provider: 'azure',
|
|
@@ -224,4 +221,261 @@ export class WrappedCompletions extends AzureOpenAI.Chat.Completions {
|
|
|
224
221
|
}
|
|
225
222
|
}
|
|
226
223
|
|
|
224
|
+
export class WrappedResponses extends AzureOpenAI.Responses {
|
|
225
|
+
private readonly phClient: PostHog
|
|
226
|
+
|
|
227
|
+
constructor(client: AzureOpenAI, phClient: PostHog) {
|
|
228
|
+
super(client)
|
|
229
|
+
this.phClient = phClient
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// --- Overload #1: Non-streaming
|
|
233
|
+
public create(
|
|
234
|
+
body: ResponsesCreateParamsNonStreaming & MonitoringParams,
|
|
235
|
+
options?: RequestOptions
|
|
236
|
+
): APIPromise<OpenAIOrignal.Responses.Response>
|
|
237
|
+
|
|
238
|
+
// --- Overload #2: Streaming
|
|
239
|
+
public create(
|
|
240
|
+
body: ResponsesCreateParamsStreaming & MonitoringParams,
|
|
241
|
+
options?: RequestOptions
|
|
242
|
+
): APIPromise<Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>
|
|
243
|
+
|
|
244
|
+
// --- Overload #3: Generic base
|
|
245
|
+
public create(
|
|
246
|
+
body: ResponsesCreateParamsBase & MonitoringParams,
|
|
247
|
+
options?: RequestOptions
|
|
248
|
+
): APIPromise<OpenAIOrignal.Responses.Response | Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>
|
|
249
|
+
|
|
250
|
+
// --- Implementation Signature
|
|
251
|
+
public create(
|
|
252
|
+
body: ResponsesCreateParamsBase & MonitoringParams,
|
|
253
|
+
options?: RequestOptions
|
|
254
|
+
): APIPromise<OpenAIOrignal.Responses.Response | Stream<OpenAIOrignal.Responses.ResponseStreamEvent>> {
|
|
255
|
+
const {
|
|
256
|
+
posthogDistinctId,
|
|
257
|
+
posthogTraceId,
|
|
258
|
+
posthogProperties,
|
|
259
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
260
|
+
posthogPrivacyMode = false,
|
|
261
|
+
posthogGroups,
|
|
262
|
+
posthogCaptureImmediate,
|
|
263
|
+
...openAIParams
|
|
264
|
+
} = body
|
|
265
|
+
|
|
266
|
+
const traceId = posthogTraceId ?? uuidv4()
|
|
267
|
+
const startTime = Date.now()
|
|
268
|
+
|
|
269
|
+
const parentPromise = super.create(openAIParams, options)
|
|
270
|
+
|
|
271
|
+
if (openAIParams.stream) {
|
|
272
|
+
return parentPromise.then((value) => {
|
|
273
|
+
if ('tee' in value && typeof (value as any).tee === 'function') {
|
|
274
|
+
const [stream1, stream2] = (value as any).tee()
|
|
275
|
+
;(async () => {
|
|
276
|
+
try {
|
|
277
|
+
let finalContent: any[] = []
|
|
278
|
+
let usage: {
|
|
279
|
+
inputTokens?: number
|
|
280
|
+
outputTokens?: number
|
|
281
|
+
reasoningTokens?: number
|
|
282
|
+
cacheReadInputTokens?: number
|
|
283
|
+
} = {
|
|
284
|
+
inputTokens: 0,
|
|
285
|
+
outputTokens: 0,
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
for await (const chunk of stream1) {
|
|
289
|
+
if (
|
|
290
|
+
chunk.type === 'response.completed' &&
|
|
291
|
+
'response' in chunk &&
|
|
292
|
+
chunk.response?.output &&
|
|
293
|
+
chunk.response.output.length > 0
|
|
294
|
+
) {
|
|
295
|
+
finalContent = chunk.response.output
|
|
296
|
+
}
|
|
297
|
+
if ('usage' in chunk && chunk.usage) {
|
|
298
|
+
usage = {
|
|
299
|
+
inputTokens: chunk.usage.input_tokens ?? 0,
|
|
300
|
+
outputTokens: chunk.usage.output_tokens ?? 0,
|
|
301
|
+
reasoningTokens: chunk.usage.output_tokens_details?.reasoning_tokens ?? 0,
|
|
302
|
+
cacheReadInputTokens: chunk.usage.input_tokens_details?.cached_tokens ?? 0,
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const latency = (Date.now() - startTime) / 1000
|
|
308
|
+
await sendEventToPosthog({
|
|
309
|
+
client: this.phClient,
|
|
310
|
+
distinctId: posthogDistinctId,
|
|
311
|
+
traceId,
|
|
312
|
+
model: openAIParams.model,
|
|
313
|
+
provider: 'azure',
|
|
314
|
+
input: openAIParams.input,
|
|
315
|
+
output: finalContent,
|
|
316
|
+
latency,
|
|
317
|
+
baseURL: (this as any).baseURL ?? '',
|
|
318
|
+
params: body,
|
|
319
|
+
httpStatus: 200,
|
|
320
|
+
usage,
|
|
321
|
+
captureImmediate: posthogCaptureImmediate,
|
|
322
|
+
})
|
|
323
|
+
} catch (error: any) {
|
|
324
|
+
await sendEventToPosthog({
|
|
325
|
+
client: this.phClient,
|
|
326
|
+
distinctId: posthogDistinctId,
|
|
327
|
+
traceId,
|
|
328
|
+
model: openAIParams.model,
|
|
329
|
+
provider: 'azure',
|
|
330
|
+
input: openAIParams.input,
|
|
331
|
+
output: [],
|
|
332
|
+
latency: 0,
|
|
333
|
+
baseURL: (this as any).baseURL ?? '',
|
|
334
|
+
params: body,
|
|
335
|
+
httpStatus: error?.status ? error.status : 500,
|
|
336
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
337
|
+
isError: true,
|
|
338
|
+
error: JSON.stringify(error),
|
|
339
|
+
captureImmediate: posthogCaptureImmediate,
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
})()
|
|
343
|
+
|
|
344
|
+
return stream2
|
|
345
|
+
}
|
|
346
|
+
return value
|
|
347
|
+
}) as APIPromise<Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>
|
|
348
|
+
} else {
|
|
349
|
+
const wrappedPromise = parentPromise.then(
|
|
350
|
+
async (result) => {
|
|
351
|
+
if ('output' in result) {
|
|
352
|
+
const latency = (Date.now() - startTime) / 1000
|
|
353
|
+
await sendEventToPosthog({
|
|
354
|
+
client: this.phClient,
|
|
355
|
+
distinctId: posthogDistinctId,
|
|
356
|
+
traceId,
|
|
357
|
+
model: openAIParams.model,
|
|
358
|
+
provider: 'azure',
|
|
359
|
+
input: openAIParams.input,
|
|
360
|
+
output: result.output,
|
|
361
|
+
latency,
|
|
362
|
+
baseURL: (this as any).baseURL ?? '',
|
|
363
|
+
params: body,
|
|
364
|
+
httpStatus: 200,
|
|
365
|
+
usage: {
|
|
366
|
+
inputTokens: result.usage?.input_tokens ?? 0,
|
|
367
|
+
outputTokens: result.usage?.output_tokens ?? 0,
|
|
368
|
+
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
369
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
370
|
+
},
|
|
371
|
+
captureImmediate: posthogCaptureImmediate,
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
return result
|
|
375
|
+
},
|
|
376
|
+
async (error: any) => {
|
|
377
|
+
await sendEventToPosthog({
|
|
378
|
+
client: this.phClient,
|
|
379
|
+
distinctId: posthogDistinctId,
|
|
380
|
+
traceId,
|
|
381
|
+
model: openAIParams.model,
|
|
382
|
+
provider: 'azure',
|
|
383
|
+
input: openAIParams.input,
|
|
384
|
+
output: [],
|
|
385
|
+
latency: 0,
|
|
386
|
+
baseURL: (this as any).baseURL ?? '',
|
|
387
|
+
params: body,
|
|
388
|
+
httpStatus: error?.status ? error.status : 500,
|
|
389
|
+
usage: {
|
|
390
|
+
inputTokens: 0,
|
|
391
|
+
outputTokens: 0,
|
|
392
|
+
},
|
|
393
|
+
isError: true,
|
|
394
|
+
error: JSON.stringify(error),
|
|
395
|
+
captureImmediate: posthogCaptureImmediate,
|
|
396
|
+
})
|
|
397
|
+
throw error
|
|
398
|
+
}
|
|
399
|
+
) as APIPromise<OpenAIOrignal.Responses.Response>
|
|
400
|
+
|
|
401
|
+
return wrappedPromise
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
public parse<Params extends OpenAIOrignal.Responses.ResponseCreateParams, ParsedT = any>(
|
|
406
|
+
body: Params & MonitoringParams,
|
|
407
|
+
options?: RequestOptions
|
|
408
|
+
): APIPromise<ParsedResponse<ParsedT>> {
|
|
409
|
+
const {
|
|
410
|
+
posthogDistinctId,
|
|
411
|
+
posthogTraceId,
|
|
412
|
+
posthogProperties,
|
|
413
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
414
|
+
posthogPrivacyMode = false,
|
|
415
|
+
posthogGroups,
|
|
416
|
+
posthogCaptureImmediate,
|
|
417
|
+
...openAIParams
|
|
418
|
+
} = body
|
|
419
|
+
|
|
420
|
+
const traceId = posthogTraceId ?? uuidv4()
|
|
421
|
+
const startTime = Date.now()
|
|
422
|
+
|
|
423
|
+
const parentPromise = super.parse(openAIParams, options)
|
|
424
|
+
|
|
425
|
+
const wrappedPromise = parentPromise.then(
|
|
426
|
+
async (result) => {
|
|
427
|
+
const latency = (Date.now() - startTime) / 1000
|
|
428
|
+
await sendEventToPosthog({
|
|
429
|
+
client: this.phClient,
|
|
430
|
+
distinctId: posthogDistinctId,
|
|
431
|
+
traceId,
|
|
432
|
+
model: openAIParams.model,
|
|
433
|
+
provider: 'azure',
|
|
434
|
+
input: openAIParams.input,
|
|
435
|
+
output: result.output,
|
|
436
|
+
latency,
|
|
437
|
+
baseURL: (this as any).baseURL ?? '',
|
|
438
|
+
params: body,
|
|
439
|
+
httpStatus: 200,
|
|
440
|
+
usage: {
|
|
441
|
+
inputTokens: result.usage?.input_tokens ?? 0,
|
|
442
|
+
outputTokens: result.usage?.output_tokens ?? 0,
|
|
443
|
+
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
444
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
445
|
+
},
|
|
446
|
+
captureImmediate: posthogCaptureImmediate,
|
|
447
|
+
})
|
|
448
|
+
return result
|
|
449
|
+
},
|
|
450
|
+
async (error: any) => {
|
|
451
|
+
await sendEventToPosthog({
|
|
452
|
+
client: this.phClient,
|
|
453
|
+
distinctId: posthogDistinctId,
|
|
454
|
+
traceId,
|
|
455
|
+
model: openAIParams.model,
|
|
456
|
+
provider: 'azure',
|
|
457
|
+
input: openAIParams.input,
|
|
458
|
+
output: [],
|
|
459
|
+
latency: 0,
|
|
460
|
+
baseURL: (this as any).baseURL ?? '',
|
|
461
|
+
params: body,
|
|
462
|
+
httpStatus: error?.status ? error.status : 500,
|
|
463
|
+
usage: {
|
|
464
|
+
inputTokens: 0,
|
|
465
|
+
outputTokens: 0,
|
|
466
|
+
},
|
|
467
|
+
isError: true,
|
|
468
|
+
error: JSON.stringify(error),
|
|
469
|
+
captureImmediate: posthogCaptureImmediate,
|
|
470
|
+
})
|
|
471
|
+
throw error
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
return wrappedPromise as APIPromise<ParsedResponse<ParsedT>>
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
227
479
|
export default PostHogAzureOpenAI
|
|
480
|
+
|
|
481
|
+
export { PostHogAzureOpenAI as OpenAI }
|