@posthog/ai 2.3.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/lib/index.cjs.js +1107 -20
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +98 -1
- package/lib/index.esm.js +1088 -22
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-ai/src/anthropic/index.d.ts +28 -0
- package/lib/posthog-ai/src/index.d.ts +4 -0
- package/lib/posthog-ai/src/langchain/callbacks.d.ts +65 -0
- package/lib/posthog-ai/src/utils.d.ts +5 -3
- package/lib/posthog-ai/src/vercel/middleware.d.ts +7 -1
- package/package.json +10 -11
- package/src/anthropic/index.ts +195 -0
- package/src/index.ts +4 -0
- package/src/langchain/callbacks.ts +578 -0
- package/src/openai/azure.ts +7 -7
- package/src/openai/index.ts +6 -6
- package/src/utils.ts +10 -3
- package/src/vercel/middleware.ts +11 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@posthog/ai",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "PostHog Node.js AI integrations",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,27 +12,26 @@
|
|
|
12
12
|
"types": "lib/index.d.ts",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/jest": "^28.1.5",
|
|
16
15
|
"@types/node": "^18.0.0",
|
|
17
|
-
"jest": "^29.0.0",
|
|
18
16
|
"node-fetch": "^3.3.2",
|
|
19
|
-
"
|
|
20
|
-
"typescript": "^4.7.4",
|
|
21
|
-
"ai": "^4.0.0",
|
|
22
|
-
"openai": "^4.0.0"
|
|
17
|
+
"typescript": "^4.7.4"
|
|
23
18
|
},
|
|
24
19
|
"keywords": [
|
|
25
20
|
"posthog",
|
|
26
21
|
"ai",
|
|
27
22
|
"openai",
|
|
28
23
|
"anthropic",
|
|
29
|
-
"llm"
|
|
24
|
+
"llm",
|
|
25
|
+
"observability"
|
|
30
26
|
],
|
|
31
27
|
"dependencies": {
|
|
32
|
-
"
|
|
33
|
-
"
|
|
28
|
+
"@anthropic-ai/sdk": "^0.36.3",
|
|
29
|
+
"@langchain/core": "^0.3.37",
|
|
34
30
|
"ai": "^4.0.0",
|
|
35
|
-
"
|
|
31
|
+
"langchain": "^0.3.15",
|
|
32
|
+
"openai": "^4.0.0",
|
|
33
|
+
"uuid": "^11.0.5",
|
|
34
|
+
"zod": "^3.24.1"
|
|
36
35
|
},
|
|
37
36
|
"scripts": {
|
|
38
37
|
"test": "jest",
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import AnthropicOriginal from '@anthropic-ai/sdk'
|
|
2
|
+
import { PostHog } from 'posthog-node'
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid'
|
|
4
|
+
import { PassThrough } from 'stream'
|
|
5
|
+
import { formatResponseAnthropic, mergeSystemPrompt, MonitoringParams, sendEventToPosthog } from '../utils'
|
|
6
|
+
|
|
7
|
+
type MessageCreateParamsNonStreaming = AnthropicOriginal.Messages.MessageCreateParamsNonStreaming
|
|
8
|
+
type MessageCreateParamsStreaming = AnthropicOriginal.Messages.MessageCreateParamsStreaming
|
|
9
|
+
type MessageCreateParams = AnthropicOriginal.Messages.MessageCreateParams
|
|
10
|
+
type Message = AnthropicOriginal.Messages.Message
|
|
11
|
+
type RawMessageStreamEvent = AnthropicOriginal.Messages.RawMessageStreamEvent
|
|
12
|
+
type MessageCreateParamsBase = AnthropicOriginal.Messages.MessageCreateParams
|
|
13
|
+
|
|
14
|
+
import type { APIPromise, RequestOptions } from '@anthropic-ai/sdk/core'
|
|
15
|
+
import type { Stream } from '@anthropic-ai/sdk/streaming'
|
|
16
|
+
|
|
17
|
+
interface MonitoringAnthropicConfig {
|
|
18
|
+
apiKey: string
|
|
19
|
+
posthog: PostHog
|
|
20
|
+
baseURL?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class PostHogAnthropic extends AnthropicOriginal {
|
|
24
|
+
private readonly phClient: PostHog
|
|
25
|
+
public messages: WrappedMessages
|
|
26
|
+
|
|
27
|
+
constructor(config: MonitoringAnthropicConfig) {
|
|
28
|
+
const { posthog, ...anthropicConfig } = config
|
|
29
|
+
super(anthropicConfig)
|
|
30
|
+
this.phClient = posthog
|
|
31
|
+
this.messages = new WrappedMessages(this, this.phClient)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class WrappedMessages extends AnthropicOriginal.Messages {
|
|
36
|
+
private readonly phClient: PostHog
|
|
37
|
+
|
|
38
|
+
constructor(parentClient: PostHogAnthropic, phClient: PostHog) {
|
|
39
|
+
super(parentClient)
|
|
40
|
+
this.phClient = phClient
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public create(body: MessageCreateParamsNonStreaming, options?: RequestOptions): APIPromise<Message>
|
|
44
|
+
public create(
|
|
45
|
+
body: MessageCreateParamsStreaming & MonitoringParams,
|
|
46
|
+
options?: RequestOptions
|
|
47
|
+
): APIPromise<Stream<RawMessageStreamEvent>>
|
|
48
|
+
public create(
|
|
49
|
+
body: MessageCreateParamsBase & MonitoringParams,
|
|
50
|
+
options?: RequestOptions
|
|
51
|
+
): APIPromise<Stream<RawMessageStreamEvent> | Message>
|
|
52
|
+
public create(
|
|
53
|
+
body: MessageCreateParams & MonitoringParams,
|
|
54
|
+
options?: RequestOptions
|
|
55
|
+
): APIPromise<Message> | APIPromise<Stream<RawMessageStreamEvent>> {
|
|
56
|
+
const {
|
|
57
|
+
posthogDistinctId,
|
|
58
|
+
posthogTraceId,
|
|
59
|
+
posthogProperties,
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
61
|
+
posthogPrivacyMode = false,
|
|
62
|
+
posthogGroups,
|
|
63
|
+
...anthropicParams
|
|
64
|
+
} = body
|
|
65
|
+
|
|
66
|
+
const traceId = posthogTraceId ?? uuidv4()
|
|
67
|
+
const startTime = Date.now()
|
|
68
|
+
|
|
69
|
+
const parentPromise = super.create(anthropicParams, options)
|
|
70
|
+
|
|
71
|
+
if (anthropicParams.stream) {
|
|
72
|
+
return parentPromise.then((value) => {
|
|
73
|
+
const passThroughStream = new PassThrough({ objectMode: true })
|
|
74
|
+
let accumulatedContent = ''
|
|
75
|
+
const usage: { inputTokens: number; outputTokens: number } = {
|
|
76
|
+
inputTokens: 0,
|
|
77
|
+
outputTokens: 0,
|
|
78
|
+
}
|
|
79
|
+
if ('tee' in value) {
|
|
80
|
+
const anthropicStream = value
|
|
81
|
+
;(async () => {
|
|
82
|
+
try {
|
|
83
|
+
for await (const chunk of anthropicStream) {
|
|
84
|
+
if ('delta' in chunk) {
|
|
85
|
+
if ('text' in chunk.delta) {
|
|
86
|
+
const delta = chunk?.delta?.text ?? ''
|
|
87
|
+
accumulatedContent += delta
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (chunk.type == 'message_start') {
|
|
91
|
+
usage.inputTokens = chunk.message.usage.input_tokens ?? 0
|
|
92
|
+
}
|
|
93
|
+
if ('usage' in chunk) {
|
|
94
|
+
usage.outputTokens = chunk.usage.output_tokens ?? 0
|
|
95
|
+
}
|
|
96
|
+
passThroughStream.write(chunk)
|
|
97
|
+
}
|
|
98
|
+
const latency = (Date.now() - startTime) / 1000
|
|
99
|
+
sendEventToPosthog({
|
|
100
|
+
client: this.phClient,
|
|
101
|
+
distinctId: posthogDistinctId ?? traceId,
|
|
102
|
+
traceId,
|
|
103
|
+
model: anthropicParams.model,
|
|
104
|
+
provider: 'anthropic',
|
|
105
|
+
input: mergeSystemPrompt(anthropicParams, 'anthropic'),
|
|
106
|
+
output: [{ content: accumulatedContent, role: 'assistant' }],
|
|
107
|
+
latency,
|
|
108
|
+
baseURL: (this as any).baseURL ?? '',
|
|
109
|
+
params: body,
|
|
110
|
+
httpStatus: 200,
|
|
111
|
+
usage,
|
|
112
|
+
})
|
|
113
|
+
passThroughStream.end()
|
|
114
|
+
} catch (error: any) {
|
|
115
|
+
// error handling
|
|
116
|
+
sendEventToPosthog({
|
|
117
|
+
client: this.phClient,
|
|
118
|
+
distinctId: posthogDistinctId ?? traceId,
|
|
119
|
+
traceId,
|
|
120
|
+
model: anthropicParams.model,
|
|
121
|
+
provider: 'anthropic',
|
|
122
|
+
input: mergeSystemPrompt(anthropicParams, 'anthropic'),
|
|
123
|
+
output: [],
|
|
124
|
+
latency: 0,
|
|
125
|
+
baseURL: (this as any).baseURL ?? '',
|
|
126
|
+
params: body,
|
|
127
|
+
httpStatus: error?.status ? error.status : 500,
|
|
128
|
+
usage: {
|
|
129
|
+
inputTokens: 0,
|
|
130
|
+
outputTokens: 0,
|
|
131
|
+
},
|
|
132
|
+
isError: true,
|
|
133
|
+
error: JSON.stringify(error),
|
|
134
|
+
})
|
|
135
|
+
passThroughStream.emit('error', error)
|
|
136
|
+
}
|
|
137
|
+
})()
|
|
138
|
+
}
|
|
139
|
+
return passThroughStream as unknown as Stream<RawMessageStreamEvent>
|
|
140
|
+
}) as APIPromise<Stream<RawMessageStreamEvent>>
|
|
141
|
+
} else {
|
|
142
|
+
const wrappedPromise = parentPromise.then(
|
|
143
|
+
(result) => {
|
|
144
|
+
if ('content' in result) {
|
|
145
|
+
const latency = (Date.now() - startTime) / 1000
|
|
146
|
+
sendEventToPosthog({
|
|
147
|
+
client: this.phClient,
|
|
148
|
+
distinctId: posthogDistinctId ?? traceId,
|
|
149
|
+
traceId,
|
|
150
|
+
model: anthropicParams.model,
|
|
151
|
+
provider: 'anthropic',
|
|
152
|
+
input: mergeSystemPrompt(anthropicParams, 'anthropic'),
|
|
153
|
+
output: formatResponseAnthropic(result),
|
|
154
|
+
latency,
|
|
155
|
+
baseURL: (this as any).baseURL ?? '',
|
|
156
|
+
params: body,
|
|
157
|
+
httpStatus: 200,
|
|
158
|
+
usage: {
|
|
159
|
+
inputTokens: result.usage.input_tokens ?? 0,
|
|
160
|
+
outputTokens: result.usage.output_tokens ?? 0,
|
|
161
|
+
},
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
return result
|
|
165
|
+
},
|
|
166
|
+
(error: any) => {
|
|
167
|
+
sendEventToPosthog({
|
|
168
|
+
client: this.phClient,
|
|
169
|
+
distinctId: posthogDistinctId ?? traceId,
|
|
170
|
+
traceId,
|
|
171
|
+
model: anthropicParams.model,
|
|
172
|
+
provider: 'anthropic',
|
|
173
|
+
input: mergeSystemPrompt(anthropicParams, 'anthropic'),
|
|
174
|
+
output: [],
|
|
175
|
+
latency: 0,
|
|
176
|
+
baseURL: (this as any).baseURL ?? '',
|
|
177
|
+
params: body,
|
|
178
|
+
httpStatus: error?.status ? error.status : 500,
|
|
179
|
+
usage: {
|
|
180
|
+
inputTokens: 0,
|
|
181
|
+
outputTokens: 0,
|
|
182
|
+
},
|
|
183
|
+
isError: true,
|
|
184
|
+
error: JSON.stringify(error),
|
|
185
|
+
})
|
|
186
|
+
throw error
|
|
187
|
+
}
|
|
188
|
+
) as APIPromise<Message>
|
|
189
|
+
|
|
190
|
+
return wrappedPromise
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export default PostHogAnthropic
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import PostHogOpenAI from './openai'
|
|
2
2
|
import PostHogAzureOpenAI from './openai/azure'
|
|
3
3
|
import { wrapVercelLanguageModel } from './vercel/middleware'
|
|
4
|
+
import PostHogAnthropic from './anthropic'
|
|
5
|
+
import { LangChainCallbackHandler } from './langchain/callbacks'
|
|
4
6
|
|
|
5
7
|
export { PostHogOpenAI as OpenAI }
|
|
6
8
|
export { PostHogAzureOpenAI as AzureOpenAI }
|
|
9
|
+
export { PostHogAnthropic as Anthropic }
|
|
7
10
|
export { wrapVercelLanguageModel as withTracing }
|
|
11
|
+
export { LangChainCallbackHandler }
|