@traccia2/sdk 0.0.5 → 0.0.7
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 +11 -11
- package/dist/integrations/auto-langchain.d.ts +4 -4
- package/dist/integrations/auto-langchain.d.ts.map +1 -1
- package/dist/integrations/auto-langchain.js +2 -2
- package/dist/integrations/auto-langchain.js.map +1 -1
- package/dist/integrations/index.d.ts +2 -1
- package/dist/integrations/index.d.ts.map +1 -1
- package/dist/integrations/index.js +4 -2
- package/dist/integrations/index.js.map +1 -1
- package/dist/integrations/langchain-callback.d.ts +12 -5
- package/dist/integrations/langchain-callback.d.ts.map +1 -1
- package/dist/integrations/langchain-callback.js +58 -39
- package/dist/integrations/langchain-callback.js.map +1 -1
- package/dist/integrations/langchain-callback.new.d.ts +62 -0
- package/dist/integrations/langchain-callback.new.d.ts.map +1 -0
- package/dist/integrations/langchain-callback.new.js +519 -0
- package/dist/integrations/langchain-callback.new.js.map +1 -0
- package/package.json +6 -1
- package/src/__tests__/integrations-langchain.test.ts +28 -28
- package/src/integrations/auto-langchain.ts +6 -6
- package/src/integrations/index.ts +2 -1
- package/src/integrations/langchain-callback.new.ts +810 -0
- package/src/integrations/langchain-callback.ts +68 -35
|
@@ -6,31 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { ISpan } from '../types';
|
|
8
8
|
import { getTracer } from '../auto';
|
|
9
|
-
|
|
10
|
-
// Try to import BaseCallbackHandler from different LangChain versions
|
|
11
|
-
let BaseCallbackHandler: any = class {
|
|
12
|
-
ignoreAgent = false;
|
|
13
|
-
ignoreChain = false;
|
|
14
|
-
ignoreLLM = false;
|
|
15
|
-
ignoreRetriever = false;
|
|
16
|
-
ignoreToolUse = false;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
// Try LangChain 0.2.x+
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
22
|
-
const { BaseCallbackHandler: Handler } = require('@langchain/core/callbacks/base');
|
|
23
|
-
BaseCallbackHandler = Handler;
|
|
24
|
-
} catch {
|
|
25
|
-
try {
|
|
26
|
-
// Try older LangChain versions
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
28
|
-
const { BaseCallbackHandler: Handler } = require('langchain/callbacks');
|
|
29
|
-
BaseCallbackHandler = Handler;
|
|
30
|
-
} catch {
|
|
31
|
-
// Fallback to basic implementation - user likely has LangChain installed
|
|
32
|
-
}
|
|
33
|
-
}
|
|
9
|
+
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
34
10
|
|
|
35
11
|
/**
|
|
36
12
|
* LangChain Callback Handler for Traccia SDK.
|
|
@@ -41,17 +17,19 @@ try {
|
|
|
41
17
|
*
|
|
42
18
|
* @example
|
|
43
19
|
* import { ChatOpenAI } from '@langchain/openai';
|
|
44
|
-
* import {
|
|
20
|
+
* import { TracciaCallbackHandler } from '@traccia/sdk/integrations';
|
|
45
21
|
*
|
|
46
|
-
* const handler = new
|
|
22
|
+
* const handler = new TracciaCallbackHandler();
|
|
47
23
|
* const model = new ChatOpenAI({ callbacks: [handler] });
|
|
48
24
|
*
|
|
49
25
|
* const response = await model.invoke({ input: 'Hello!' });
|
|
50
26
|
* // Automatically traced with spans for LLM calls, tokens, latency, etc.
|
|
51
27
|
*/
|
|
52
|
-
export class
|
|
28
|
+
export class TracciaCallbackHandler extends BaseCallbackHandler {
|
|
29
|
+
name = 'TracciaCallbackHandler';
|
|
53
30
|
private tracer = getTracer('langchain');
|
|
54
31
|
private spanStack: Map<string, ISpan> = new Map();
|
|
32
|
+
private streamingStartTimes: Record<string, Date> = {};
|
|
55
33
|
|
|
56
34
|
/**
|
|
57
35
|
* Extract model name from LLM instance, checking multiple property locations.
|
|
@@ -125,23 +103,47 @@ export class TraciaCallbackHandler extends BaseCallbackHandler {
|
|
|
125
103
|
if (span) {
|
|
126
104
|
try {
|
|
127
105
|
// Try multiple ways to get token usage
|
|
128
|
-
// OpenAI format
|
|
106
|
+
// OpenAI format and new @langchain/core format
|
|
129
107
|
const tokenUsage =
|
|
130
108
|
output?.llmOutput?.token_usage ||
|
|
109
|
+
output?.llmOutput?.tokenUsage ||
|
|
131
110
|
output?.token_usage ||
|
|
132
111
|
output?.metadata?.token_usage;
|
|
133
112
|
|
|
134
113
|
if (tokenUsage) {
|
|
135
|
-
|
|
136
|
-
|
|
114
|
+
// Handle standard token counts
|
|
115
|
+
const promptTokens = tokenUsage.prompt_tokens ?? tokenUsage.promptTokens;
|
|
116
|
+
const completionTokens = tokenUsage.completion_tokens ?? tokenUsage.completionTokens;
|
|
117
|
+
const totalTokens = tokenUsage.total_tokens ?? tokenUsage.totalTokens;
|
|
118
|
+
|
|
119
|
+
if (promptTokens !== undefined) {
|
|
120
|
+
span.setAttribute('llm.tokens.prompt', promptTokens);
|
|
137
121
|
}
|
|
138
|
-
if (
|
|
139
|
-
span.setAttribute('llm.tokens.completion',
|
|
122
|
+
if (completionTokens !== undefined) {
|
|
123
|
+
span.setAttribute('llm.tokens.completion', completionTokens);
|
|
140
124
|
}
|
|
141
|
-
|
|
142
|
-
if (totalTokens > 0) {
|
|
125
|
+
if (totalTokens !== undefined) {
|
|
143
126
|
span.setAttribute('llm.tokens.total', totalTokens);
|
|
144
127
|
}
|
|
128
|
+
|
|
129
|
+
// Handle detailed token breakdown for models like GPT-4o vision
|
|
130
|
+
// input_token_details contains breakdown of prompt token usage
|
|
131
|
+
if (tokenUsage.input_token_details && typeof tokenUsage.input_token_details === 'object') {
|
|
132
|
+
for (const [key, value] of Object.entries(tokenUsage.input_token_details)) {
|
|
133
|
+
if (typeof value === 'number') {
|
|
134
|
+
span.setAttribute(`llm.tokens.input_${key}`, value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// output_token_details contains breakdown of completion token usage
|
|
140
|
+
if (tokenUsage.output_token_details && typeof tokenUsage.output_token_details === 'object') {
|
|
141
|
+
for (const [key, value] of Object.entries(tokenUsage.output_token_details)) {
|
|
142
|
+
if (typeof value === 'number') {
|
|
143
|
+
span.setAttribute(`llm.tokens.output_${key}`, value);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
// Capture output text length
|
|
@@ -187,6 +189,29 @@ export class TraciaCallbackHandler extends BaseCallbackHandler {
|
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Handle LLM new token - called when a new token is generated during streaming.
|
|
194
|
+
* Tracks first token latency and token count for streaming scenarios.
|
|
195
|
+
*/
|
|
196
|
+
public async handleLLMNewToken(
|
|
197
|
+
_token: string,
|
|
198
|
+
_idx?: any,
|
|
199
|
+
runId?: string
|
|
200
|
+
): Promise<void> {
|
|
201
|
+
if (runId && !(runId in this.streamingStartTimes)) {
|
|
202
|
+
// Record the time of the first streaming token
|
|
203
|
+
this.streamingStartTimes[runId] = new Date();
|
|
204
|
+
const span = this.spanStack.get(runId);
|
|
205
|
+
if (span) {
|
|
206
|
+
try {
|
|
207
|
+
span.setAttribute('stream.first_token_generated', true);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
// Silently fail
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
190
215
|
/**
|
|
191
216
|
* Handle chain start - called when a chain begins execution.
|
|
192
217
|
*/
|
|
@@ -360,6 +385,14 @@ export class TraciaCallbackHandler extends BaseCallbackHandler {
|
|
|
360
385
|
return this.handleLLMError(error, runId);
|
|
361
386
|
}
|
|
362
387
|
|
|
388
|
+
public async onLLMNewToken(
|
|
389
|
+
_token: string,
|
|
390
|
+
idx?: any,
|
|
391
|
+
runId?: string
|
|
392
|
+
): Promise<void> {
|
|
393
|
+
return this.handleLLMNewToken(_token, idx, runId);
|
|
394
|
+
}
|
|
395
|
+
|
|
363
396
|
public async onChainStart(
|
|
364
397
|
chain: any,
|
|
365
398
|
inputs: any,
|