@posthog/ai 2.0.1 → 2.1.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/README.md +10 -13
- package/lib/index.cjs.js +70 -40
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.esm.js +70 -40
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-ai/src/openai/index.d.ts +1 -1
- package/lib/posthog-ai/src/utils.d.ts +2 -6
- package/lib/posthog-ai/src/vercel/middleware.d.ts +2 -2
- package/package.json +1 -1
- package/src/openai/index.ts +19 -19
- package/src/utils.ts +4 -24
- package/src/vercel/middleware.ts +67 -21
package/README.md
CHANGED
|
@@ -14,25 +14,22 @@ npm install @posthog/ai
|
|
|
14
14
|
import { OpenAI } from '@posthog/ai'
|
|
15
15
|
import { PostHog } from 'posthog-node'
|
|
16
16
|
|
|
17
|
-
const phClient = new PostHog(
|
|
18
|
-
'<YOUR_PROJECT_API_KEY>',
|
|
19
|
-
{ host: 'https://us.i.posthog.com' }
|
|
20
|
-
);
|
|
17
|
+
const phClient = new PostHog('<YOUR_PROJECT_API_KEY>', { host: 'https://us.i.posthog.com' })
|
|
21
18
|
|
|
22
19
|
const client = new OpenAI({
|
|
23
20
|
apiKey: '<YOUR_OPENAI_API_KEY>',
|
|
24
21
|
posthog: phClient,
|
|
25
|
-
})
|
|
22
|
+
})
|
|
26
23
|
|
|
27
24
|
const completion = await client.chat.completions.create({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
})
|
|
25
|
+
model: 'gpt-3.5-turbo',
|
|
26
|
+
messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }],
|
|
27
|
+
posthogDistinctId: 'user_123', // optional
|
|
28
|
+
posthogTraceId: 'trace_123', // optional
|
|
29
|
+
posthogProperties: { conversation_id: 'abc123', paid: true }, //optional
|
|
30
|
+
posthogGroups: { company: 'company_id_in_your_db' }, // optional
|
|
31
|
+
posthogPrivacyMode: false, // optional
|
|
32
|
+
})
|
|
36
33
|
|
|
37
34
|
console.log(completion.choices[0].message.content)
|
|
38
35
|
|
package/lib/index.cjs.js
CHANGED
|
@@ -63,8 +63,8 @@ const sendEventToPosthog = ({
|
|
|
63
63
|
$ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),
|
|
64
64
|
$ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),
|
|
65
65
|
$ai_http_status: httpStatus,
|
|
66
|
-
$ai_input_tokens: usage.
|
|
67
|
-
$ai_output_tokens: usage.
|
|
66
|
+
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
67
|
+
$ai_output_tokens: usage.outputTokens ?? 0,
|
|
68
68
|
$ai_latency: latency,
|
|
69
69
|
$ai_trace_id: traceId,
|
|
70
70
|
$ai_base_url: baseURL,
|
|
@@ -120,8 +120,8 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
120
120
|
});
|
|
121
121
|
let accumulatedContent = '';
|
|
122
122
|
let usage = {
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
inputTokens: 0,
|
|
124
|
+
outputTokens: 0
|
|
125
125
|
};
|
|
126
126
|
if ('tee' in value) {
|
|
127
127
|
const openAIStream = value;
|
|
@@ -132,8 +132,8 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
132
132
|
accumulatedContent += delta;
|
|
133
133
|
if (chunk.usage) {
|
|
134
134
|
usage = {
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
136
|
+
outputTokens: chunk.usage.completion_tokens ?? 0
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
passThroughStream.write(chunk);
|
|
@@ -145,7 +145,7 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
145
145
|
traceId,
|
|
146
146
|
model: openAIParams.model,
|
|
147
147
|
provider: 'openai',
|
|
148
|
-
input:
|
|
148
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
149
149
|
output: [{
|
|
150
150
|
content: accumulatedContent,
|
|
151
151
|
role: 'assistant'
|
|
@@ -165,15 +165,15 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
165
165
|
traceId,
|
|
166
166
|
model: openAIParams.model,
|
|
167
167
|
provider: 'openai',
|
|
168
|
-
input:
|
|
168
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
169
169
|
output: [],
|
|
170
170
|
latency: 0,
|
|
171
171
|
baseURL: this.baseURL ?? '',
|
|
172
172
|
params: body,
|
|
173
173
|
httpStatus: 500,
|
|
174
174
|
usage: {
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
inputTokens: 0,
|
|
176
|
+
outputTokens: 0
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
179
|
passThroughStream.emit('error', error);
|
|
@@ -192,7 +192,7 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
192
192
|
traceId,
|
|
193
193
|
model: openAIParams.model,
|
|
194
194
|
provider: 'openai',
|
|
195
|
-
input:
|
|
195
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
196
196
|
output: [{
|
|
197
197
|
content: result.choices[0].message.content,
|
|
198
198
|
role: 'assistant'
|
|
@@ -202,8 +202,8 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
202
202
|
params: body,
|
|
203
203
|
httpStatus: 200,
|
|
204
204
|
usage: {
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
206
|
+
outputTokens: result.usage?.completion_tokens ?? 0
|
|
207
207
|
}
|
|
208
208
|
});
|
|
209
209
|
}
|
|
@@ -215,15 +215,15 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
215
215
|
traceId,
|
|
216
216
|
model: openAIParams.model,
|
|
217
217
|
provider: 'openai',
|
|
218
|
-
input:
|
|
218
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
219
219
|
output: [],
|
|
220
220
|
latency: 0,
|
|
221
221
|
baseURL: this.baseURL ?? '',
|
|
222
222
|
params: body,
|
|
223
223
|
httpStatus: 500,
|
|
224
224
|
usage: {
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
inputTokens: 0,
|
|
226
|
+
outputTokens: 0
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
throw error;
|
|
@@ -233,6 +233,36 @@ class WrappedCompletions extends OpenAIOrignal__default["default"].Chat.Completi
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
const mapVercelParams = params => {
|
|
237
|
+
return {
|
|
238
|
+
temperature: params.temperature,
|
|
239
|
+
max_tokens: params.maxTokens,
|
|
240
|
+
top_p: params.topP,
|
|
241
|
+
frequency_penalty: params.frequencyPenalty,
|
|
242
|
+
presence_penalty: params.presencePenalty,
|
|
243
|
+
stop: params.stopSequences,
|
|
244
|
+
stream: params.stream
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
const mapVercelPrompt = prompt => {
|
|
248
|
+
return prompt.map(p => {
|
|
249
|
+
let content = '';
|
|
250
|
+
if (Array.isArray(p.content)) {
|
|
251
|
+
content = p.content.map(c => {
|
|
252
|
+
if (c.type === 'text') {
|
|
253
|
+
return c.text;
|
|
254
|
+
}
|
|
255
|
+
return '';
|
|
256
|
+
}).join('');
|
|
257
|
+
} else {
|
|
258
|
+
content = p.content;
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
role: p.role,
|
|
262
|
+
content
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
};
|
|
236
266
|
const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
237
267
|
const middleware = {
|
|
238
268
|
wrapGenerate: async ({
|
|
@@ -240,6 +270,10 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
240
270
|
params
|
|
241
271
|
}) => {
|
|
242
272
|
const startTime = Date.now();
|
|
273
|
+
let mergedParams = {
|
|
274
|
+
...options,
|
|
275
|
+
...mapVercelParams(params)
|
|
276
|
+
};
|
|
243
277
|
try {
|
|
244
278
|
const result = await doGenerate();
|
|
245
279
|
const latency = (Date.now() - startTime) / 1000;
|
|
@@ -249,20 +283,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
249
283
|
traceId: options.posthogTraceId,
|
|
250
284
|
model: model.modelId,
|
|
251
285
|
provider: 'vercel',
|
|
252
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
286
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
253
287
|
output: [{
|
|
254
288
|
content: result.text,
|
|
255
289
|
role: 'assistant'
|
|
256
290
|
}],
|
|
257
291
|
latency,
|
|
258
292
|
baseURL: '',
|
|
259
|
-
params:
|
|
260
|
-
posthog_properties: options
|
|
261
|
-
},
|
|
293
|
+
params: mergedParams,
|
|
262
294
|
httpStatus: 200,
|
|
263
295
|
usage: {
|
|
264
|
-
|
|
265
|
-
|
|
296
|
+
inputTokens: result.usage.promptTokens,
|
|
297
|
+
outputTokens: result.usage.completionTokens
|
|
266
298
|
}
|
|
267
299
|
});
|
|
268
300
|
return result;
|
|
@@ -273,17 +305,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
273
305
|
traceId: options.posthogTraceId,
|
|
274
306
|
model: model.modelId,
|
|
275
307
|
provider: 'vercel',
|
|
276
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
308
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
277
309
|
output: [],
|
|
278
310
|
latency: 0,
|
|
279
311
|
baseURL: '',
|
|
280
|
-
params:
|
|
281
|
-
posthog_properties: options
|
|
282
|
-
},
|
|
312
|
+
params: mergedParams,
|
|
283
313
|
httpStatus: 500,
|
|
284
314
|
usage: {
|
|
285
|
-
|
|
286
|
-
|
|
315
|
+
inputTokens: 0,
|
|
316
|
+
outputTokens: 0
|
|
287
317
|
}
|
|
288
318
|
});
|
|
289
319
|
throw error;
|
|
@@ -296,6 +326,10 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
296
326
|
const startTime = Date.now();
|
|
297
327
|
let generatedText = '';
|
|
298
328
|
let usage = {};
|
|
329
|
+
let mergedParams = {
|
|
330
|
+
...options,
|
|
331
|
+
...mapVercelParams(params)
|
|
332
|
+
};
|
|
299
333
|
try {
|
|
300
334
|
const {
|
|
301
335
|
stream,
|
|
@@ -308,8 +342,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
308
342
|
}
|
|
309
343
|
if (chunk.type === 'finish') {
|
|
310
344
|
usage = {
|
|
311
|
-
|
|
312
|
-
|
|
345
|
+
inputTokens: chunk.usage?.promptTokens,
|
|
346
|
+
outputTokens: chunk.usage?.completionTokens
|
|
313
347
|
};
|
|
314
348
|
}
|
|
315
349
|
controller.enqueue(chunk);
|
|
@@ -322,16 +356,14 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
322
356
|
traceId: options.posthogTraceId,
|
|
323
357
|
model: model.modelId,
|
|
324
358
|
provider: 'vercel',
|
|
325
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
359
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
326
360
|
output: [{
|
|
327
361
|
content: generatedText,
|
|
328
362
|
role: 'assistant'
|
|
329
363
|
}],
|
|
330
364
|
latency,
|
|
331
365
|
baseURL: '',
|
|
332
|
-
params:
|
|
333
|
-
posthog_properties: options
|
|
334
|
-
},
|
|
366
|
+
params: mergedParams,
|
|
335
367
|
httpStatus: 200,
|
|
336
368
|
usage
|
|
337
369
|
});
|
|
@@ -348,17 +380,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
348
380
|
traceId: options.posthogTraceId,
|
|
349
381
|
model: model.modelId,
|
|
350
382
|
provider: 'vercel',
|
|
351
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
383
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
352
384
|
output: [],
|
|
353
385
|
latency: 0,
|
|
354
386
|
baseURL: '',
|
|
355
|
-
params:
|
|
356
|
-
posthog_properties: options
|
|
357
|
-
},
|
|
387
|
+
params: mergedParams,
|
|
358
388
|
httpStatus: 500,
|
|
359
389
|
usage: {
|
|
360
|
-
|
|
361
|
-
|
|
390
|
+
inputTokens: 0,
|
|
391
|
+
outputTokens: 0
|
|
362
392
|
}
|
|
363
393
|
});
|
|
364
394
|
throw error;
|
package/lib/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/utils.ts","../src/openai/index.ts","../src/vercel/middleware.ts"],"sourcesContent":["import { PostHog } from 'posthog-node'\nimport OpenAIOrignal from 'openai'\n\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\n\nexport interface MonitoringParams {\n posthogDistinctId?: string\n posthogTraceId?: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: Record<string, any>\n}\n\nexport const getModelParams = (params: ChatCompletionCreateParamsBase & MonitoringParams): Record<string, any> => {\n const modelParams: Record<string, any> = {}\n const paramKeys = [\n 'temperature',\n 'max_tokens',\n 'max_completion_tokens',\n 'top_p',\n 'frequency_penalty',\n 'presence_penalty',\n 'n',\n 'stop',\n 'stream',\n 'streaming',\n ] as const\n\n for (const key of paramKeys) {\n if (key in params && (params as any)[key] !== undefined) {\n modelParams[key] = (params as any)[key]\n }\n }\n return modelParams\n}\n\nexport const getUsage = (response: any, provider: string): { input_tokens: number; output_tokens: number } => {\n if (!response?.usage) {\n return { input_tokens: 0, output_tokens: 0 }\n }\n\n if (provider === 'anthropic') {\n return {\n input_tokens: response.usage.input_tokens ?? 0,\n output_tokens: response.usage.output_tokens ?? 0,\n }\n } else if (provider === 'openai') {\n return {\n input_tokens: response.usage.prompt_tokens ?? 0,\n output_tokens: response.usage.completion_tokens ?? 0,\n }\n }\n\n return { input_tokens: 0, output_tokens: 0 }\n}\n\n/**\n * Helper to format responses (non-streaming) for consumption, mirroring Python's openai vs. anthropic approach.\n */\nexport const formatResponse = (response: any, provider: string): Array<{ role: string; content: string }> => {\n if (!response) {\n return []\n }\n if (provider === 'anthropic') {\n return formatResponseAnthropic(response)\n } else if (provider === 'openai') {\n return formatResponseOpenAI(response)\n }\n return []\n}\n\nexport const formatResponseAnthropic = (response: any): Array<{ role: string; content: string }> => {\n // Example approach if \"response.content\" holds array of text segments, etc.\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.content ?? []) {\n if (choice?.text) {\n output.push({\n role: 'assistant',\n content: choice.text,\n })\n }\n }\n return output\n}\n\nexport const formatResponseOpenAI = (response: any): Array<{ role: string; content: string }> => {\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.choices ?? []) {\n if (choice.message?.content) {\n output.push({\n role: choice.message.role,\n content: choice.message.content,\n })\n }\n }\n return output\n}\n\nexport const mergeSystemPrompt = (params: ChatCompletionCreateParamsBase & MonitoringParams, provider: string): any => {\n if (provider !== 'anthropic') {\n return params.messages\n }\n const messages = params.messages || []\n if (!(params as any).system) {\n return messages\n }\n const systemMessage = (params as any).system\n return [{ role: 'system', content: systemMessage }, ...messages]\n}\n\nexport const withPrivacyMode = (client: PostHog, privacyMode: boolean, input: any): any => {\n return (client as any).privacy_mode || privacyMode ? null : input\n}\n\nexport type SendEventToPosthogParams = {\n client: PostHog\n distinctId?: string\n traceId: string\n model: string\n provider: string\n input: any\n output: any\n latency: number\n baseURL: string\n httpStatus: number\n usage?: { input_tokens?: number; output_tokens?: number }\n params: ChatCompletionCreateParamsBase & MonitoringParams\n}\n\nexport const sendEventToPosthog = ({\n client,\n distinctId,\n traceId,\n model,\n provider,\n input,\n output,\n latency,\n baseURL,\n params,\n httpStatus = 200,\n usage = {},\n}: SendEventToPosthogParams): void => {\n if (client.capture) {\n client.capture({\n distinctId: distinctId ?? traceId,\n event: '$ai_generation',\n properties: {\n $ai_provider: provider,\n $ai_model: model,\n $ai_model_parameters: getModelParams(params),\n $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),\n $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),\n $ai_http_status: httpStatus,\n $ai_input_tokens: usage.input_tokens ?? 0,\n $ai_output_tokens: usage.output_tokens ?? 0,\n $ai_latency: latency,\n $ai_trace_id: traceId,\n $ai_base_url: baseURL,\n ...params.posthogProperties,\n ...(distinctId ? {} : { $process_person_profile: false }),\n },\n groups: params.posthogGroups,\n })\n }\n}\n","import OpenAIOrignal from 'openai'\nimport { PostHog } from 'posthog-node'\nimport { v4 as uuidv4 } from 'uuid'\nimport { PassThrough } from 'stream'\nimport { mergeSystemPrompt, MonitoringParams, sendEventToPosthog } from '../utils'\n\ntype ChatCompletion = OpenAIOrignal.ChatCompletion\ntype ChatCompletionChunk = OpenAIOrignal.ChatCompletionChunk\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\ntype ChatCompletionCreateParamsNonStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsNonStreaming\ntype ChatCompletionCreateParamsStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsStreaming\nimport type { APIPromise, RequestOptions } from 'openai/core'\nimport type { Stream } from 'openai/streaming'\n\ninterface MonitoringOpenAIConfig {\n apiKey: string\n posthog: PostHog\n baseURL?: string\n}\n\nexport class PostHogOpenAI extends OpenAIOrignal {\n private readonly phClient: PostHog\n\n constructor(config: MonitoringOpenAIConfig) {\n const { posthog, ...openAIConfig } = config\n super(openAIConfig)\n this.phClient = posthog\n this.chat = new WrappedChat(this, this.phClient)\n }\n\n public chat: WrappedChat\n}\n\nexport class WrappedChat extends OpenAIOrignal.Chat {\n constructor(parentClient: PostHogOpenAI, phClient: PostHog) {\n super(parentClient)\n this.completions = new WrappedCompletions(parentClient, phClient)\n }\n\n public completions: WrappedCompletions\n}\n\nexport class WrappedCompletions extends OpenAIOrignal.Chat.Completions {\n private readonly phClient: PostHog\n\n constructor(client: OpenAIOrignal, phClient: PostHog) {\n super(client)\n this.phClient = phClient\n }\n\n // --- Overload #1: Non-streaming\n public create(\n body: ChatCompletionCreateParamsNonStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion>\n\n // --- Overload #2: Streaming\n public create(\n body: ChatCompletionCreateParamsStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<Stream<ChatCompletionChunk>>\n\n // --- Overload #3: Generic base\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>>\n\n // --- Implementation Signature\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const {\n posthogDistinctId,\n posthogTraceId,\n posthogProperties,\n posthogPrivacyMode = false,\n posthogGroups,\n ...openAIParams\n } = body\n\n const traceId = posthogTraceId ?? uuidv4()\n const startTime = Date.now()\n\n const parentPromise = super.create(openAIParams, options)\n\n if (openAIParams.stream) {\n return parentPromise.then((value) => {\n const passThroughStream = new PassThrough({ objectMode: true })\n let accumulatedContent = ''\n let usage: { input_tokens: number; output_tokens: number } = {\n input_tokens: 0,\n output_tokens: 0,\n }\n if ('tee' in value) {\n const openAIStream = value\n ;(async () => {\n try {\n for await (const chunk of openAIStream) {\n const delta = chunk?.choices?.[0]?.delta?.content ?? ''\n accumulatedContent += delta\n if (chunk.usage) {\n usage = {\n input_tokens: chunk.usage.prompt_tokens ?? 0,\n output_tokens: chunk.usage.completion_tokens ?? 0,\n }\n }\n passThroughStream.write(chunk)\n }\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: accumulatedContent, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage,\n })\n passThroughStream.end()\n } catch (error) {\n // error handling\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n passThroughStream.emit('error', error)\n }\n })()\n }\n return passThroughStream as unknown as Stream<ChatCompletionChunk>\n }) as APIPromise<Stream<ChatCompletionChunk>>\n } else {\n const wrappedPromise = parentPromise.then(\n (result) => {\n if ('choices' in result) {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: result.choices[0].message.content, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage: {\n input_tokens: result.usage?.prompt_tokens ?? 0,\n output_tokens: result.usage?.completion_tokens ?? 0,\n },\n })\n }\n return result\n },\n (error) => {\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n throw error\n }\n ) as APIPromise<ChatCompletion>\n\n return wrappedPromise\n }\n }\n}\n\nexport default PostHogOpenAI\n","import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'\nimport type {\n LanguageModelV1,\n Experimental_LanguageModelV1Middleware as LanguageModelV1Middleware,\n LanguageModelV1StreamPart,\n} from 'ai'\nimport { v4 as uuidv4 } from 'uuid'\nimport type { PostHog } from 'posthog-node'\nimport { sendEventToPosthog } from '../utils'\n\ninterface CreateInstrumentationMiddlewareOptions {\n posthogDistinctId?: string\n posthogTraceId: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: string[]\n}\n\nexport const createInstrumentationMiddleware = (\n phClient: PostHog,\n model: LanguageModelV1,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1Middleware => {\n const middleware: LanguageModelV1Middleware = {\n wrapGenerate: async ({ doGenerate, params }) => {\n const startTime = Date.now()\n\n try {\n const result = await doGenerate()\n const latency = (Date.now() - startTime) / 1000\n\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [{ content: result.text, role: 'assistant' }],\n latency,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 200,\n usage: {\n input_tokens: result.usage.promptTokens,\n output_tokens: result.usage.completionTokens,\n },\n })\n\n return result\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [],\n latency: 0,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n throw error\n }\n },\n\n wrapStream: async ({ doStream, params }) => {\n const startTime = Date.now()\n let generatedText = ''\n let usage: { input_tokens?: number; output_tokens?: number } = {}\n\n try {\n const { stream, ...rest } = await doStream()\n\n const transformStream = new TransformStream<LanguageModelV1StreamPart, LanguageModelV1StreamPart>({\n transform(chunk, controller) {\n if (chunk.type === 'text-delta') {\n generatedText += chunk.textDelta\n }\n if (chunk.type === 'finish') {\n usage = {\n input_tokens: chunk.usage?.promptTokens,\n output_tokens: chunk.usage?.completionTokens,\n }\n }\n controller.enqueue(chunk)\n },\n\n flush() {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [{ content: generatedText, role: 'assistant' }],\n latency,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 200,\n usage,\n })\n },\n })\n\n return {\n stream: stream.pipeThrough(transformStream),\n ...rest,\n }\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [],\n latency: 0,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n throw error\n }\n },\n }\n\n return middleware\n}\n\nexport const wrapVercelLanguageModel = (\n model: LanguageModelV1,\n phClient: PostHog,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1 => {\n const traceId = options.posthogTraceId ?? uuidv4()\n const middleware = createInstrumentationMiddleware(phClient, model, {\n ...options,\n posthogTraceId: traceId,\n posthogDistinctId: options.posthogDistinctId ?? traceId,\n })\n\n const wrappedModel = wrapLanguageModel({\n model,\n middleware,\n })\n\n return wrappedModel\n}\n"],"names":["getModelParams","params","modelParams","paramKeys","key","undefined","mergeSystemPrompt","provider","messages","system","systemMessage","role","content","withPrivacyMode","client","privacyMode","input","privacy_mode","sendEventToPosthog","distinctId","traceId","model","output","latency","baseURL","httpStatus","usage","capture","event","properties","$ai_provider","$ai_model","$ai_model_parameters","$ai_input","posthogPrivacyMode","$ai_output_choices","$ai_http_status","$ai_input_tokens","input_tokens","$ai_output_tokens","output_tokens","$ai_latency","$ai_trace_id","$ai_base_url","posthogProperties","$process_person_profile","groups","posthogGroups","PostHogOpenAI","OpenAIOrignal","constructor","config","posthog","openAIConfig","phClient","chat","WrappedChat","Chat","parentClient","completions","WrappedCompletions","Completions","create","body","options","posthogDistinctId","posthogTraceId","openAIParams","uuidv4","startTime","Date","now","parentPromise","stream","then","value","passThroughStream","PassThrough","objectMode","accumulatedContent","openAIStream","chunk","delta","choices","prompt_tokens","completion_tokens","write","end","error","emit","wrappedPromise","result","message","createInstrumentationMiddleware","middleware","wrapGenerate","doGenerate","modelId","prompt","text","posthog_properties","promptTokens","completionTokens","wrapStream","doStream","generatedText","rest","transformStream","TransformStream","transform","controller","type","textDelta","enqueue","flush","pipeThrough","wrapVercelLanguageModel","wrappedModel","wrapLanguageModel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/utils.ts","../src/openai/index.ts","../src/vercel/middleware.ts"],"sourcesContent":["import { PostHog } from 'posthog-node'\nimport OpenAIOrignal from 'openai'\n\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\n\nexport interface MonitoringParams {\n posthogDistinctId?: string\n posthogTraceId?: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: Record<string, any>\n}\n\nexport const getModelParams = (params: ChatCompletionCreateParamsBase & MonitoringParams): Record<string, any> => {\n const modelParams: Record<string, any> = {}\n const paramKeys = [\n 'temperature',\n 'max_tokens',\n 'max_completion_tokens',\n 'top_p',\n 'frequency_penalty',\n 'presence_penalty',\n 'n',\n 'stop',\n 'stream',\n 'streaming',\n ] as const\n\n for (const key of paramKeys) {\n if (key in params && (params as any)[key] !== undefined) {\n modelParams[key] = (params as any)[key]\n }\n }\n return modelParams\n}\n\n/**\n * Helper to format responses (non-streaming) for consumption, mirroring Python's openai vs. anthropic approach.\n */\nexport const formatResponse = (response: any, provider: string): Array<{ role: string; content: string }> => {\n if (!response) {\n return []\n }\n if (provider === 'anthropic') {\n return formatResponseAnthropic(response)\n } else if (provider === 'openai') {\n return formatResponseOpenAI(response)\n }\n return []\n}\n\nexport const formatResponseAnthropic = (response: any): Array<{ role: string; content: string }> => {\n // Example approach if \"response.content\" holds array of text segments, etc.\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.content ?? []) {\n if (choice?.text) {\n output.push({\n role: 'assistant',\n content: choice.text,\n })\n }\n }\n return output\n}\n\nexport const formatResponseOpenAI = (response: any): Array<{ role: string; content: string }> => {\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.choices ?? []) {\n if (choice.message?.content) {\n output.push({\n role: choice.message.role,\n content: choice.message.content,\n })\n }\n }\n return output\n}\n\nexport const mergeSystemPrompt = (params: ChatCompletionCreateParamsBase & MonitoringParams, provider: string): any => {\n if (provider !== 'anthropic') {\n return params.messages\n }\n const messages = params.messages || []\n if (!(params as any).system) {\n return messages\n }\n const systemMessage = (params as any).system\n return [{ role: 'system', content: systemMessage }, ...messages]\n}\n\nexport const withPrivacyMode = (client: PostHog, privacyMode: boolean, input: any): any => {\n return (client as any).privacy_mode || privacyMode ? null : input\n}\n\nexport type SendEventToPosthogParams = {\n client: PostHog\n distinctId?: string\n traceId: string\n model: string\n provider: string\n input: any\n output: any\n latency: number\n baseURL: string\n httpStatus: number\n usage?: { inputTokens?: number; outputTokens?: number }\n params: ChatCompletionCreateParamsBase & MonitoringParams\n}\n\nexport const sendEventToPosthog = ({\n client,\n distinctId,\n traceId,\n model,\n provider,\n input,\n output,\n latency,\n baseURL,\n params,\n httpStatus = 200,\n usage = {},\n}: SendEventToPosthogParams): void => {\n if (client.capture) {\n client.capture({\n distinctId: distinctId ?? traceId,\n event: '$ai_generation',\n properties: {\n $ai_provider: provider,\n $ai_model: model,\n $ai_model_parameters: getModelParams(params),\n $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),\n $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),\n $ai_http_status: httpStatus,\n $ai_input_tokens: usage.inputTokens ?? 0,\n $ai_output_tokens: usage.outputTokens ?? 0,\n $ai_latency: latency,\n $ai_trace_id: traceId,\n $ai_base_url: baseURL,\n ...params.posthogProperties,\n ...(distinctId ? {} : { $process_person_profile: false }),\n },\n groups: params.posthogGroups,\n })\n }\n}","import OpenAIOrignal from 'openai'\nimport { PostHog } from 'posthog-node'\nimport { v4 as uuidv4 } from 'uuid'\nimport { PassThrough } from 'stream'\nimport { mergeSystemPrompt, MonitoringParams, sendEventToPosthog } from '../utils'\n\ntype ChatCompletion = OpenAIOrignal.ChatCompletion\ntype ChatCompletionChunk = OpenAIOrignal.ChatCompletionChunk\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\ntype ChatCompletionCreateParamsNonStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsNonStreaming\ntype ChatCompletionCreateParamsStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsStreaming\nimport type { APIPromise, RequestOptions } from 'openai/core'\nimport type { Stream } from 'openai/streaming'\n\ninterface MonitoringOpenAIConfig {\n apiKey: string\n posthog: PostHog\n baseURL?: string\n}\n\nexport class PostHogOpenAI extends OpenAIOrignal {\n private readonly phClient: PostHog\n public chat: WrappedChat\n\n constructor(config: MonitoringOpenAIConfig) {\n const { posthog, ...openAIConfig } = config\n super(openAIConfig)\n this.phClient = posthog\n this.chat = new WrappedChat(this, this.phClient)\n }\n}\n\nexport class WrappedChat extends OpenAIOrignal.Chat {\n constructor(parentClient: PostHogOpenAI, phClient: PostHog) {\n super(parentClient)\n this.completions = new WrappedCompletions(parentClient, phClient)\n }\n\n public completions: WrappedCompletions\n}\n\nexport class WrappedCompletions extends OpenAIOrignal.Chat.Completions {\n private readonly phClient: PostHog\n\n constructor(client: OpenAIOrignal, phClient: PostHog) {\n super(client)\n this.phClient = phClient\n }\n\n // --- Overload #1: Non-streaming\n public create(\n body: ChatCompletionCreateParamsNonStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion>\n\n // --- Overload #2: Streaming\n public create(\n body: ChatCompletionCreateParamsStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<Stream<ChatCompletionChunk>>\n\n // --- Overload #3: Generic base\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>>\n\n // --- Implementation Signature\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const {\n posthogDistinctId,\n posthogTraceId,\n posthogProperties,\n posthogPrivacyMode = false,\n posthogGroups,\n ...openAIParams\n } = body\n\n const traceId = posthogTraceId ?? uuidv4()\n const startTime = Date.now()\n\n const parentPromise = super.create(openAIParams, options)\n\n if (openAIParams.stream) {\n return parentPromise.then((value) => {\n const passThroughStream = new PassThrough({ objectMode: true })\n let accumulatedContent = ''\n let usage: { inputTokens: number; outputTokens: number } = {\n inputTokens: 0,\n outputTokens: 0,\n }\n if ('tee' in value) {\n const openAIStream = value;\n (async () => {\n try {\n for await (const chunk of openAIStream) {\n const delta = chunk?.choices?.[0]?.delta?.content ?? ''\n accumulatedContent += delta\n if (chunk.usage) {\n usage = {\n inputTokens: chunk.usage.prompt_tokens ?? 0,\n outputTokens: chunk.usage.completion_tokens ?? 0,\n }\n }\n passThroughStream.write(chunk)\n }\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: accumulatedContent, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage,\n })\n passThroughStream.end()\n } catch (error) {\n // error handling\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n passThroughStream.emit('error', error)\n }\n })()\n }\n return passThroughStream as unknown as Stream<ChatCompletionChunk>\n }) as APIPromise<Stream<ChatCompletionChunk>>\n } else {\n const wrappedPromise = parentPromise.then(\n (result) => {\n if ('choices' in result) {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: result.choices[0].message.content, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage: {\n inputTokens: result.usage?.prompt_tokens ?? 0,\n outputTokens: result.usage?.completion_tokens ?? 0,\n },\n })\n }\n return result\n },\n (error) => {\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n throw error\n }\n ) as APIPromise<ChatCompletion>\n\n return wrappedPromise\n }\n }\n\n}\n\nexport default PostHogOpenAI\n","import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'\nimport type {\n LanguageModelV1,\n Experimental_LanguageModelV1Middleware as LanguageModelV1Middleware,\n LanguageModelV1Prompt,\n LanguageModelV1StreamPart,\n} from 'ai'\nimport { v4 as uuidv4 } from 'uuid'\nimport { PostHog } from 'posthog-node'\nimport { sendEventToPosthog } from '../utils'\n\ninterface CreateInstrumentationMiddlewareOptions {\n posthogDistinctId?: string\n posthogTraceId: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: Record<string, any>\n}\n\ninterface PostHogInput {\n content: string\n role: string\n}\n\nconst mapVercelParams = (params: any): Record<string, any> => {\n return {\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n top_p: params.topP,\n frequency_penalty: params.frequencyPenalty,\n presence_penalty: params.presencePenalty,\n stop: params.stopSequences,\n stream: params.stream,\n }\n}\n\nconst mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {\n return prompt.map((p) => {\n let content = ''\n if (Array.isArray(p.content)) {\n content = p.content\n .map((c) => {\n if (c.type === 'text') {\n return c.text\n }\n return ''\n })\n .join('')\n } else {\n content = p.content\n }\n return {\n role: p.role,\n content,\n }\n })\n}\n\nexport const createInstrumentationMiddleware = (\n phClient: PostHog,\n model: LanguageModelV1,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1Middleware => {\n const middleware: LanguageModelV1Middleware = {\n wrapGenerate: async ({ doGenerate, params }) => {\n const startTime = Date.now()\n let mergedParams = {\n ...options,\n ...mapVercelParams(params),\n }\n try {\n const result = await doGenerate()\n const latency = (Date.now() - startTime) / 1000\n\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [{ content: result.text, role: 'assistant' }],\n latency,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 200,\n usage: {\n inputTokens: result.usage.promptTokens,\n outputTokens: result.usage.completionTokens,\n },\n })\n\n return result\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [],\n latency: 0,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n throw error\n }\n },\n\n wrapStream: async ({ doStream, params }) => {\n const startTime = Date.now()\n let generatedText = ''\n let usage: { inputTokens?: number; outputTokens?: number } = {}\n let mergedParams = {\n ...options,\n ...mapVercelParams(params),\n }\n try {\n const { stream, ...rest } = await doStream()\n\n const transformStream = new TransformStream<LanguageModelV1StreamPart, LanguageModelV1StreamPart>({\n transform(chunk, controller) {\n if (chunk.type === 'text-delta') {\n generatedText += chunk.textDelta\n }\n if (chunk.type === 'finish') {\n usage = {\n inputTokens: chunk.usage?.promptTokens,\n outputTokens: chunk.usage?.completionTokens,\n }\n }\n controller.enqueue(chunk)\n },\n\n flush() {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [{ content: generatedText, role: 'assistant' }],\n latency,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 200,\n usage,\n })\n },\n })\n\n return {\n stream: stream.pipeThrough(transformStream),\n ...rest,\n }\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [],\n latency: 0,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n throw error\n }\n },\n }\n\n return middleware\n}\n\nexport const wrapVercelLanguageModel = (\n model: LanguageModelV1,\n phClient: PostHog,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1 => {\n const traceId = options.posthogTraceId ?? uuidv4()\n const middleware = createInstrumentationMiddleware(phClient, model, {\n ...options,\n posthogTraceId: traceId,\n posthogDistinctId: options.posthogDistinctId ?? traceId,\n })\n\n const wrappedModel = wrapLanguageModel({\n model,\n middleware,\n })\n\n return wrappedModel\n}\n"],"names":["getModelParams","params","modelParams","paramKeys","key","undefined","mergeSystemPrompt","provider","messages","system","systemMessage","role","content","withPrivacyMode","client","privacyMode","input","privacy_mode","sendEventToPosthog","distinctId","traceId","model","output","latency","baseURL","httpStatus","usage","capture","event","properties","$ai_provider","$ai_model","$ai_model_parameters","$ai_input","posthogPrivacyMode","$ai_output_choices","$ai_http_status","$ai_input_tokens","inputTokens","$ai_output_tokens","outputTokens","$ai_latency","$ai_trace_id","$ai_base_url","posthogProperties","$process_person_profile","groups","posthogGroups","PostHogOpenAI","OpenAIOrignal","constructor","config","posthog","openAIConfig","phClient","chat","WrappedChat","Chat","parentClient","completions","WrappedCompletions","Completions","create","body","options","posthogDistinctId","posthogTraceId","openAIParams","uuidv4","startTime","Date","now","parentPromise","stream","then","value","passThroughStream","PassThrough","objectMode","accumulatedContent","openAIStream","chunk","delta","choices","prompt_tokens","completion_tokens","write","end","error","emit","wrappedPromise","result","message","mapVercelParams","temperature","max_tokens","maxTokens","top_p","topP","frequency_penalty","frequencyPenalty","presence_penalty","presencePenalty","stop","stopSequences","mapVercelPrompt","prompt","map","p","Array","isArray","c","type","text","join","createInstrumentationMiddleware","middleware","wrapGenerate","doGenerate","mergedParams","modelId","promptTokens","completionTokens","wrapStream","doStream","generatedText","rest","transformStream","TransformStream","transform","controller","textDelta","enqueue","flush","pipeThrough","wrapVercelLanguageModel","wrappedModel","wrapLanguageModel"],"mappings":";;;;;;;;;;;;;AAaO,MAAMA,cAAc,GAAIC,MAAyD,IAAyB;EAC/G,MAAMC,WAAW,GAAwB,EAAE,CAAA;EAC3C,MAAMC,SAAS,GAAG,CAChB,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,OAAO,EACP,mBAAmB,EACnB,kBAAkB,EAClB,GAAG,EACH,MAAM,EACN,QAAQ,EACR,WAAW,CACH,CAAA;AAEV,EAAA,KAAK,MAAMC,GAAG,IAAID,SAAS,EAAE;IAC3B,IAAIC,GAAG,IAAIH,MAAM,IAAKA,MAAc,CAACG,GAAG,CAAC,KAAKC,SAAS,EAAE;AACvDH,MAAAA,WAAW,CAACE,GAAG,CAAC,GAAIH,MAAc,CAACG,GAAG,CAAC,CAAA;AACxC,KAAA;AACF,GAAA;AACD,EAAA,OAAOF,WAAW,CAAA;AACpB,CAAC,CAAA;AA4CM,MAAMI,iBAAiB,GAAGA,CAACL,MAAyD,EAAEM,QAAgB,KAAS;EACpH,IAAIA,QAAQ,KAAK,WAAW,EAAE;IAC5B,OAAON,MAAM,CAACO,QAAQ,CAAA;AACvB,GAAA;AACD,EAAA,MAAMA,QAAQ,GAAGP,MAAM,CAACO,QAAQ,IAAI,EAAE,CAAA;AACtC,EAAA,IAAI,CAAEP,MAAc,CAACQ,MAAM,EAAE;AAC3B,IAAA,OAAOD,QAAQ,CAAA;AAChB,GAAA;AACD,EAAA,MAAME,aAAa,GAAIT,MAAc,CAACQ,MAAM,CAAA;AAC5C,EAAA,OAAO,CAAC;AAAEE,IAAAA,IAAI,EAAE,QAAQ;AAAEC,IAAAA,OAAO,EAAEF,aAAAA;GAAe,EAAE,GAAGF,QAAQ,CAAC,CAAA;AAClE,CAAC,CAAA;AAEM,MAAMK,eAAe,GAAGA,CAACC,MAAe,EAAEC,WAAoB,EAAEC,KAAU,KAAS;EACxF,OAAQF,MAAc,CAACG,YAAY,IAAIF,WAAW,GAAG,IAAI,GAAGC,KAAK,CAAA;AACnE,CAAC,CAAA;AAiBM,MAAME,kBAAkB,GAAGA,CAAC;EACjCJ,MAAM;EACNK,UAAU;EACVC,OAAO;EACPC,KAAK;EACLd,QAAQ;EACRS,KAAK;EACLM,MAAM;EACNC,OAAO;EACPC,OAAO;EACPvB,MAAM;AACNwB,EAAAA,UAAU,GAAG,GAAG;AAChBC,EAAAA,KAAK,GAAG,EAAE;AAAA,CACe,KAAU;EACnC,IAAIZ,MAAM,CAACa,OAAO,EAAE;IAClBb,MAAM,CAACa,OAAO,CAAC;MACbR,UAAU,EAAEA,UAAU,IAAIC,OAAO;AACjCQ,MAAAA,KAAK,EAAE,gBAAgB;AACvBC,MAAAA,UAAU,EAAE;AACVC,QAAAA,YAAY,EAAEvB,QAAQ;AACtBwB,QAAAA,SAAS,EAAEV,KAAK;AAChBW,QAAAA,oBAAoB,EAAEhC,cAAc,CAACC,MAAM,CAAC;AAC5CgC,QAAAA,SAAS,EAAEpB,eAAe,CAACC,MAAM,EAAEb,MAAM,CAACiC,kBAAkB,IAAI,KAAK,EAAElB,KAAK,CAAC;AAC7EmB,QAAAA,kBAAkB,EAAEtB,eAAe,CAACC,MAAM,EAAEb,MAAM,CAACiC,kBAAkB,IAAI,KAAK,EAAEZ,MAAM,CAAC;AACvFc,QAAAA,eAAe,EAAEX,UAAU;AAC3BY,QAAAA,gBAAgB,EAAEX,KAAK,CAACY,WAAW,IAAI,CAAC;AACxCC,QAAAA,iBAAiB,EAAEb,KAAK,CAACc,YAAY,IAAI,CAAC;AAC1CC,QAAAA,WAAW,EAAElB,OAAO;AACpBmB,QAAAA,YAAY,EAAEtB,OAAO;AACrBuB,QAAAA,YAAY,EAAEnB,OAAO;QACrB,GAAGvB,MAAM,CAAC2C,iBAAiB;AAC3B,QAAA,IAAIzB,UAAU,GAAG,EAAE,GAAG;AAAE0B,UAAAA,uBAAuB,EAAE,KAAA;SAAO,CAAA;OACzD;MACDC,MAAM,EAAE7C,MAAM,CAAC8C,aAAAA;AAChB,KAAA,CAAC,CAAA;AACH,GAAA;AACH,CAAC;;AC7HK,MAAOC,aAAc,SAAQC,iCAAa,CAAA;EAI9CC,WAAAA,CAAYC,MAA8B,EAAA;IACxC,MAAM;MAAEC,OAAO;MAAE,GAAGC,YAAAA;AAAc,KAAA,GAAGF,MAAM,CAAA;IAC3C,KAAK,CAACE,YAAY,CAAC,CAAA;IACnB,IAAI,CAACC,QAAQ,GAAGF,OAAO,CAAA;IACvB,IAAI,CAACG,IAAI,GAAG,IAAIC,WAAW,CAAC,IAAI,EAAE,IAAI,CAACF,QAAQ,CAAC,CAAA;AAClD,GAAA;AACD,CAAA;AAEY,MAAAE,WAAY,SAAQP,iCAAa,CAACQ,IAAI,CAAA;AACjDP,EAAAA,WAAYA,CAAAQ,YAA2B,EAAEJ,QAAiB,EAAA;IACxD,KAAK,CAACI,YAAY,CAAC,CAAA;IACnB,IAAI,CAACC,WAAW,GAAG,IAAIC,kBAAkB,CAACF,YAAY,EAAEJ,QAAQ,CAAC,CAAA;AACnE,GAAA;AAGD,CAAA;MAEYM,kBAAmB,SAAQX,iCAAa,CAACQ,IAAI,CAACI,WAAW,CAAA;AAGpEX,EAAAA,WAAYA,CAAApC,MAAqB,EAAEwC,QAAiB,EAAA;IAClD,KAAK,CAACxC,MAAM,CAAC,CAAA;IACb,IAAI,CAACwC,QAAQ,GAAGA,QAAQ,CAAA;AAC1B,GAAA;AAoBA;AACOQ,EAAAA,MAAMA,CACXC,IAAuD,EACvDC,OAAwB,EAAA;IAExB,MAAM;MACJC,iBAAiB;MACjBC,cAAc;MACdtB,iBAAiB;AACjBV,MAAAA,kBAAkB,GAAG,KAAK;MAC1Ba,aAAa;MACb,GAAGoB,YAAAA;AACJ,KAAA,GAAGJ,IAAI,CAAA;AAER,IAAA,MAAM3C,OAAO,GAAG8C,cAAc,IAAIE,OAAM,EAAE,CAAA;AAC1C,IAAA,MAAMC,SAAS,GAAGC,IAAI,CAACC,GAAG,EAAE,CAAA;IAE5B,MAAMC,aAAa,GAAG,KAAK,CAACV,MAAM,CAACK,YAAY,EAAEH,OAAO,CAAC,CAAA;IAEzD,IAAIG,YAAY,CAACM,MAAM,EAAE;AACvB,MAAA,OAAOD,aAAa,CAACE,IAAI,CAAEC,KAAK,IAAI;AAClC,QAAA,MAAMC,iBAAiB,GAAG,IAAIC,kBAAW,CAAC;AAAEC,UAAAA,UAAU,EAAE,IAAA;AAAM,SAAA,CAAC,CAAA;QAC/D,IAAIC,kBAAkB,GAAG,EAAE,CAAA;AAC3B,QAAA,IAAIrD,KAAK,GAAkD;AACzDY,UAAAA,WAAW,EAAE,CAAC;AACdE,UAAAA,YAAY,EAAE,CAAA;SACf,CAAA;QACD,IAAI,KAAK,IAAImC,KAAK,EAAE;UAClB,MAAMK,YAAY,GAAGL,KAAK,CAAA;AAC1B,UAAA,CAAC,YAAW;YACV,IAAI;AACF,cAAA,WAAW,MAAMM,KAAK,IAAID,YAAY,EAAE;AACtC,gBAAA,MAAME,KAAK,GAAGD,KAAK,EAAEE,OAAO,GAAG,CAAC,CAAC,EAAED,KAAK,EAAEtE,OAAO,IAAI,EAAE,CAAA;AACvDmE,gBAAAA,kBAAkB,IAAIG,KAAK,CAAA;gBAC3B,IAAID,KAAK,CAACvD,KAAK,EAAE;AACfA,kBAAAA,KAAK,GAAG;AACNY,oBAAAA,WAAW,EAAE2C,KAAK,CAACvD,KAAK,CAAC0D,aAAa,IAAI,CAAC;AAC3C5C,oBAAAA,YAAY,EAAEyC,KAAK,CAACvD,KAAK,CAAC2D,iBAAiB,IAAI,CAAA;mBAChD,CAAA;AACF,iBAAA;AACDT,gBAAAA,iBAAiB,CAACU,KAAK,CAACL,KAAK,CAAC,CAAA;AAC/B,eAAA;cACD,MAAM1D,OAAO,GAAG,CAAC+C,IAAI,CAACC,GAAG,EAAE,GAAGF,SAAS,IAAI,IAAI,CAAA;AAC/CnD,cAAAA,kBAAkB,CAAC;gBACjBJ,MAAM,EAAE,IAAI,CAACwC,QAAQ;gBACrBnC,UAAU,EAAE8C,iBAAiB,IAAI7C,OAAO;gBACxCA,OAAO;gBACPC,KAAK,EAAE8C,YAAY,CAAC9C,KAAK;AACzBd,gBAAAA,QAAQ,EAAE,QAAQ;AAClBS,gBAAAA,KAAK,EAAEV,iBAAiB,CAAC6D,YAAY,EAAE,QAAQ,CAAC;AAChD7C,gBAAAA,MAAM,EAAE,CAAC;AAAEV,kBAAAA,OAAO,EAAEmE,kBAAkB;AAAEpE,kBAAAA,IAAI,EAAE,WAAA;AAAW,iBAAE,CAAC;gBAC5DY,OAAO;AACPC,gBAAAA,OAAO,EAAG,IAAY,CAACA,OAAO,IAAI,EAAE;AACpCvB,gBAAAA,MAAM,EAAE8D,IAAI;AACZtC,gBAAAA,UAAU,EAAE,GAAG;AACfC,gBAAAA,KAAAA;AACD,eAAA,CAAC,CAAA;cACFkD,iBAAiB,CAACW,GAAG,EAAE,CAAA;aACxB,CAAC,OAAOC,KAAK,EAAE;AACd;AACAtE,cAAAA,kBAAkB,CAAC;gBACjBJ,MAAM,EAAE,IAAI,CAACwC,QAAQ;gBACrBnC,UAAU,EAAE8C,iBAAiB,IAAI7C,OAAO;gBACxCA,OAAO;gBACPC,KAAK,EAAE8C,YAAY,CAAC9C,KAAK;AACzBd,gBAAAA,QAAQ,EAAE,QAAQ;AAClBS,gBAAAA,KAAK,EAAEV,iBAAiB,CAAC6D,YAAY,EAAE,QAAQ,CAAC;AAChD7C,gBAAAA,MAAM,EAAE,EAAE;AACVC,gBAAAA,OAAO,EAAE,CAAC;AACVC,gBAAAA,OAAO,EAAG,IAAY,CAACA,OAAO,IAAI,EAAE;AACpCvB,gBAAAA,MAAM,EAAE8D,IAAI;AACZtC,gBAAAA,UAAU,EAAE,GAAG;AACfC,gBAAAA,KAAK,EAAE;AACLY,kBAAAA,WAAW,EAAE,CAAC;AACdE,kBAAAA,YAAY,EAAE,CAAA;AACf,iBAAA;AACF,eAAA,CAAC,CAAA;AACFoC,cAAAA,iBAAiB,CAACa,IAAI,CAAC,OAAO,EAAED,KAAK,CAAC,CAAA;AACvC,aAAA;AACH,WAAC,GAAG,CAAA;AACL,SAAA;AACD,QAAA,OAAOZ,iBAA2D,CAAA;AACpE,OAAC,CAA4C,CAAA;AAC9C,KAAA,MAAM;AACL,MAAA,MAAMc,cAAc,GAAGlB,aAAa,CAACE,IAAI,CACtCiB,MAAM,IAAI;QACT,IAAI,SAAS,IAAIA,MAAM,EAAE;UACvB,MAAMpE,OAAO,GAAG,CAAC+C,IAAI,CAACC,GAAG,EAAE,GAAGF,SAAS,IAAI,IAAI,CAAA;AAC/CnD,UAAAA,kBAAkB,CAAC;YACjBJ,MAAM,EAAE,IAAI,CAACwC,QAAQ;YACrBnC,UAAU,EAAE8C,iBAAiB,IAAI7C,OAAO;YACxCA,OAAO;YACPC,KAAK,EAAE8C,YAAY,CAAC9C,KAAK;AACzBd,YAAAA,QAAQ,EAAE,QAAQ;AAClBS,YAAAA,KAAK,EAAEV,iBAAiB,CAAC6D,YAAY,EAAE,QAAQ,CAAC;AAChD7C,YAAAA,MAAM,EAAE,CAAC;cAAEV,OAAO,EAAE+E,MAAM,CAACR,OAAO,CAAC,CAAC,CAAC,CAACS,OAAO,CAAChF,OAAO;AAAED,cAAAA,IAAI,EAAE,WAAA;aAAa,CAAC;YAC3EY,OAAO;AACPC,YAAAA,OAAO,EAAG,IAAY,CAACA,OAAO,IAAI,EAAE;AACpCvB,YAAAA,MAAM,EAAE8D,IAAI;AACZtC,YAAAA,UAAU,EAAE,GAAG;AACfC,YAAAA,KAAK,EAAE;AACLY,cAAAA,WAAW,EAAEqD,MAAM,CAACjE,KAAK,EAAE0D,aAAa,IAAI,CAAC;AAC7C5C,cAAAA,YAAY,EAAEmD,MAAM,CAACjE,KAAK,EAAE2D,iBAAiB,IAAI,CAAA;AAClD,aAAA;AACF,WAAA,CAAC,CAAA;AACH,SAAA;AACD,QAAA,OAAOM,MAAM,CAAA;OACd,EACAH,KAAK,IAAI;AACRtE,QAAAA,kBAAkB,CAAC;UACjBJ,MAAM,EAAE,IAAI,CAACwC,QAAQ;UACrBnC,UAAU,EAAE8C,iBAAiB,IAAI7C,OAAO;UACxCA,OAAO;UACPC,KAAK,EAAE8C,YAAY,CAAC9C,KAAK;AACzBd,UAAAA,QAAQ,EAAE,QAAQ;AAClBS,UAAAA,KAAK,EAAEV,iBAAiB,CAAC6D,YAAY,EAAE,QAAQ,CAAC;AAChD7C,UAAAA,MAAM,EAAE,EAAE;AACVC,UAAAA,OAAO,EAAE,CAAC;AACVC,UAAAA,OAAO,EAAG,IAAY,CAACA,OAAO,IAAI,EAAE;AACpCvB,UAAAA,MAAM,EAAE8D,IAAI;AACZtC,UAAAA,UAAU,EAAE,GAAG;AACfC,UAAAA,KAAK,EAAE;AACLY,YAAAA,WAAW,EAAE,CAAC;AACdE,YAAAA,YAAY,EAAE,CAAA;AACf,WAAA;AACF,SAAA,CAAC,CAAA;AACF,QAAA,MAAMgD,KAAK,CAAA;AACb,OAAC,CAC4B,CAAA;AAE/B,MAAA,OAAOE,cAAc,CAAA;AACtB,KAAA;AACH,GAAA;AAED;;ACjLD,MAAMG,eAAe,GAAI5F,MAAW,IAAyB;EAC3D,OAAO;IACL6F,WAAW,EAAE7F,MAAM,CAAC6F,WAAW;IAC/BC,UAAU,EAAE9F,MAAM,CAAC+F,SAAS;IAC5BC,KAAK,EAAEhG,MAAM,CAACiG,IAAI;IAClBC,iBAAiB,EAAElG,MAAM,CAACmG,gBAAgB;IAC1CC,gBAAgB,EAAEpG,MAAM,CAACqG,eAAe;IACxCC,IAAI,EAAEtG,MAAM,CAACuG,aAAa;IAC1B/B,MAAM,EAAExE,MAAM,CAACwE,MAAAA;GAChB,CAAA;AACH,CAAC,CAAA;AAED,MAAMgC,eAAe,GAAIC,MAA6B,IAAoB;AACxE,EAAA,OAAOA,MAAM,CAACC,GAAG,CAAEC,CAAC,IAAI;IACtB,IAAIhG,OAAO,GAAG,EAAE,CAAA;IAChB,IAAIiG,KAAK,CAACC,OAAO,CAACF,CAAC,CAAChG,OAAO,CAAC,EAAE;MAC5BA,OAAO,GAAGgG,CAAC,CAAChG,OAAO,CAChB+F,GAAG,CAAEI,CAAC,IAAI;AACT,QAAA,IAAIA,CAAC,CAACC,IAAI,KAAK,MAAM,EAAE;UACrB,OAAOD,CAAC,CAACE,IAAI,CAAA;AACd,SAAA;AACD,QAAA,OAAO,EAAE,CAAA;AACX,OAAC,CAAC,CACDC,IAAI,CAAC,EAAE,CAAC,CAAA;AACZ,KAAA,MAAM;MACLtG,OAAO,GAAGgG,CAAC,CAAChG,OAAO,CAAA;AACpB,KAAA;IACD,OAAO;MACLD,IAAI,EAAEiG,CAAC,CAACjG,IAAI;AACZC,MAAAA,OAAAA;KACD,CAAA;AACH,GAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAEM,MAAMuG,+BAA+B,GAAGA,CAC7C7D,QAAiB,EACjBjC,KAAsB,EACtB2C,OAA+C,KAClB;AAC7B,EAAA,MAAMoD,UAAU,GAA8B;IAC5CC,YAAY,EAAE,OAAO;MAAEC,UAAU;AAAErH,MAAAA,MAAAA;AAAQ,KAAA,KAAI;AAC7C,MAAA,MAAMoE,SAAS,GAAGC,IAAI,CAACC,GAAG,EAAE,CAAA;AAC5B,MAAA,IAAIgD,YAAY,GAAG;AACjB,QAAA,GAAGvD,OAAO;QACV,GAAG6B,eAAe,CAAC5F,MAAM,CAAA;OAC1B,CAAA;MACD,IAAI;AACF,QAAA,MAAM0F,MAAM,GAAG,MAAM2B,UAAU,EAAE,CAAA;QACjC,MAAM/F,OAAO,GAAG,CAAC+C,IAAI,CAACC,GAAG,EAAE,GAAGF,SAAS,IAAI,IAAI,CAAA;AAE/CnD,QAAAA,kBAAkB,CAAC;AACjBJ,UAAAA,MAAM,EAAEwC,QAAQ;UAChBnC,UAAU,EAAE6C,OAAO,CAACC,iBAAiB;UACrC7C,OAAO,EAAE4C,OAAO,CAACE,cAAc;UAC/B7C,KAAK,EAAEA,KAAK,CAACmG,OAAO;AACpBjH,UAAAA,QAAQ,EAAE,QAAQ;AAClBS,UAAAA,KAAK,EAAEgD,OAAO,CAAC9B,kBAAkB,GAAG,EAAE,GAAGuE,eAAe,CAACxG,MAAM,CAACyG,MAAM,CAAC;AACvEpF,UAAAA,MAAM,EAAE,CAAC;YAAEV,OAAO,EAAE+E,MAAM,CAACsB,IAAI;AAAEtG,YAAAA,IAAI,EAAE,WAAA;WAAa,CAAC;UACrDY,OAAO;AACPC,UAAAA,OAAO,EAAE,EAAE;AACXvB,UAAAA,MAAM,EAAEsH,YAAmB;AAC3B9F,UAAAA,UAAU,EAAE,GAAG;AACfC,UAAAA,KAAK,EAAE;AACLY,YAAAA,WAAW,EAAEqD,MAAM,CAACjE,KAAK,CAAC+F,YAAY;AACtCjF,YAAAA,YAAY,EAAEmD,MAAM,CAACjE,KAAK,CAACgG,gBAAAA;AAC5B,WAAA;AACF,SAAA,CAAC,CAAA;AAEF,QAAA,OAAO/B,MAAM,CAAA;OACd,CAAC,OAAOH,KAAK,EAAE;AACdtE,QAAAA,kBAAkB,CAAC;AACjBJ,UAAAA,MAAM,EAAEwC,QAAQ;UAChBnC,UAAU,EAAE6C,OAAO,CAACC,iBAAiB;UACrC7C,OAAO,EAAE4C,OAAO,CAACE,cAAc;UAC/B7C,KAAK,EAAEA,KAAK,CAACmG,OAAO;AACpBjH,UAAAA,QAAQ,EAAE,QAAQ;AAClBS,UAAAA,KAAK,EAAEgD,OAAO,CAAC9B,kBAAkB,GAAG,EAAE,GAAGuE,eAAe,CAACxG,MAAM,CAACyG,MAAM,CAAC;AACvEpF,UAAAA,MAAM,EAAE,EAAE;AACVC,UAAAA,OAAO,EAAE,CAAC;AACVC,UAAAA,OAAO,EAAE,EAAE;AACXvB,UAAAA,MAAM,EAAEsH,YAAmB;AAC3B9F,UAAAA,UAAU,EAAE,GAAG;AACfC,UAAAA,KAAK,EAAE;AACLY,YAAAA,WAAW,EAAE,CAAC;AACdE,YAAAA,YAAY,EAAE,CAAA;AACf,WAAA;AACF,SAAA,CAAC,CAAA;AACF,QAAA,MAAMgD,KAAK,CAAA;AACZ,OAAA;KACF;IAEDmC,UAAU,EAAE,OAAO;MAAEC,QAAQ;AAAE3H,MAAAA,MAAAA;AAAQ,KAAA,KAAI;AACzC,MAAA,MAAMoE,SAAS,GAAGC,IAAI,CAACC,GAAG,EAAE,CAAA;MAC5B,IAAIsD,aAAa,GAAG,EAAE,CAAA;MACtB,IAAInG,KAAK,GAAoD,EAAE,CAAA;AAC/D,MAAA,IAAI6F,YAAY,GAAG;AACjB,QAAA,GAAGvD,OAAO;QACV,GAAG6B,eAAe,CAAC5F,MAAM,CAAA;OAC1B,CAAA;MACD,IAAI;QACF,MAAM;UAAEwE,MAAM;UAAE,GAAGqD,IAAAA;SAAM,GAAG,MAAMF,QAAQ,EAAE,CAAA;AAE5C,QAAA,MAAMG,eAAe,GAAG,IAAIC,eAAe,CAAuD;AAChGC,UAAAA,SAASA,CAAChD,KAAK,EAAEiD,UAAU,EAAA;AACzB,YAAA,IAAIjD,KAAK,CAAC+B,IAAI,KAAK,YAAY,EAAE;cAC/Ba,aAAa,IAAI5C,KAAK,CAACkD,SAAS,CAAA;AACjC,aAAA;AACD,YAAA,IAAIlD,KAAK,CAAC+B,IAAI,KAAK,QAAQ,EAAE;AAC3BtF,cAAAA,KAAK,GAAG;AACNY,gBAAAA,WAAW,EAAE2C,KAAK,CAACvD,KAAK,EAAE+F,YAAY;AACtCjF,gBAAAA,YAAY,EAAEyC,KAAK,CAACvD,KAAK,EAAEgG,gBAAAA;eAC5B,CAAA;AACF,aAAA;AACDQ,YAAAA,UAAU,CAACE,OAAO,CAACnD,KAAK,CAAC,CAAA;WAC1B;AAEDoD,UAAAA,KAAKA,GAAA;YACH,MAAM9G,OAAO,GAAG,CAAC+C,IAAI,CAACC,GAAG,EAAE,GAAGF,SAAS,IAAI,IAAI,CAAA;AAC/CnD,YAAAA,kBAAkB,CAAC;AACjBJ,cAAAA,MAAM,EAAEwC,QAAQ;cAChBnC,UAAU,EAAE6C,OAAO,CAACC,iBAAiB;cACrC7C,OAAO,EAAE4C,OAAO,CAACE,cAAc;cAC/B7C,KAAK,EAAEA,KAAK,CAACmG,OAAO;AACpBjH,cAAAA,QAAQ,EAAE,QAAQ;AAClBS,cAAAA,KAAK,EAAEgD,OAAO,CAAC9B,kBAAkB,GAAG,EAAE,GAAGuE,eAAe,CAACxG,MAAM,CAACyG,MAAM,CAAC;AACvEpF,cAAAA,MAAM,EAAE,CAAC;AAAEV,gBAAAA,OAAO,EAAEiH,aAAa;AAAElH,gBAAAA,IAAI,EAAE,WAAA;AAAW,eAAE,CAAC;cACvDY,OAAO;AACPC,cAAAA,OAAO,EAAE,EAAE;AACXvB,cAAAA,MAAM,EAAEsH,YAAmB;AAC3B9F,cAAAA,UAAU,EAAE,GAAG;AACfC,cAAAA,KAAAA;AACD,aAAA,CAAC,CAAA;AACJ,WAAA;AACD,SAAA,CAAC,CAAA;QAEF,OAAO;AACL+C,UAAAA,MAAM,EAAEA,MAAM,CAAC6D,WAAW,CAACP,eAAe,CAAC;UAC3C,GAAGD,IAAAA;SACJ,CAAA;OACF,CAAC,OAAOtC,KAAK,EAAE;AACdtE,QAAAA,kBAAkB,CAAC;AACjBJ,UAAAA,MAAM,EAAEwC,QAAQ;UAChBnC,UAAU,EAAE6C,OAAO,CAACC,iBAAiB;UACrC7C,OAAO,EAAE4C,OAAO,CAACE,cAAc;UAC/B7C,KAAK,EAAEA,KAAK,CAACmG,OAAO;AACpBjH,UAAAA,QAAQ,EAAE,QAAQ;AAClBS,UAAAA,KAAK,EAAEgD,OAAO,CAAC9B,kBAAkB,GAAG,EAAE,GAAGuE,eAAe,CAACxG,MAAM,CAACyG,MAAM,CAAC;AACvEpF,UAAAA,MAAM,EAAE,EAAE;AACVC,UAAAA,OAAO,EAAE,CAAC;AACVC,UAAAA,OAAO,EAAE,EAAE;AACXvB,UAAAA,MAAM,EAAEsH,YAAmB;AAC3B9F,UAAAA,UAAU,EAAE,GAAG;AACfC,UAAAA,KAAK,EAAE;AACLY,YAAAA,WAAW,EAAE,CAAC;AACdE,YAAAA,YAAY,EAAE,CAAA;AACf,WAAA;AACF,SAAA,CAAC,CAAA;AACF,QAAA,MAAMgD,KAAK,CAAA;AACZ,OAAA;AACH,KAAA;GACD,CAAA;AAED,EAAA,OAAO4B,UAAU,CAAA;AACnB,CAAC,CAAA;AAEM,MAAMmB,uBAAuB,GAAGA,CACrClH,KAAsB,EACtBiC,QAAiB,EACjBU,OAA+C,KAC5B;EACnB,MAAM5C,OAAO,GAAG4C,OAAO,CAACE,cAAc,IAAIE,OAAM,EAAE,CAAA;AAClD,EAAA,MAAMgD,UAAU,GAAGD,+BAA+B,CAAC7D,QAAQ,EAAEjC,KAAK,EAAE;AAClE,IAAA,GAAG2C,OAAO;AACVE,IAAAA,cAAc,EAAE9C,OAAO;AACvB6C,IAAAA,iBAAiB,EAAED,OAAO,CAACC,iBAAiB,IAAI7C,OAAAA;AACjD,GAAA,CAAC,CAAA;EAEF,MAAMoH,YAAY,GAAGC,iCAAiB,CAAC;IACrCpH,KAAK;AACL+F,IAAAA,UAAAA;AACD,GAAA,CAAC,CAAA;AAEF,EAAA,OAAOoB,YAAY,CAAA;AACrB;;;;;"}
|
package/lib/index.d.ts
CHANGED
|
@@ -25,8 +25,8 @@ interface MonitoringOpenAIConfig {
|
|
|
25
25
|
}
|
|
26
26
|
declare class PostHogOpenAI extends OpenAIOrignal {
|
|
27
27
|
private readonly phClient;
|
|
28
|
-
constructor(config: MonitoringOpenAIConfig);
|
|
29
28
|
chat: WrappedChat;
|
|
29
|
+
constructor(config: MonitoringOpenAIConfig);
|
|
30
30
|
}
|
|
31
31
|
declare class WrappedChat extends OpenAIOrignal.Chat {
|
|
32
32
|
constructor(parentClient: PostHogOpenAI, phClient: PostHog);
|
|
@@ -45,7 +45,7 @@ interface CreateInstrumentationMiddlewareOptions {
|
|
|
45
45
|
posthogTraceId: string;
|
|
46
46
|
posthogProperties?: Record<string, any>;
|
|
47
47
|
posthogPrivacyMode?: boolean;
|
|
48
|
-
posthogGroups?: string
|
|
48
|
+
posthogGroups?: Record<string, any>;
|
|
49
49
|
}
|
|
50
50
|
declare const wrapVercelLanguageModel: (model: LanguageModelV1, phClient: PostHog, options: CreateInstrumentationMiddlewareOptions) => LanguageModelV1;
|
|
51
51
|
|
package/lib/index.esm.js
CHANGED
|
@@ -55,8 +55,8 @@ const sendEventToPosthog = ({
|
|
|
55
55
|
$ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),
|
|
56
56
|
$ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),
|
|
57
57
|
$ai_http_status: httpStatus,
|
|
58
|
-
$ai_input_tokens: usage.
|
|
59
|
-
$ai_output_tokens: usage.
|
|
58
|
+
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
59
|
+
$ai_output_tokens: usage.outputTokens ?? 0,
|
|
60
60
|
$ai_latency: latency,
|
|
61
61
|
$ai_trace_id: traceId,
|
|
62
62
|
$ai_base_url: baseURL,
|
|
@@ -112,8 +112,8 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
112
112
|
});
|
|
113
113
|
let accumulatedContent = '';
|
|
114
114
|
let usage = {
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
inputTokens: 0,
|
|
116
|
+
outputTokens: 0
|
|
117
117
|
};
|
|
118
118
|
if ('tee' in value) {
|
|
119
119
|
const openAIStream = value;
|
|
@@ -124,8 +124,8 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
124
124
|
accumulatedContent += delta;
|
|
125
125
|
if (chunk.usage) {
|
|
126
126
|
usage = {
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
128
|
+
outputTokens: chunk.usage.completion_tokens ?? 0
|
|
129
129
|
};
|
|
130
130
|
}
|
|
131
131
|
passThroughStream.write(chunk);
|
|
@@ -137,7 +137,7 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
137
137
|
traceId,
|
|
138
138
|
model: openAIParams.model,
|
|
139
139
|
provider: 'openai',
|
|
140
|
-
input:
|
|
140
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
141
141
|
output: [{
|
|
142
142
|
content: accumulatedContent,
|
|
143
143
|
role: 'assistant'
|
|
@@ -157,15 +157,15 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
157
157
|
traceId,
|
|
158
158
|
model: openAIParams.model,
|
|
159
159
|
provider: 'openai',
|
|
160
|
-
input:
|
|
160
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
161
161
|
output: [],
|
|
162
162
|
latency: 0,
|
|
163
163
|
baseURL: this.baseURL ?? '',
|
|
164
164
|
params: body,
|
|
165
165
|
httpStatus: 500,
|
|
166
166
|
usage: {
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
inputTokens: 0,
|
|
168
|
+
outputTokens: 0
|
|
169
169
|
}
|
|
170
170
|
});
|
|
171
171
|
passThroughStream.emit('error', error);
|
|
@@ -184,7 +184,7 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
184
184
|
traceId,
|
|
185
185
|
model: openAIParams.model,
|
|
186
186
|
provider: 'openai',
|
|
187
|
-
input:
|
|
187
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
188
188
|
output: [{
|
|
189
189
|
content: result.choices[0].message.content,
|
|
190
190
|
role: 'assistant'
|
|
@@ -194,8 +194,8 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
194
194
|
params: body,
|
|
195
195
|
httpStatus: 200,
|
|
196
196
|
usage: {
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
198
|
+
outputTokens: result.usage?.completion_tokens ?? 0
|
|
199
199
|
}
|
|
200
200
|
});
|
|
201
201
|
}
|
|
@@ -207,15 +207,15 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
207
207
|
traceId,
|
|
208
208
|
model: openAIParams.model,
|
|
209
209
|
provider: 'openai',
|
|
210
|
-
input:
|
|
210
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
211
211
|
output: [],
|
|
212
212
|
latency: 0,
|
|
213
213
|
baseURL: this.baseURL ?? '',
|
|
214
214
|
params: body,
|
|
215
215
|
httpStatus: 500,
|
|
216
216
|
usage: {
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
inputTokens: 0,
|
|
218
|
+
outputTokens: 0
|
|
219
219
|
}
|
|
220
220
|
});
|
|
221
221
|
throw error;
|
|
@@ -225,6 +225,36 @@ class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
const mapVercelParams = params => {
|
|
229
|
+
return {
|
|
230
|
+
temperature: params.temperature,
|
|
231
|
+
max_tokens: params.maxTokens,
|
|
232
|
+
top_p: params.topP,
|
|
233
|
+
frequency_penalty: params.frequencyPenalty,
|
|
234
|
+
presence_penalty: params.presencePenalty,
|
|
235
|
+
stop: params.stopSequences,
|
|
236
|
+
stream: params.stream
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
const mapVercelPrompt = prompt => {
|
|
240
|
+
return prompt.map(p => {
|
|
241
|
+
let content = '';
|
|
242
|
+
if (Array.isArray(p.content)) {
|
|
243
|
+
content = p.content.map(c => {
|
|
244
|
+
if (c.type === 'text') {
|
|
245
|
+
return c.text;
|
|
246
|
+
}
|
|
247
|
+
return '';
|
|
248
|
+
}).join('');
|
|
249
|
+
} else {
|
|
250
|
+
content = p.content;
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
role: p.role,
|
|
254
|
+
content
|
|
255
|
+
};
|
|
256
|
+
});
|
|
257
|
+
};
|
|
228
258
|
const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
229
259
|
const middleware = {
|
|
230
260
|
wrapGenerate: async ({
|
|
@@ -232,6 +262,10 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
232
262
|
params
|
|
233
263
|
}) => {
|
|
234
264
|
const startTime = Date.now();
|
|
265
|
+
let mergedParams = {
|
|
266
|
+
...options,
|
|
267
|
+
...mapVercelParams(params)
|
|
268
|
+
};
|
|
235
269
|
try {
|
|
236
270
|
const result = await doGenerate();
|
|
237
271
|
const latency = (Date.now() - startTime) / 1000;
|
|
@@ -241,20 +275,18 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
241
275
|
traceId: options.posthogTraceId,
|
|
242
276
|
model: model.modelId,
|
|
243
277
|
provider: 'vercel',
|
|
244
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
278
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
245
279
|
output: [{
|
|
246
280
|
content: result.text,
|
|
247
281
|
role: 'assistant'
|
|
248
282
|
}],
|
|
249
283
|
latency,
|
|
250
284
|
baseURL: '',
|
|
251
|
-
params:
|
|
252
|
-
posthog_properties: options
|
|
253
|
-
},
|
|
285
|
+
params: mergedParams,
|
|
254
286
|
httpStatus: 200,
|
|
255
287
|
usage: {
|
|
256
|
-
|
|
257
|
-
|
|
288
|
+
inputTokens: result.usage.promptTokens,
|
|
289
|
+
outputTokens: result.usage.completionTokens
|
|
258
290
|
}
|
|
259
291
|
});
|
|
260
292
|
return result;
|
|
@@ -265,17 +297,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
265
297
|
traceId: options.posthogTraceId,
|
|
266
298
|
model: model.modelId,
|
|
267
299
|
provider: 'vercel',
|
|
268
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
300
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
269
301
|
output: [],
|
|
270
302
|
latency: 0,
|
|
271
303
|
baseURL: '',
|
|
272
|
-
params:
|
|
273
|
-
posthog_properties: options
|
|
274
|
-
},
|
|
304
|
+
params: mergedParams,
|
|
275
305
|
httpStatus: 500,
|
|
276
306
|
usage: {
|
|
277
|
-
|
|
278
|
-
|
|
307
|
+
inputTokens: 0,
|
|
308
|
+
outputTokens: 0
|
|
279
309
|
}
|
|
280
310
|
});
|
|
281
311
|
throw error;
|
|
@@ -288,6 +318,10 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
288
318
|
const startTime = Date.now();
|
|
289
319
|
let generatedText = '';
|
|
290
320
|
let usage = {};
|
|
321
|
+
let mergedParams = {
|
|
322
|
+
...options,
|
|
323
|
+
...mapVercelParams(params)
|
|
324
|
+
};
|
|
291
325
|
try {
|
|
292
326
|
const {
|
|
293
327
|
stream,
|
|
@@ -300,8 +334,8 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
300
334
|
}
|
|
301
335
|
if (chunk.type === 'finish') {
|
|
302
336
|
usage = {
|
|
303
|
-
|
|
304
|
-
|
|
337
|
+
inputTokens: chunk.usage?.promptTokens,
|
|
338
|
+
outputTokens: chunk.usage?.completionTokens
|
|
305
339
|
};
|
|
306
340
|
}
|
|
307
341
|
controller.enqueue(chunk);
|
|
@@ -314,16 +348,14 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
314
348
|
traceId: options.posthogTraceId,
|
|
315
349
|
model: model.modelId,
|
|
316
350
|
provider: 'vercel',
|
|
317
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
351
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
318
352
|
output: [{
|
|
319
353
|
content: generatedText,
|
|
320
354
|
role: 'assistant'
|
|
321
355
|
}],
|
|
322
356
|
latency,
|
|
323
357
|
baseURL: '',
|
|
324
|
-
params:
|
|
325
|
-
posthog_properties: options
|
|
326
|
-
},
|
|
358
|
+
params: mergedParams,
|
|
327
359
|
httpStatus: 200,
|
|
328
360
|
usage
|
|
329
361
|
});
|
|
@@ -340,17 +372,15 @@ const createInstrumentationMiddleware = (phClient, model, options) => {
|
|
|
340
372
|
traceId: options.posthogTraceId,
|
|
341
373
|
model: model.modelId,
|
|
342
374
|
provider: 'vercel',
|
|
343
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
375
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
344
376
|
output: [],
|
|
345
377
|
latency: 0,
|
|
346
378
|
baseURL: '',
|
|
347
|
-
params:
|
|
348
|
-
posthog_properties: options
|
|
349
|
-
},
|
|
379
|
+
params: mergedParams,
|
|
350
380
|
httpStatus: 500,
|
|
351
381
|
usage: {
|
|
352
|
-
|
|
353
|
-
|
|
382
|
+
inputTokens: 0,
|
|
383
|
+
outputTokens: 0
|
|
354
384
|
}
|
|
355
385
|
});
|
|
356
386
|
throw error;
|
package/lib/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/utils.ts","../src/openai/index.ts","../src/vercel/middleware.ts"],"sourcesContent":["import { PostHog } from 'posthog-node'\nimport OpenAIOrignal from 'openai'\n\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\n\nexport interface MonitoringParams {\n posthogDistinctId?: string\n posthogTraceId?: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: Record<string, any>\n}\n\nexport const getModelParams = (params: ChatCompletionCreateParamsBase & MonitoringParams): Record<string, any> => {\n const modelParams: Record<string, any> = {}\n const paramKeys = [\n 'temperature',\n 'max_tokens',\n 'max_completion_tokens',\n 'top_p',\n 'frequency_penalty',\n 'presence_penalty',\n 'n',\n 'stop',\n 'stream',\n 'streaming',\n ] as const\n\n for (const key of paramKeys) {\n if (key in params && (params as any)[key] !== undefined) {\n modelParams[key] = (params as any)[key]\n }\n }\n return modelParams\n}\n\nexport const getUsage = (response: any, provider: string): { input_tokens: number; output_tokens: number } => {\n if (!response?.usage) {\n return { input_tokens: 0, output_tokens: 0 }\n }\n\n if (provider === 'anthropic') {\n return {\n input_tokens: response.usage.input_tokens ?? 0,\n output_tokens: response.usage.output_tokens ?? 0,\n }\n } else if (provider === 'openai') {\n return {\n input_tokens: response.usage.prompt_tokens ?? 0,\n output_tokens: response.usage.completion_tokens ?? 0,\n }\n }\n\n return { input_tokens: 0, output_tokens: 0 }\n}\n\n/**\n * Helper to format responses (non-streaming) for consumption, mirroring Python's openai vs. anthropic approach.\n */\nexport const formatResponse = (response: any, provider: string): Array<{ role: string; content: string }> => {\n if (!response) {\n return []\n }\n if (provider === 'anthropic') {\n return formatResponseAnthropic(response)\n } else if (provider === 'openai') {\n return formatResponseOpenAI(response)\n }\n return []\n}\n\nexport const formatResponseAnthropic = (response: any): Array<{ role: string; content: string }> => {\n // Example approach if \"response.content\" holds array of text segments, etc.\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.content ?? []) {\n if (choice?.text) {\n output.push({\n role: 'assistant',\n content: choice.text,\n })\n }\n }\n return output\n}\n\nexport const formatResponseOpenAI = (response: any): Array<{ role: string; content: string }> => {\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.choices ?? []) {\n if (choice.message?.content) {\n output.push({\n role: choice.message.role,\n content: choice.message.content,\n })\n }\n }\n return output\n}\n\nexport const mergeSystemPrompt = (params: ChatCompletionCreateParamsBase & MonitoringParams, provider: string): any => {\n if (provider !== 'anthropic') {\n return params.messages\n }\n const messages = params.messages || []\n if (!(params as any).system) {\n return messages\n }\n const systemMessage = (params as any).system\n return [{ role: 'system', content: systemMessage }, ...messages]\n}\n\nexport const withPrivacyMode = (client: PostHog, privacyMode: boolean, input: any): any => {\n return (client as any).privacy_mode || privacyMode ? null : input\n}\n\nexport type SendEventToPosthogParams = {\n client: PostHog\n distinctId?: string\n traceId: string\n model: string\n provider: string\n input: any\n output: any\n latency: number\n baseURL: string\n httpStatus: number\n usage?: { input_tokens?: number; output_tokens?: number }\n params: ChatCompletionCreateParamsBase & MonitoringParams\n}\n\nexport const sendEventToPosthog = ({\n client,\n distinctId,\n traceId,\n model,\n provider,\n input,\n output,\n latency,\n baseURL,\n params,\n httpStatus = 200,\n usage = {},\n}: SendEventToPosthogParams): void => {\n if (client.capture) {\n client.capture({\n distinctId: distinctId ?? traceId,\n event: '$ai_generation',\n properties: {\n $ai_provider: provider,\n $ai_model: model,\n $ai_model_parameters: getModelParams(params),\n $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),\n $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),\n $ai_http_status: httpStatus,\n $ai_input_tokens: usage.input_tokens ?? 0,\n $ai_output_tokens: usage.output_tokens ?? 0,\n $ai_latency: latency,\n $ai_trace_id: traceId,\n $ai_base_url: baseURL,\n ...params.posthogProperties,\n ...(distinctId ? {} : { $process_person_profile: false }),\n },\n groups: params.posthogGroups,\n })\n }\n}\n","import OpenAIOrignal from 'openai'\nimport { PostHog } from 'posthog-node'\nimport { v4 as uuidv4 } from 'uuid'\nimport { PassThrough } from 'stream'\nimport { mergeSystemPrompt, MonitoringParams, sendEventToPosthog } from '../utils'\n\ntype ChatCompletion = OpenAIOrignal.ChatCompletion\ntype ChatCompletionChunk = OpenAIOrignal.ChatCompletionChunk\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\ntype ChatCompletionCreateParamsNonStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsNonStreaming\ntype ChatCompletionCreateParamsStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsStreaming\nimport type { APIPromise, RequestOptions } from 'openai/core'\nimport type { Stream } from 'openai/streaming'\n\ninterface MonitoringOpenAIConfig {\n apiKey: string\n posthog: PostHog\n baseURL?: string\n}\n\nexport class PostHogOpenAI extends OpenAIOrignal {\n private readonly phClient: PostHog\n\n constructor(config: MonitoringOpenAIConfig) {\n const { posthog, ...openAIConfig } = config\n super(openAIConfig)\n this.phClient = posthog\n this.chat = new WrappedChat(this, this.phClient)\n }\n\n public chat: WrappedChat\n}\n\nexport class WrappedChat extends OpenAIOrignal.Chat {\n constructor(parentClient: PostHogOpenAI, phClient: PostHog) {\n super(parentClient)\n this.completions = new WrappedCompletions(parentClient, phClient)\n }\n\n public completions: WrappedCompletions\n}\n\nexport class WrappedCompletions extends OpenAIOrignal.Chat.Completions {\n private readonly phClient: PostHog\n\n constructor(client: OpenAIOrignal, phClient: PostHog) {\n super(client)\n this.phClient = phClient\n }\n\n // --- Overload #1: Non-streaming\n public create(\n body: ChatCompletionCreateParamsNonStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion>\n\n // --- Overload #2: Streaming\n public create(\n body: ChatCompletionCreateParamsStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<Stream<ChatCompletionChunk>>\n\n // --- Overload #3: Generic base\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>>\n\n // --- Implementation Signature\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const {\n posthogDistinctId,\n posthogTraceId,\n posthogProperties,\n posthogPrivacyMode = false,\n posthogGroups,\n ...openAIParams\n } = body\n\n const traceId = posthogTraceId ?? uuidv4()\n const startTime = Date.now()\n\n const parentPromise = super.create(openAIParams, options)\n\n if (openAIParams.stream) {\n return parentPromise.then((value) => {\n const passThroughStream = new PassThrough({ objectMode: true })\n let accumulatedContent = ''\n let usage: { input_tokens: number; output_tokens: number } = {\n input_tokens: 0,\n output_tokens: 0,\n }\n if ('tee' in value) {\n const openAIStream = value\n ;(async () => {\n try {\n for await (const chunk of openAIStream) {\n const delta = chunk?.choices?.[0]?.delta?.content ?? ''\n accumulatedContent += delta\n if (chunk.usage) {\n usage = {\n input_tokens: chunk.usage.prompt_tokens ?? 0,\n output_tokens: chunk.usage.completion_tokens ?? 0,\n }\n }\n passThroughStream.write(chunk)\n }\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: accumulatedContent, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage,\n })\n passThroughStream.end()\n } catch (error) {\n // error handling\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n passThroughStream.emit('error', error)\n }\n })()\n }\n return passThroughStream as unknown as Stream<ChatCompletionChunk>\n }) as APIPromise<Stream<ChatCompletionChunk>>\n } else {\n const wrappedPromise = parentPromise.then(\n (result) => {\n if ('choices' in result) {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: result.choices[0].message.content, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage: {\n input_tokens: result.usage?.prompt_tokens ?? 0,\n output_tokens: result.usage?.completion_tokens ?? 0,\n },\n })\n }\n return result\n },\n (error) => {\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: posthogPrivacyMode ? '' : mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n throw error\n }\n ) as APIPromise<ChatCompletion>\n\n return wrappedPromise\n }\n }\n}\n\nexport default PostHogOpenAI\n","import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'\nimport type {\n LanguageModelV1,\n Experimental_LanguageModelV1Middleware as LanguageModelV1Middleware,\n LanguageModelV1StreamPart,\n} from 'ai'\nimport { v4 as uuidv4 } from 'uuid'\nimport type { PostHog } from 'posthog-node'\nimport { sendEventToPosthog } from '../utils'\n\ninterface CreateInstrumentationMiddlewareOptions {\n posthogDistinctId?: string\n posthogTraceId: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: string[]\n}\n\nexport const createInstrumentationMiddleware = (\n phClient: PostHog,\n model: LanguageModelV1,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1Middleware => {\n const middleware: LanguageModelV1Middleware = {\n wrapGenerate: async ({ doGenerate, params }) => {\n const startTime = Date.now()\n\n try {\n const result = await doGenerate()\n const latency = (Date.now() - startTime) / 1000\n\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [{ content: result.text, role: 'assistant' }],\n latency,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 200,\n usage: {\n input_tokens: result.usage.promptTokens,\n output_tokens: result.usage.completionTokens,\n },\n })\n\n return result\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [],\n latency: 0,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n throw error\n }\n },\n\n wrapStream: async ({ doStream, params }) => {\n const startTime = Date.now()\n let generatedText = ''\n let usage: { input_tokens?: number; output_tokens?: number } = {}\n\n try {\n const { stream, ...rest } = await doStream()\n\n const transformStream = new TransformStream<LanguageModelV1StreamPart, LanguageModelV1StreamPart>({\n transform(chunk, controller) {\n if (chunk.type === 'text-delta') {\n generatedText += chunk.textDelta\n }\n if (chunk.type === 'finish') {\n usage = {\n input_tokens: chunk.usage?.promptTokens,\n output_tokens: chunk.usage?.completionTokens,\n }\n }\n controller.enqueue(chunk)\n },\n\n flush() {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [{ content: generatedText, role: 'assistant' }],\n latency,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 200,\n usage,\n })\n },\n })\n\n return {\n stream: stream.pipeThrough(transformStream),\n ...rest,\n }\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : params.prompt,\n output: [],\n latency: 0,\n baseURL: '',\n params: { posthog_properties: options } as any,\n httpStatus: 500,\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n },\n })\n throw error\n }\n },\n }\n\n return middleware\n}\n\nexport const wrapVercelLanguageModel = (\n model: LanguageModelV1,\n phClient: PostHog,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1 => {\n const traceId = options.posthogTraceId ?? uuidv4()\n const middleware = createInstrumentationMiddleware(phClient, model, {\n ...options,\n posthogTraceId: traceId,\n posthogDistinctId: options.posthogDistinctId ?? traceId,\n })\n\n const wrappedModel = wrapLanguageModel({\n model,\n middleware,\n })\n\n return wrappedModel\n}\n"],"names":["getModelParams","params","modelParams","paramKeys","key","undefined","mergeSystemPrompt","provider","messages","system","systemMessage","role","content","withPrivacyMode","client","privacyMode","input","privacy_mode","sendEventToPosthog","distinctId","traceId","model","output","latency","baseURL","httpStatus","usage","capture","event","properties","$ai_provider","$ai_model","$ai_model_parameters","$ai_input","posthogPrivacyMode","$ai_output_choices","$ai_http_status","$ai_input_tokens","input_tokens","$ai_output_tokens","output_tokens","$ai_latency","$ai_trace_id","$ai_base_url","posthogProperties","$process_person_profile","groups","posthogGroups","PostHogOpenAI","OpenAIOrignal","constructor","config","posthog","openAIConfig","phClient","chat","WrappedChat","Chat","parentClient","completions","WrappedCompletions","Completions","create","body","options","posthogDistinctId","posthogTraceId","openAIParams","uuidv4","startTime","Date","now","parentPromise","stream","then","value","passThroughStream","PassThrough","objectMode","accumulatedContent","openAIStream","chunk","delta","choices","prompt_tokens","completion_tokens","write","end","error","emit","wrappedPromise","result","message","createInstrumentationMiddleware","middleware","wrapGenerate","doGenerate","modelId","prompt","text","posthog_properties","promptTokens","completionTokens","wrapStream","doStream","generatedText","rest","transformStream","TransformStream","transform","controller","type","textDelta","enqueue","flush","pipeThrough","wrapVercelLanguageModel","wrappedModel","wrapLanguageModel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/utils.ts","../src/openai/index.ts","../src/vercel/middleware.ts"],"sourcesContent":["import { PostHog } from 'posthog-node'\nimport OpenAIOrignal from 'openai'\n\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\n\nexport interface MonitoringParams {\n posthogDistinctId?: string\n posthogTraceId?: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: Record<string, any>\n}\n\nexport const getModelParams = (params: ChatCompletionCreateParamsBase & MonitoringParams): Record<string, any> => {\n const modelParams: Record<string, any> = {}\n const paramKeys = [\n 'temperature',\n 'max_tokens',\n 'max_completion_tokens',\n 'top_p',\n 'frequency_penalty',\n 'presence_penalty',\n 'n',\n 'stop',\n 'stream',\n 'streaming',\n ] as const\n\n for (const key of paramKeys) {\n if (key in params && (params as any)[key] !== undefined) {\n modelParams[key] = (params as any)[key]\n }\n }\n return modelParams\n}\n\n/**\n * Helper to format responses (non-streaming) for consumption, mirroring Python's openai vs. anthropic approach.\n */\nexport const formatResponse = (response: any, provider: string): Array<{ role: string; content: string }> => {\n if (!response) {\n return []\n }\n if (provider === 'anthropic') {\n return formatResponseAnthropic(response)\n } else if (provider === 'openai') {\n return formatResponseOpenAI(response)\n }\n return []\n}\n\nexport const formatResponseAnthropic = (response: any): Array<{ role: string; content: string }> => {\n // Example approach if \"response.content\" holds array of text segments, etc.\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.content ?? []) {\n if (choice?.text) {\n output.push({\n role: 'assistant',\n content: choice.text,\n })\n }\n }\n return output\n}\n\nexport const formatResponseOpenAI = (response: any): Array<{ role: string; content: string }> => {\n const output: Array<{ role: string; content: string }> = []\n for (const choice of response.choices ?? []) {\n if (choice.message?.content) {\n output.push({\n role: choice.message.role,\n content: choice.message.content,\n })\n }\n }\n return output\n}\n\nexport const mergeSystemPrompt = (params: ChatCompletionCreateParamsBase & MonitoringParams, provider: string): any => {\n if (provider !== 'anthropic') {\n return params.messages\n }\n const messages = params.messages || []\n if (!(params as any).system) {\n return messages\n }\n const systemMessage = (params as any).system\n return [{ role: 'system', content: systemMessage }, ...messages]\n}\n\nexport const withPrivacyMode = (client: PostHog, privacyMode: boolean, input: any): any => {\n return (client as any).privacy_mode || privacyMode ? null : input\n}\n\nexport type SendEventToPosthogParams = {\n client: PostHog\n distinctId?: string\n traceId: string\n model: string\n provider: string\n input: any\n output: any\n latency: number\n baseURL: string\n httpStatus: number\n usage?: { inputTokens?: number; outputTokens?: number }\n params: ChatCompletionCreateParamsBase & MonitoringParams\n}\n\nexport const sendEventToPosthog = ({\n client,\n distinctId,\n traceId,\n model,\n provider,\n input,\n output,\n latency,\n baseURL,\n params,\n httpStatus = 200,\n usage = {},\n}: SendEventToPosthogParams): void => {\n if (client.capture) {\n client.capture({\n distinctId: distinctId ?? traceId,\n event: '$ai_generation',\n properties: {\n $ai_provider: provider,\n $ai_model: model,\n $ai_model_parameters: getModelParams(params),\n $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),\n $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),\n $ai_http_status: httpStatus,\n $ai_input_tokens: usage.inputTokens ?? 0,\n $ai_output_tokens: usage.outputTokens ?? 0,\n $ai_latency: latency,\n $ai_trace_id: traceId,\n $ai_base_url: baseURL,\n ...params.posthogProperties,\n ...(distinctId ? {} : { $process_person_profile: false }),\n },\n groups: params.posthogGroups,\n })\n }\n}","import OpenAIOrignal from 'openai'\nimport { PostHog } from 'posthog-node'\nimport { v4 as uuidv4 } from 'uuid'\nimport { PassThrough } from 'stream'\nimport { mergeSystemPrompt, MonitoringParams, sendEventToPosthog } from '../utils'\n\ntype ChatCompletion = OpenAIOrignal.ChatCompletion\ntype ChatCompletionChunk = OpenAIOrignal.ChatCompletionChunk\ntype ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParams\ntype ChatCompletionCreateParamsNonStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsNonStreaming\ntype ChatCompletionCreateParamsStreaming = OpenAIOrignal.Chat.Completions.ChatCompletionCreateParamsStreaming\nimport type { APIPromise, RequestOptions } from 'openai/core'\nimport type { Stream } from 'openai/streaming'\n\ninterface MonitoringOpenAIConfig {\n apiKey: string\n posthog: PostHog\n baseURL?: string\n}\n\nexport class PostHogOpenAI extends OpenAIOrignal {\n private readonly phClient: PostHog\n public chat: WrappedChat\n\n constructor(config: MonitoringOpenAIConfig) {\n const { posthog, ...openAIConfig } = config\n super(openAIConfig)\n this.phClient = posthog\n this.chat = new WrappedChat(this, this.phClient)\n }\n}\n\nexport class WrappedChat extends OpenAIOrignal.Chat {\n constructor(parentClient: PostHogOpenAI, phClient: PostHog) {\n super(parentClient)\n this.completions = new WrappedCompletions(parentClient, phClient)\n }\n\n public completions: WrappedCompletions\n}\n\nexport class WrappedCompletions extends OpenAIOrignal.Chat.Completions {\n private readonly phClient: PostHog\n\n constructor(client: OpenAIOrignal, phClient: PostHog) {\n super(client)\n this.phClient = phClient\n }\n\n // --- Overload #1: Non-streaming\n public create(\n body: ChatCompletionCreateParamsNonStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion>\n\n // --- Overload #2: Streaming\n public create(\n body: ChatCompletionCreateParamsStreaming & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<Stream<ChatCompletionChunk>>\n\n // --- Overload #3: Generic base\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>>\n\n // --- Implementation Signature\n public create(\n body: ChatCompletionCreateParamsBase & MonitoringParams,\n options?: RequestOptions\n ): APIPromise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const {\n posthogDistinctId,\n posthogTraceId,\n posthogProperties,\n posthogPrivacyMode = false,\n posthogGroups,\n ...openAIParams\n } = body\n\n const traceId = posthogTraceId ?? uuidv4()\n const startTime = Date.now()\n\n const parentPromise = super.create(openAIParams, options)\n\n if (openAIParams.stream) {\n return parentPromise.then((value) => {\n const passThroughStream = new PassThrough({ objectMode: true })\n let accumulatedContent = ''\n let usage: { inputTokens: number; outputTokens: number } = {\n inputTokens: 0,\n outputTokens: 0,\n }\n if ('tee' in value) {\n const openAIStream = value;\n (async () => {\n try {\n for await (const chunk of openAIStream) {\n const delta = chunk?.choices?.[0]?.delta?.content ?? ''\n accumulatedContent += delta\n if (chunk.usage) {\n usage = {\n inputTokens: chunk.usage.prompt_tokens ?? 0,\n outputTokens: chunk.usage.completion_tokens ?? 0,\n }\n }\n passThroughStream.write(chunk)\n }\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: accumulatedContent, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage,\n })\n passThroughStream.end()\n } catch (error) {\n // error handling\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n passThroughStream.emit('error', error)\n }\n })()\n }\n return passThroughStream as unknown as Stream<ChatCompletionChunk>\n }) as APIPromise<Stream<ChatCompletionChunk>>\n } else {\n const wrappedPromise = parentPromise.then(\n (result) => {\n if ('choices' in result) {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [{ content: result.choices[0].message.content, role: 'assistant' }],\n latency,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 200,\n usage: {\n inputTokens: result.usage?.prompt_tokens ?? 0,\n outputTokens: result.usage?.completion_tokens ?? 0,\n },\n })\n }\n return result\n },\n (error) => {\n sendEventToPosthog({\n client: this.phClient,\n distinctId: posthogDistinctId ?? traceId,\n traceId,\n model: openAIParams.model,\n provider: 'openai',\n input: mergeSystemPrompt(openAIParams, 'openai'),\n output: [],\n latency: 0,\n baseURL: (this as any).baseURL ?? '',\n params: body,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n throw error\n }\n ) as APIPromise<ChatCompletion>\n\n return wrappedPromise\n }\n }\n\n}\n\nexport default PostHogOpenAI\n","import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'\nimport type {\n LanguageModelV1,\n Experimental_LanguageModelV1Middleware as LanguageModelV1Middleware,\n LanguageModelV1Prompt,\n LanguageModelV1StreamPart,\n} from 'ai'\nimport { v4 as uuidv4 } from 'uuid'\nimport { PostHog } from 'posthog-node'\nimport { sendEventToPosthog } from '../utils'\n\ninterface CreateInstrumentationMiddlewareOptions {\n posthogDistinctId?: string\n posthogTraceId: string\n posthogProperties?: Record<string, any>\n posthogPrivacyMode?: boolean\n posthogGroups?: Record<string, any>\n}\n\ninterface PostHogInput {\n content: string\n role: string\n}\n\nconst mapVercelParams = (params: any): Record<string, any> => {\n return {\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n top_p: params.topP,\n frequency_penalty: params.frequencyPenalty,\n presence_penalty: params.presencePenalty,\n stop: params.stopSequences,\n stream: params.stream,\n }\n}\n\nconst mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {\n return prompt.map((p) => {\n let content = ''\n if (Array.isArray(p.content)) {\n content = p.content\n .map((c) => {\n if (c.type === 'text') {\n return c.text\n }\n return ''\n })\n .join('')\n } else {\n content = p.content\n }\n return {\n role: p.role,\n content,\n }\n })\n}\n\nexport const createInstrumentationMiddleware = (\n phClient: PostHog,\n model: LanguageModelV1,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1Middleware => {\n const middleware: LanguageModelV1Middleware = {\n wrapGenerate: async ({ doGenerate, params }) => {\n const startTime = Date.now()\n let mergedParams = {\n ...options,\n ...mapVercelParams(params),\n }\n try {\n const result = await doGenerate()\n const latency = (Date.now() - startTime) / 1000\n\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [{ content: result.text, role: 'assistant' }],\n latency,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 200,\n usage: {\n inputTokens: result.usage.promptTokens,\n outputTokens: result.usage.completionTokens,\n },\n })\n\n return result\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [],\n latency: 0,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n throw error\n }\n },\n\n wrapStream: async ({ doStream, params }) => {\n const startTime = Date.now()\n let generatedText = ''\n let usage: { inputTokens?: number; outputTokens?: number } = {}\n let mergedParams = {\n ...options,\n ...mapVercelParams(params),\n }\n try {\n const { stream, ...rest } = await doStream()\n\n const transformStream = new TransformStream<LanguageModelV1StreamPart, LanguageModelV1StreamPart>({\n transform(chunk, controller) {\n if (chunk.type === 'text-delta') {\n generatedText += chunk.textDelta\n }\n if (chunk.type === 'finish') {\n usage = {\n inputTokens: chunk.usage?.promptTokens,\n outputTokens: chunk.usage?.completionTokens,\n }\n }\n controller.enqueue(chunk)\n },\n\n flush() {\n const latency = (Date.now() - startTime) / 1000\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [{ content: generatedText, role: 'assistant' }],\n latency,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 200,\n usage,\n })\n },\n })\n\n return {\n stream: stream.pipeThrough(transformStream),\n ...rest,\n }\n } catch (error) {\n sendEventToPosthog({\n client: phClient,\n distinctId: options.posthogDistinctId,\n traceId: options.posthogTraceId,\n model: model.modelId,\n provider: 'vercel',\n input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),\n output: [],\n latency: 0,\n baseURL: '',\n params: mergedParams as any,\n httpStatus: 500,\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n })\n throw error\n }\n },\n }\n\n return middleware\n}\n\nexport const wrapVercelLanguageModel = (\n model: LanguageModelV1,\n phClient: PostHog,\n options: CreateInstrumentationMiddlewareOptions\n): LanguageModelV1 => {\n const traceId = options.posthogTraceId ?? uuidv4()\n const middleware = createInstrumentationMiddleware(phClient, model, {\n ...options,\n posthogTraceId: traceId,\n posthogDistinctId: options.posthogDistinctId ?? traceId,\n })\n\n const wrappedModel = wrapLanguageModel({\n model,\n middleware,\n })\n\n return wrappedModel\n}\n"],"names":["getModelParams","params","modelParams","paramKeys","key","undefined","mergeSystemPrompt","provider","messages","system","systemMessage","role","content","withPrivacyMode","client","privacyMode","input","privacy_mode","sendEventToPosthog","distinctId","traceId","model","output","latency","baseURL","httpStatus","usage","capture","event","properties","$ai_provider","$ai_model","$ai_model_parameters","$ai_input","posthogPrivacyMode","$ai_output_choices","$ai_http_status","$ai_input_tokens","inputTokens","$ai_output_tokens","outputTokens","$ai_latency","$ai_trace_id","$ai_base_url","posthogProperties","$process_person_profile","groups","posthogGroups","PostHogOpenAI","OpenAIOrignal","constructor","config","posthog","openAIConfig","phClient","chat","WrappedChat","Chat","parentClient","completions","WrappedCompletions","Completions","create","body","options","posthogDistinctId","posthogTraceId","openAIParams","uuidv4","startTime","Date","now","parentPromise","stream","then","value","passThroughStream","PassThrough","objectMode","accumulatedContent","openAIStream","chunk","delta","choices","prompt_tokens","completion_tokens","write","end","error","emit","wrappedPromise","result","message","mapVercelParams","temperature","max_tokens","maxTokens","top_p","topP","frequency_penalty","frequencyPenalty","presence_penalty","presencePenalty","stop","stopSequences","mapVercelPrompt","prompt","map","p","Array","isArray","c","type","text","join","createInstrumentationMiddleware","middleware","wrapGenerate","doGenerate","mergedParams","modelId","promptTokens","completionTokens","wrapStream","doStream","generatedText","rest","transformStream","TransformStream","transform","controller","textDelta","enqueue","flush","pipeThrough","wrapVercelLanguageModel","wrappedModel","wrapLanguageModel"],"mappings":"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"}
|
|
@@ -15,8 +15,8 @@ interface MonitoringOpenAIConfig {
|
|
|
15
15
|
}
|
|
16
16
|
export declare class PostHogOpenAI extends OpenAIOrignal {
|
|
17
17
|
private readonly phClient;
|
|
18
|
-
constructor(config: MonitoringOpenAIConfig);
|
|
19
18
|
chat: WrappedChat;
|
|
19
|
+
constructor(config: MonitoringOpenAIConfig);
|
|
20
20
|
}
|
|
21
21
|
export declare class WrappedChat extends OpenAIOrignal.Chat {
|
|
22
22
|
constructor(parentClient: PostHogOpenAI, phClient: PostHog);
|
|
@@ -9,10 +9,6 @@ export interface MonitoringParams {
|
|
|
9
9
|
posthogGroups?: Record<string, any>;
|
|
10
10
|
}
|
|
11
11
|
export declare const getModelParams: (params: ChatCompletionCreateParamsBase & MonitoringParams) => Record<string, any>;
|
|
12
|
-
export declare const getUsage: (response: any, provider: string) => {
|
|
13
|
-
input_tokens: number;
|
|
14
|
-
output_tokens: number;
|
|
15
|
-
};
|
|
16
12
|
/**
|
|
17
13
|
* Helper to format responses (non-streaming) for consumption, mirroring Python's openai vs. anthropic approach.
|
|
18
14
|
*/
|
|
@@ -42,8 +38,8 @@ export type SendEventToPosthogParams = {
|
|
|
42
38
|
baseURL: string;
|
|
43
39
|
httpStatus: number;
|
|
44
40
|
usage?: {
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
inputTokens?: number;
|
|
42
|
+
outputTokens?: number;
|
|
47
43
|
};
|
|
48
44
|
params: ChatCompletionCreateParamsBase & MonitoringParams;
|
|
49
45
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { LanguageModelV1, Experimental_LanguageModelV1Middleware as LanguageModelV1Middleware } from 'ai';
|
|
2
|
-
import
|
|
2
|
+
import { PostHog } from 'posthog-node';
|
|
3
3
|
interface CreateInstrumentationMiddlewareOptions {
|
|
4
4
|
posthogDistinctId?: string;
|
|
5
5
|
posthogTraceId: string;
|
|
6
6
|
posthogProperties?: Record<string, any>;
|
|
7
7
|
posthogPrivacyMode?: boolean;
|
|
8
|
-
posthogGroups?: string
|
|
8
|
+
posthogGroups?: Record<string, any>;
|
|
9
9
|
}
|
|
10
10
|
export declare const createInstrumentationMiddleware: (phClient: PostHog, model: LanguageModelV1, options: CreateInstrumentationMiddlewareOptions) => LanguageModelV1Middleware;
|
|
11
11
|
export declare const wrapVercelLanguageModel: (model: LanguageModelV1, phClient: PostHog, options: CreateInstrumentationMiddlewareOptions) => LanguageModelV1;
|
package/package.json
CHANGED
package/src/openai/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ interface MonitoringOpenAIConfig {
|
|
|
20
20
|
|
|
21
21
|
export class PostHogOpenAI extends OpenAIOrignal {
|
|
22
22
|
private readonly phClient: PostHog
|
|
23
|
+
public chat: WrappedChat
|
|
23
24
|
|
|
24
25
|
constructor(config: MonitoringOpenAIConfig) {
|
|
25
26
|
const { posthog, ...openAIConfig } = config
|
|
@@ -27,8 +28,6 @@ export class PostHogOpenAI extends OpenAIOrignal {
|
|
|
27
28
|
this.phClient = posthog
|
|
28
29
|
this.chat = new WrappedChat(this, this.phClient)
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
-
public chat: WrappedChat
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export class WrappedChat extends OpenAIOrignal.Chat {
|
|
@@ -89,21 +88,21 @@ export class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
89
88
|
return parentPromise.then((value) => {
|
|
90
89
|
const passThroughStream = new PassThrough({ objectMode: true })
|
|
91
90
|
let accumulatedContent = ''
|
|
92
|
-
let usage: {
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
let usage: { inputTokens: number; outputTokens: number } = {
|
|
92
|
+
inputTokens: 0,
|
|
93
|
+
outputTokens: 0,
|
|
95
94
|
}
|
|
96
95
|
if ('tee' in value) {
|
|
97
|
-
const openAIStream = value
|
|
98
|
-
|
|
96
|
+
const openAIStream = value;
|
|
97
|
+
(async () => {
|
|
99
98
|
try {
|
|
100
99
|
for await (const chunk of openAIStream) {
|
|
101
100
|
const delta = chunk?.choices?.[0]?.delta?.content ?? ''
|
|
102
101
|
accumulatedContent += delta
|
|
103
102
|
if (chunk.usage) {
|
|
104
103
|
usage = {
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
105
|
+
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
107
106
|
}
|
|
108
107
|
}
|
|
109
108
|
passThroughStream.write(chunk)
|
|
@@ -115,7 +114,7 @@ export class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
115
114
|
traceId,
|
|
116
115
|
model: openAIParams.model,
|
|
117
116
|
provider: 'openai',
|
|
118
|
-
input:
|
|
117
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
119
118
|
output: [{ content: accumulatedContent, role: 'assistant' }],
|
|
120
119
|
latency,
|
|
121
120
|
baseURL: (this as any).baseURL ?? '',
|
|
@@ -132,15 +131,15 @@ export class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
132
131
|
traceId,
|
|
133
132
|
model: openAIParams.model,
|
|
134
133
|
provider: 'openai',
|
|
135
|
-
input:
|
|
134
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
136
135
|
output: [],
|
|
137
136
|
latency: 0,
|
|
138
137
|
baseURL: (this as any).baseURL ?? '',
|
|
139
138
|
params: body,
|
|
140
139
|
httpStatus: 500,
|
|
141
140
|
usage: {
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
inputTokens: 0,
|
|
142
|
+
outputTokens: 0,
|
|
144
143
|
},
|
|
145
144
|
})
|
|
146
145
|
passThroughStream.emit('error', error)
|
|
@@ -160,15 +159,15 @@ export class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
160
159
|
traceId,
|
|
161
160
|
model: openAIParams.model,
|
|
162
161
|
provider: 'openai',
|
|
163
|
-
input:
|
|
162
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
164
163
|
output: [{ content: result.choices[0].message.content, role: 'assistant' }],
|
|
165
164
|
latency,
|
|
166
165
|
baseURL: (this as any).baseURL ?? '',
|
|
167
166
|
params: body,
|
|
168
167
|
httpStatus: 200,
|
|
169
168
|
usage: {
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
170
|
+
outputTokens: result.usage?.completion_tokens ?? 0,
|
|
172
171
|
},
|
|
173
172
|
})
|
|
174
173
|
}
|
|
@@ -181,15 +180,15 @@ export class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
181
180
|
traceId,
|
|
182
181
|
model: openAIParams.model,
|
|
183
182
|
provider: 'openai',
|
|
184
|
-
input:
|
|
183
|
+
input: mergeSystemPrompt(openAIParams, 'openai'),
|
|
185
184
|
output: [],
|
|
186
185
|
latency: 0,
|
|
187
186
|
baseURL: (this as any).baseURL ?? '',
|
|
188
187
|
params: body,
|
|
189
188
|
httpStatus: 500,
|
|
190
189
|
usage: {
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
inputTokens: 0,
|
|
191
|
+
outputTokens: 0,
|
|
193
192
|
},
|
|
194
193
|
})
|
|
195
194
|
throw error
|
|
@@ -199,6 +198,7 @@ export class WrappedCompletions extends OpenAIOrignal.Chat.Completions {
|
|
|
199
198
|
return wrappedPromise
|
|
200
199
|
}
|
|
201
200
|
}
|
|
201
|
+
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
export default PostHogOpenAI
|
package/src/utils.ts
CHANGED
|
@@ -34,26 +34,6 @@ export const getModelParams = (params: ChatCompletionCreateParamsBase & Monitori
|
|
|
34
34
|
return modelParams
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export const getUsage = (response: any, provider: string): { input_tokens: number; output_tokens: number } => {
|
|
38
|
-
if (!response?.usage) {
|
|
39
|
-
return { input_tokens: 0, output_tokens: 0 }
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (provider === 'anthropic') {
|
|
43
|
-
return {
|
|
44
|
-
input_tokens: response.usage.input_tokens ?? 0,
|
|
45
|
-
output_tokens: response.usage.output_tokens ?? 0,
|
|
46
|
-
}
|
|
47
|
-
} else if (provider === 'openai') {
|
|
48
|
-
return {
|
|
49
|
-
input_tokens: response.usage.prompt_tokens ?? 0,
|
|
50
|
-
output_tokens: response.usage.completion_tokens ?? 0,
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return { input_tokens: 0, output_tokens: 0 }
|
|
55
|
-
}
|
|
56
|
-
|
|
57
37
|
/**
|
|
58
38
|
* Helper to format responses (non-streaming) for consumption, mirroring Python's openai vs. anthropic approach.
|
|
59
39
|
*/
|
|
@@ -123,7 +103,7 @@ export type SendEventToPosthogParams = {
|
|
|
123
103
|
latency: number
|
|
124
104
|
baseURL: string
|
|
125
105
|
httpStatus: number
|
|
126
|
-
usage?: {
|
|
106
|
+
usage?: { inputTokens?: number; outputTokens?: number }
|
|
127
107
|
params: ChatCompletionCreateParamsBase & MonitoringParams
|
|
128
108
|
}
|
|
129
109
|
|
|
@@ -152,8 +132,8 @@ export const sendEventToPosthog = ({
|
|
|
152
132
|
$ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, input),
|
|
153
133
|
$ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, output),
|
|
154
134
|
$ai_http_status: httpStatus,
|
|
155
|
-
$ai_input_tokens: usage.
|
|
156
|
-
$ai_output_tokens: usage.
|
|
135
|
+
$ai_input_tokens: usage.inputTokens ?? 0,
|
|
136
|
+
$ai_output_tokens: usage.outputTokens ?? 0,
|
|
157
137
|
$ai_latency: latency,
|
|
158
138
|
$ai_trace_id: traceId,
|
|
159
139
|
$ai_base_url: baseURL,
|
|
@@ -163,4 +143,4 @@ export const sendEventToPosthog = ({
|
|
|
163
143
|
groups: params.posthogGroups,
|
|
164
144
|
})
|
|
165
145
|
}
|
|
166
|
-
}
|
|
146
|
+
}
|
package/src/vercel/middleware.ts
CHANGED
|
@@ -2,10 +2,11 @@ import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'
|
|
|
2
2
|
import type {
|
|
3
3
|
LanguageModelV1,
|
|
4
4
|
Experimental_LanguageModelV1Middleware as LanguageModelV1Middleware,
|
|
5
|
+
LanguageModelV1Prompt,
|
|
5
6
|
LanguageModelV1StreamPart,
|
|
6
7
|
} from 'ai'
|
|
7
8
|
import { v4 as uuidv4 } from 'uuid'
|
|
8
|
-
import
|
|
9
|
+
import { PostHog } from 'posthog-node'
|
|
9
10
|
import { sendEventToPosthog } from '../utils'
|
|
10
11
|
|
|
11
12
|
interface CreateInstrumentationMiddlewareOptions {
|
|
@@ -13,7 +14,46 @@ interface CreateInstrumentationMiddlewareOptions {
|
|
|
13
14
|
posthogTraceId: string
|
|
14
15
|
posthogProperties?: Record<string, any>
|
|
15
16
|
posthogPrivacyMode?: boolean
|
|
16
|
-
posthogGroups?: string
|
|
17
|
+
posthogGroups?: Record<string, any>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface PostHogInput {
|
|
21
|
+
content: string
|
|
22
|
+
role: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const mapVercelParams = (params: any): Record<string, any> => {
|
|
26
|
+
return {
|
|
27
|
+
temperature: params.temperature,
|
|
28
|
+
max_tokens: params.maxTokens,
|
|
29
|
+
top_p: params.topP,
|
|
30
|
+
frequency_penalty: params.frequencyPenalty,
|
|
31
|
+
presence_penalty: params.presencePenalty,
|
|
32
|
+
stop: params.stopSequences,
|
|
33
|
+
stream: params.stream,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {
|
|
38
|
+
return prompt.map((p) => {
|
|
39
|
+
let content = ''
|
|
40
|
+
if (Array.isArray(p.content)) {
|
|
41
|
+
content = p.content
|
|
42
|
+
.map((c) => {
|
|
43
|
+
if (c.type === 'text') {
|
|
44
|
+
return c.text
|
|
45
|
+
}
|
|
46
|
+
return ''
|
|
47
|
+
})
|
|
48
|
+
.join('')
|
|
49
|
+
} else {
|
|
50
|
+
content = p.content
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
role: p.role,
|
|
54
|
+
content,
|
|
55
|
+
}
|
|
56
|
+
})
|
|
17
57
|
}
|
|
18
58
|
|
|
19
59
|
export const createInstrumentationMiddleware = (
|
|
@@ -24,7 +64,10 @@ export const createInstrumentationMiddleware = (
|
|
|
24
64
|
const middleware: LanguageModelV1Middleware = {
|
|
25
65
|
wrapGenerate: async ({ doGenerate, params }) => {
|
|
26
66
|
const startTime = Date.now()
|
|
27
|
-
|
|
67
|
+
let mergedParams = {
|
|
68
|
+
...options,
|
|
69
|
+
...mapVercelParams(params),
|
|
70
|
+
}
|
|
28
71
|
try {
|
|
29
72
|
const result = await doGenerate()
|
|
30
73
|
const latency = (Date.now() - startTime) / 1000
|
|
@@ -35,15 +78,15 @@ export const createInstrumentationMiddleware = (
|
|
|
35
78
|
traceId: options.posthogTraceId,
|
|
36
79
|
model: model.modelId,
|
|
37
80
|
provider: 'vercel',
|
|
38
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
81
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
39
82
|
output: [{ content: result.text, role: 'assistant' }],
|
|
40
83
|
latency,
|
|
41
84
|
baseURL: '',
|
|
42
|
-
params:
|
|
85
|
+
params: mergedParams as any,
|
|
43
86
|
httpStatus: 200,
|
|
44
87
|
usage: {
|
|
45
|
-
|
|
46
|
-
|
|
88
|
+
inputTokens: result.usage.promptTokens,
|
|
89
|
+
outputTokens: result.usage.completionTokens,
|
|
47
90
|
},
|
|
48
91
|
})
|
|
49
92
|
|
|
@@ -55,15 +98,15 @@ export const createInstrumentationMiddleware = (
|
|
|
55
98
|
traceId: options.posthogTraceId,
|
|
56
99
|
model: model.modelId,
|
|
57
100
|
provider: 'vercel',
|
|
58
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
101
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
59
102
|
output: [],
|
|
60
103
|
latency: 0,
|
|
61
104
|
baseURL: '',
|
|
62
|
-
params:
|
|
105
|
+
params: mergedParams as any,
|
|
63
106
|
httpStatus: 500,
|
|
64
107
|
usage: {
|
|
65
|
-
|
|
66
|
-
|
|
108
|
+
inputTokens: 0,
|
|
109
|
+
outputTokens: 0,
|
|
67
110
|
},
|
|
68
111
|
})
|
|
69
112
|
throw error
|
|
@@ -73,8 +116,11 @@ export const createInstrumentationMiddleware = (
|
|
|
73
116
|
wrapStream: async ({ doStream, params }) => {
|
|
74
117
|
const startTime = Date.now()
|
|
75
118
|
let generatedText = ''
|
|
76
|
-
let usage: {
|
|
77
|
-
|
|
119
|
+
let usage: { inputTokens?: number; outputTokens?: number } = {}
|
|
120
|
+
let mergedParams = {
|
|
121
|
+
...options,
|
|
122
|
+
...mapVercelParams(params),
|
|
123
|
+
}
|
|
78
124
|
try {
|
|
79
125
|
const { stream, ...rest } = await doStream()
|
|
80
126
|
|
|
@@ -85,8 +131,8 @@ export const createInstrumentationMiddleware = (
|
|
|
85
131
|
}
|
|
86
132
|
if (chunk.type === 'finish') {
|
|
87
133
|
usage = {
|
|
88
|
-
|
|
89
|
-
|
|
134
|
+
inputTokens: chunk.usage?.promptTokens,
|
|
135
|
+
outputTokens: chunk.usage?.completionTokens,
|
|
90
136
|
}
|
|
91
137
|
}
|
|
92
138
|
controller.enqueue(chunk)
|
|
@@ -100,11 +146,11 @@ export const createInstrumentationMiddleware = (
|
|
|
100
146
|
traceId: options.posthogTraceId,
|
|
101
147
|
model: model.modelId,
|
|
102
148
|
provider: 'vercel',
|
|
103
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
149
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
104
150
|
output: [{ content: generatedText, role: 'assistant' }],
|
|
105
151
|
latency,
|
|
106
152
|
baseURL: '',
|
|
107
|
-
params:
|
|
153
|
+
params: mergedParams as any,
|
|
108
154
|
httpStatus: 200,
|
|
109
155
|
usage,
|
|
110
156
|
})
|
|
@@ -122,15 +168,15 @@ export const createInstrumentationMiddleware = (
|
|
|
122
168
|
traceId: options.posthogTraceId,
|
|
123
169
|
model: model.modelId,
|
|
124
170
|
provider: 'vercel',
|
|
125
|
-
input: options.posthogPrivacyMode ? '' : params.prompt,
|
|
171
|
+
input: options.posthogPrivacyMode ? '' : mapVercelPrompt(params.prompt),
|
|
126
172
|
output: [],
|
|
127
173
|
latency: 0,
|
|
128
174
|
baseURL: '',
|
|
129
|
-
params:
|
|
175
|
+
params: mergedParams as any,
|
|
130
176
|
httpStatus: 500,
|
|
131
177
|
usage: {
|
|
132
|
-
|
|
133
|
-
|
|
178
|
+
inputTokens: 0,
|
|
179
|
+
outputTokens: 0,
|
|
134
180
|
},
|
|
135
181
|
})
|
|
136
182
|
throw error
|