@posthog/ai 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/utils.ts CHANGED
@@ -7,7 +7,7 @@ type ChatCompletionCreateParamsBase = OpenAIOrignal.Chat.Completions.ChatComplet
7
7
  type MessageCreateParams = AnthropicOriginal.Messages.MessageCreateParams
8
8
 
9
9
  // limit large outputs by truncating to 200kb (approx 200k bytes)
10
- const MAX_OUTPUT_SIZE = 200000
10
+ export const MAX_OUTPUT_SIZE = 200000
11
11
  const STRING_FORMAT = 'utf8'
12
12
 
13
13
  export interface MonitoringParams {
@@ -19,6 +19,7 @@ export interface MonitoringParams {
19
19
  posthogModelOverride?: string
20
20
  posthogProviderOverride?: string
21
21
  posthogCostOverride?: CostOverride
22
+ fullDebug?: boolean
22
23
  }
23
24
 
24
25
  export interface CostOverride {
@@ -148,6 +149,7 @@ export type SendEventToPosthogParams = {
148
149
  isError?: boolean
149
150
  error?: string
150
151
  tools?: any
152
+ fullDebug?: boolean
151
153
  }
152
154
 
153
155
  function sanitizeValues(obj: any): any {
@@ -181,6 +183,7 @@ export const sendEventToPosthog = ({
181
183
  isError = false,
182
184
  error,
183
185
  tools,
186
+ fullDebug = false,
184
187
  }: SendEventToPosthogParams): void => {
185
188
  if (client.capture) {
186
189
  // sanitize input and output for UTF-8 validity
@@ -212,28 +215,35 @@ export const sendEventToPosthog = ({
212
215
  ...(usage.cacheCreationInputTokens ? { $ai_cache_creation_input_tokens: usage.cacheCreationInputTokens } : {}),
213
216
  }
214
217
 
218
+ const properties = {
219
+ $ai_provider: params.posthogProviderOverride ?? provider,
220
+ $ai_model: params.posthogModelOverride ?? model,
221
+ $ai_model_parameters: getModelParams(params),
222
+ $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeInput),
223
+ $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeOutput),
224
+ $ai_http_status: httpStatus,
225
+ $ai_input_tokens: usage.inputTokens ?? 0,
226
+ $ai_output_tokens: usage.outputTokens ?? 0,
227
+ ...additionalTokenValues,
228
+ $ai_latency: latency,
229
+ $ai_trace_id: traceId,
230
+ $ai_base_url: baseURL,
231
+ ...params.posthogProperties,
232
+ ...(distinctId ? {} : { $process_person_profile: false }),
233
+ ...(tools ? { $ai_tools: tools } : {}),
234
+ ...errorData,
235
+ ...costOverrideData,
236
+ }
237
+
238
+ if (fullDebug) {
239
+ // @ts-ignore
240
+ console.log('Sending event to PostHog', properties)
241
+ }
242
+
215
243
  client.capture({
216
244
  distinctId: distinctId ?? traceId,
217
245
  event: '$ai_generation',
218
- properties: {
219
- $ai_provider: params.posthogProviderOverride ?? provider,
220
- $ai_model: params.posthogModelOverride ?? model,
221
- $ai_model_parameters: getModelParams(params),
222
- $ai_input: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeInput),
223
- $ai_output_choices: withPrivacyMode(client, params.posthogPrivacyMode ?? false, safeOutput),
224
- $ai_http_status: httpStatus,
225
- $ai_input_tokens: usage.inputTokens ?? 0,
226
- $ai_output_tokens: usage.outputTokens ?? 0,
227
- ...additionalTokenValues,
228
- $ai_latency: latency,
229
- $ai_trace_id: traceId,
230
- $ai_base_url: baseURL,
231
- ...params.posthogProperties,
232
- ...(distinctId ? {} : { $process_person_profile: false }),
233
- ...(tools ? { $ai_tools: tools } : {}),
234
- ...errorData,
235
- ...costOverrideData,
236
- },
246
+ properties,
237
247
  groups: params.posthogGroups,
238
248
  })
239
249
  }
@@ -2,7 +2,8 @@ import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'
2
2
  import type { LanguageModelV1, LanguageModelV1Middleware, LanguageModelV1Prompt, LanguageModelV1StreamPart } from 'ai'
3
3
  import { v4 as uuidv4 } from 'uuid'
4
4
  import { PostHog } from 'posthog-node'
5
- import { CostOverride, sendEventToPosthog, truncate } from '../utils'
5
+ import { CostOverride, sendEventToPosthog, truncate, MAX_OUTPUT_SIZE } from '../utils'
6
+ import { Buffer } from 'buffer'
6
7
 
7
8
  interface ClientOptions {
8
9
  posthogDistinctId?: string
@@ -13,6 +14,7 @@ interface ClientOptions {
13
14
  posthogModelOverride?: string
14
15
  posthogProviderOverride?: string
15
16
  posthogCostOverride?: CostOverride
17
+ fullDebug?: boolean
16
18
  }
17
19
 
18
20
  interface CreateInstrumentationMiddlewareOptions {
@@ -24,6 +26,7 @@ interface CreateInstrumentationMiddlewareOptions {
24
26
  posthogModelOverride?: string
25
27
  posthogProviderOverride?: string
26
28
  posthogCostOverride?: CostOverride
29
+ fullDebug?: boolean
27
30
  }
28
31
 
29
32
  interface PostHogInput {
@@ -58,7 +61,9 @@ const mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {
58
61
  } else {
59
62
  promptsArray = prompt
60
63
  }
61
- return promptsArray.map((p) => {
64
+
65
+ // Map and truncate individual content
66
+ const inputs: PostHogInput[] = promptsArray.map((p) => {
62
67
  let content = {}
63
68
  if (Array.isArray(p.content)) {
64
69
  content = p.content.map((c: any) => {
@@ -119,6 +124,21 @@ const mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {
119
124
  content,
120
125
  }
121
126
  })
127
+ try {
128
+ // Trim the inputs array until its JSON size fits within MAX_OUTPUT_SIZE
129
+ let serialized = JSON.stringify(inputs)
130
+ while (Buffer.byteLength(serialized, 'utf8') > MAX_OUTPUT_SIZE && inputs.length > 0) {
131
+ // Remove oldest message
132
+ inputs.shift()
133
+ // add blank message to beginning of array
134
+ inputs.unshift({ role: 'assistant', content: '[removed message due to size limit]' })
135
+ serialized = JSON.stringify(inputs)
136
+ }
137
+ } catch (error) {
138
+ console.error('Error stringifying inputs')
139
+ return [{ role: 'posthog', content: 'An error occurred while processing your request. Please try again.' }]
140
+ }
141
+ return inputs
122
142
  }
123
143
 
124
144
  const mapVercelOutput = (result: any): PostHogInput[] => {
@@ -215,6 +235,7 @@ export const createInstrumentationMiddleware = (
215
235
  outputTokens: result.usage.completionTokens,
216
236
  ...additionalTokenValues,
217
237
  },
238
+ fullDebug: options.fullDebug,
218
239
  })
219
240
 
220
241
  return result
@@ -238,6 +259,7 @@ export const createInstrumentationMiddleware = (
238
259
  },
239
260
  isError: true,
240
261
  error: truncate(JSON.stringify(error)),
262
+ fullDebug: options.fullDebug,
241
263
  })
242
264
  throw error
243
265
  }
@@ -304,6 +326,7 @@ export const createInstrumentationMiddleware = (
304
326
  params: mergedParams as any,
305
327
  httpStatus: 200,
306
328
  usage,
329
+ fullDebug: options.fullDebug,
307
330
  })
308
331
  },
309
332
  })
@@ -331,6 +354,7 @@ export const createInstrumentationMiddleware = (
331
354
  },
332
355
  isError: true,
333
356
  error: truncate(JSON.stringify(error)),
357
+ fullDebug: options.fullDebug,
334
358
  })
335
359
  throw error
336
360
  }