openlayer 0.16.2 → 0.17.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 +39 -0
- package/_shims/bun-runtime.js +1 -2
- package/_shims/bun-runtime.js.map +1 -1
- package/_shims/node-runtime.js +18 -9
- package/_shims/node-runtime.js.map +1 -1
- package/_shims/node-runtime.mjs.map +1 -1
- package/_shims/registry.js +2 -2
- package/_shims/registry.js.map +1 -1
- package/_shims/registry.mjs.map +1 -1
- package/_shims/web-runtime.js +1 -2
- package/_shims/web-runtime.js.map +1 -1
- package/_shims/web-runtime.mjs.map +1 -1
- package/core.d.ts +2 -4
- package/core.d.ts.map +1 -1
- package/core.js +9 -9
- package/core.js.map +1 -1
- package/core.mjs +4 -4
- package/core.mjs.map +1 -1
- package/error.js.map +1 -1
- package/error.mjs.map +1 -1
- package/index.js +17 -7
- package/index.js.map +1 -1
- package/index.mjs.map +1 -1
- package/internal/qs/stringify.js +1 -2
- package/internal/qs/stringify.js.map +1 -1
- package/internal/qs/stringify.mjs.map +1 -1
- package/internal/qs/utils.js +9 -9
- package/internal/qs/utils.js.map +1 -1
- package/internal/qs/utils.mjs.map +1 -1
- package/lib/core/cli.js +17 -7
- package/lib/core/cli.js.map +1 -1
- package/lib/core/cli.mjs.map +1 -1
- package/lib/core/openai-monitor.d.ts.map +1 -1
- package/lib/core/openai-monitor.js +1 -1
- package/lib/core/openai-monitor.js.map +1 -1
- package/lib/core/openai-monitor.mjs +1 -1
- package/lib/core/openai-monitor.mjs.map +1 -1
- package/lib/integrations/bedrockAgentTracer.js +49 -50
- package/lib/integrations/bedrockAgentTracer.js.map +1 -1
- package/lib/integrations/bedrockAgentTracer.mjs +48 -48
- package/lib/integrations/bedrockAgentTracer.mjs.map +1 -1
- package/lib/integrations/index.d.ts +5 -0
- package/lib/integrations/index.d.ts.map +1 -0
- package/lib/integrations/index.js +21 -0
- package/lib/integrations/index.js.map +1 -0
- package/lib/integrations/index.mjs +5 -0
- package/lib/integrations/index.mjs.map +1 -0
- package/lib/integrations/langchainCallback.d.ts +83 -27
- package/lib/integrations/langchainCallback.d.ts.map +1 -1
- package/lib/integrations/langchainCallback.js +597 -88
- package/lib/integrations/langchainCallback.js.map +1 -1
- package/lib/integrations/langchainCallback.mjs +599 -87
- package/lib/integrations/langchainCallback.mjs.map +1 -1
- package/lib/integrations/openAiTracer.js +1 -2
- package/lib/integrations/openAiTracer.js.map +1 -1
- package/lib/integrations/openAiTracer.mjs.map +1 -1
- package/lib/integrations/tracedTool.d.ts +66 -0
- package/lib/integrations/tracedTool.d.ts.map +1 -0
- package/lib/integrations/tracedTool.js +186 -0
- package/lib/integrations/tracedTool.js.map +1 -0
- package/lib/integrations/tracedTool.mjs +149 -0
- package/lib/integrations/tracedTool.mjs.map +1 -0
- package/lib/tracing/steps.d.ts +120 -1
- package/lib/tracing/steps.d.ts.map +1 -1
- package/lib/tracing/steps.js +128 -4
- package/lib/tracing/steps.js.map +1 -1
- package/lib/tracing/steps.mjs +119 -1
- package/lib/tracing/steps.mjs.map +1 -1
- package/lib/tracing/tracer.d.ts +69 -1
- package/lib/tracing/tracer.d.ts.map +1 -1
- package/lib/tracing/tracer.js +92 -18
- package/lib/tracing/tracer.js.map +1 -1
- package/lib/tracing/tracer.mjs +78 -10
- package/lib/tracing/tracer.mjs.map +1 -1
- package/package.json +3 -1
- package/resources/commits/commits.js +17 -7
- package/resources/commits/commits.js.map +1 -1
- package/resources/commits/test-results.js.map +1 -1
- package/resources/commits/test-results.mjs.map +1 -1
- package/resources/inference-pipelines/data.d.ts +8 -0
- package/resources/inference-pipelines/data.d.ts.map +1 -1
- package/resources/inference-pipelines/inference-pipelines.js +17 -7
- package/resources/inference-pipelines/inference-pipelines.js.map +1 -1
- package/resources/inference-pipelines/inference-pipelines.mjs.map +1 -1
- package/resources/inference-pipelines/test-results.js.map +1 -1
- package/resources/inference-pipelines/test-results.mjs.map +1 -1
- package/resources/projects/commits.js.map +1 -1
- package/resources/projects/commits.mjs.map +1 -1
- package/resources/projects/inference-pipelines.js.map +1 -1
- package/resources/projects/inference-pipelines.mjs.map +1 -1
- package/resources/projects/projects.js +17 -7
- package/resources/projects/projects.js.map +1 -1
- package/resources/projects/projects.mjs.map +1 -1
- package/resources/projects/tests.js.map +1 -1
- package/resources/projects/tests.mjs.map +1 -1
- package/resources/storage/storage.js +17 -7
- package/resources/storage/storage.js.map +1 -1
- package/shims/node.d.ts +0 -4
- package/shims/node.d.ts.map +1 -1
- package/shims/node.js +0 -25
- package/shims/node.js.map +1 -1
- package/shims/node.mjs +0 -1
- package/shims/node.mjs.map +1 -1
- package/shims/web.js +0 -25
- package/shims/web.js.map +1 -1
- package/shims/web.mjs +0 -1
- package/shims/web.mjs.map +1 -1
- package/src/core.ts +4 -4
- package/src/lib/core/openai-monitor.ts +1 -1
- package/src/lib/integrations/index.ts +4 -0
- package/src/lib/integrations/langchainCallback.ts +802 -88
- package/src/lib/integrations/tracedTool.ts +175 -0
- package/src/lib/tracing/index.d.ts +10 -0
- package/src/lib/tracing/steps.ts +218 -5
- package/src/lib/tracing/tracer.ts +153 -9
- package/src/resources/inference-pipelines/data.ts +10 -0
- package/src/uploads.ts +3 -2
- package/src/version.ts +1 -1
- package/uploads.d.ts +2 -2
- package/uploads.d.ts.map +1 -1
- package/uploads.js +3 -4
- package/uploads.js.map +1 -1
- package/uploads.mjs +1 -2
- package/uploads.mjs.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
- package/lib/tracing/enums.d.ts +0 -5
- package/lib/tracing/enums.d.ts.map +0 -1
- package/lib/tracing/enums.js +0 -9
- package/lib/tracing/enums.js.map +0 -1
- package/lib/tracing/enums.mjs +0 -6
- package/lib/tracing/enums.mjs.map +0 -1
- package/src/lib/tracing/enums.ts +0 -4
|
@@ -1,119 +1,628 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.OpenlayerHandler = void 0;
|
|
7
4
|
const base_1 = require("@langchain/core/callbacks/base");
|
|
8
5
|
const messages_1 = require("@langchain/core/messages");
|
|
9
|
-
const performance_now_1 = __importDefault(require("performance-now"));
|
|
10
6
|
const tracer_1 = require("../tracing/tracer.js");
|
|
11
7
|
const LANGCHAIN_TO_OPENLAYER_PROVIDER_MAP = {
|
|
12
8
|
openai: 'OpenAI',
|
|
13
9
|
'openai-chat': 'OpenAI',
|
|
14
10
|
'chat-ollama': 'Ollama',
|
|
15
11
|
vertexai: 'Google',
|
|
12
|
+
anthropic: 'Anthropic',
|
|
13
|
+
'azure-openai': 'Azure OpenAI',
|
|
14
|
+
cohere: 'Cohere',
|
|
15
|
+
huggingface: 'Hugging Face',
|
|
16
16
|
};
|
|
17
17
|
const PROVIDER_TO_STEP_NAME = {
|
|
18
18
|
OpenAI: 'OpenAI Chat Completion',
|
|
19
19
|
Ollama: 'Ollama Chat Completion',
|
|
20
20
|
Google: 'Google Vertex AI Chat Completion',
|
|
21
|
+
Anthropic: 'Anthropic Chat Completion',
|
|
22
|
+
'Azure OpenAI': 'Azure OpenAI Chat Completion',
|
|
23
|
+
Cohere: 'Cohere Chat Completion',
|
|
24
|
+
'Hugging Face': 'Hugging Face Chat Completion',
|
|
21
25
|
};
|
|
26
|
+
const LANGSMITH_HIDDEN_TAG = 'langsmith:hidden';
|
|
27
|
+
/**
|
|
28
|
+
* Comprehensive LangChain callback handler for Openlayer tracing.
|
|
29
|
+
*
|
|
30
|
+
* Supports all LangChain components:
|
|
31
|
+
* - LLMs and Chat Models (with streaming support)
|
|
32
|
+
* - Chains
|
|
33
|
+
* - Agents and Tools
|
|
34
|
+
* - Retrievers
|
|
35
|
+
* - Error handling and hierarchical tracking
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { OpenlayerHandler } from 'openlayer/lib/integrations/langchainCallback';
|
|
40
|
+
*
|
|
41
|
+
* const handler = new OpenlayerHandler({
|
|
42
|
+
* userId: 'user-123',
|
|
43
|
+
* sessionId: 'session-456',
|
|
44
|
+
* tags: ['production'],
|
|
45
|
+
* version: '1.0.0'
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* const model = new ChatOpenAI({
|
|
49
|
+
* callbacks: [handler]
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
22
53
|
class OpenlayerHandler extends base_1.BaseCallbackHandler {
|
|
23
|
-
constructor(
|
|
54
|
+
constructor(params) {
|
|
24
55
|
super();
|
|
25
56
|
this.name = 'OpenlayerHandler';
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
this.completionStartTimes = {};
|
|
58
|
+
this.promptToParentRunMap = new Map();
|
|
59
|
+
this.runMap = new Map();
|
|
60
|
+
this.sessionId = params?.sessionId;
|
|
61
|
+
this.userId = params?.userId;
|
|
62
|
+
this.tags = params?.tags ?? [];
|
|
63
|
+
this.traceMetadata = params?.traceMetadata;
|
|
64
|
+
this.version = params?.version;
|
|
65
|
+
}
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// LLM Handlers
|
|
68
|
+
// ============================================================================
|
|
69
|
+
async handleLLMNewToken(token, _idx, runId, _parentRunId, _tags, _fields) {
|
|
70
|
+
try {
|
|
71
|
+
// Track first token timing for streaming
|
|
72
|
+
if (runId && !(runId in this.completionStartTimes)) {
|
|
73
|
+
console.debug(`LLM first streaming token: ${runId}`);
|
|
74
|
+
this.completionStartTimes[runId] = new Date();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, name) {
|
|
82
|
+
try {
|
|
83
|
+
console.debug(`LLM start with ID: ${runId}`);
|
|
84
|
+
this.handleGenerationStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, name);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
88
|
+
}
|
|
37
89
|
}
|
|
38
90
|
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
91
|
+
try {
|
|
92
|
+
console.debug(`Chat model start with ID: ${runId}`);
|
|
93
|
+
const prompts = messages.flatMap((message) => message.map((m) => this.extractChatMessageContent(m)));
|
|
94
|
+
this.handleGenerationStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, name);
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async handleLLMEnd(output, runId, parentRunId) {
|
|
101
|
+
try {
|
|
102
|
+
console.debug(`LLM end with ID: ${runId}`);
|
|
103
|
+
if (output.generations.length === 0) {
|
|
104
|
+
console.debug('No generations found in LLM output');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const lastGeneration = output.generations[output.generations.length - 1];
|
|
108
|
+
if (!lastGeneration || lastGeneration.length === 0) {
|
|
109
|
+
console.debug('No responses found in last generation');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const lastResponse = lastGeneration[lastGeneration.length - 1];
|
|
113
|
+
const llmUsage = (lastResponse ? this.extractUsageMetadata(lastResponse) : undefined) ||
|
|
114
|
+
output.llmOutput?.['tokenUsage'];
|
|
115
|
+
const modelName = lastResponse ? this.extractModelNameFromMetadata(lastResponse) : undefined;
|
|
116
|
+
const usageDetails = {
|
|
117
|
+
input: llmUsage?.input_tokens ?? llmUsage?.promptTokens,
|
|
118
|
+
output: llmUsage?.output_tokens ?? llmUsage?.completionTokens,
|
|
119
|
+
total: llmUsage?.total_tokens ?? llmUsage?.totalTokens,
|
|
120
|
+
};
|
|
121
|
+
// Handle detailed token usage if available
|
|
122
|
+
if (llmUsage && 'input_token_details' in llmUsage) {
|
|
123
|
+
for (const [key, val] of Object.entries(llmUsage['input_token_details'] ?? {})) {
|
|
124
|
+
usageDetails[`input_${key}`] = val;
|
|
125
|
+
if ('input' in usageDetails && typeof val === 'number') {
|
|
126
|
+
usageDetails['input'] = Math.max(0, usageDetails['input'] - val);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (llmUsage && 'output_token_details' in llmUsage) {
|
|
131
|
+
for (const [key, val] of Object.entries(llmUsage['output_token_details'] ?? {})) {
|
|
132
|
+
usageDetails[`output_${key}`] = val;
|
|
133
|
+
if ('output' in usageDetails && typeof val === 'number') {
|
|
134
|
+
usageDetails['output'] = Math.max(0, usageDetails['output'] - val);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Extract clean output for dashboard display
|
|
139
|
+
const extractedOutput = lastResponse ?
|
|
140
|
+
'message' in lastResponse && lastResponse['message'] instanceof messages_1.BaseMessage ?
|
|
141
|
+
lastResponse['message'].content // Just the content, not the full message object
|
|
142
|
+
: lastResponse.text || ''
|
|
143
|
+
: '';
|
|
144
|
+
// Extract raw output (complete response object for debugging/analysis)
|
|
145
|
+
const rawOutput = lastResponse ?
|
|
146
|
+
JSON.stringify({
|
|
147
|
+
generation: lastResponse,
|
|
148
|
+
llmOutput: output.llmOutput,
|
|
149
|
+
fullResponse: output,
|
|
150
|
+
}, null, 2)
|
|
151
|
+
: null;
|
|
152
|
+
this.handleStepEnd({
|
|
153
|
+
runId,
|
|
154
|
+
output: extractedOutput,
|
|
155
|
+
rawOutput,
|
|
156
|
+
...(modelName && { modelName }),
|
|
157
|
+
usageDetails,
|
|
158
|
+
...(runId in this.completionStartTimes && { completionStartTime: this.completionStartTimes[runId] }),
|
|
159
|
+
});
|
|
160
|
+
if (runId in this.completionStartTimes) {
|
|
161
|
+
delete this.completionStartTimes[runId];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async handleLLMError(err, runId, parentRunId) {
|
|
169
|
+
try {
|
|
170
|
+
console.debug(`LLM error ${err} with ID: ${runId}`);
|
|
171
|
+
const azureRefusalError = this.parseAzureRefusalError(err);
|
|
172
|
+
this.handleStepEnd({
|
|
173
|
+
runId,
|
|
174
|
+
error: err.toString() + azureRefusalError,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// Chain Handlers
|
|
183
|
+
// ============================================================================
|
|
184
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name) {
|
|
185
|
+
try {
|
|
186
|
+
console.debug(`Chain start with ID: ${runId}`);
|
|
187
|
+
const runName = name ?? chain.id.at(-1)?.toString() ?? 'Langchain Chain';
|
|
188
|
+
this.registerOpenlayerPrompt(parentRunId, metadata);
|
|
189
|
+
// Process inputs to handle different formats
|
|
190
|
+
let finalInput = inputs;
|
|
191
|
+
if (typeof inputs === 'object' &&
|
|
192
|
+
'input' in inputs &&
|
|
193
|
+
Array.isArray(inputs['input']) &&
|
|
194
|
+
inputs['input'].every((m) => m instanceof messages_1.BaseMessage)) {
|
|
195
|
+
finalInput = inputs['input'].map((m) => this.extractChatMessageContent(m));
|
|
196
|
+
}
|
|
197
|
+
else if (typeof inputs === 'object' && 'content' in inputs && typeof inputs['content'] === 'string') {
|
|
198
|
+
finalInput = inputs['content'];
|
|
199
|
+
}
|
|
200
|
+
const { step, endStep } = (0, tracer_1.addChainStepToTrace)({
|
|
201
|
+
name: runName,
|
|
202
|
+
inputs: finalInput,
|
|
203
|
+
metadata: this.joinTagsAndMetaData(tags, metadata) || {},
|
|
204
|
+
});
|
|
205
|
+
this.runMap.set(runId, { step, endStep });
|
|
206
|
+
}
|
|
207
|
+
catch (e) {
|
|
208
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async handleChainEnd(outputs, runId, parentRunId) {
|
|
212
|
+
try {
|
|
213
|
+
console.debug(`Chain end with ID: ${runId}`);
|
|
214
|
+
let finalOutput = outputs;
|
|
215
|
+
if (typeof outputs === 'object' && 'output' in outputs && typeof outputs['output'] === 'string') {
|
|
216
|
+
finalOutput = outputs['output'];
|
|
217
|
+
}
|
|
218
|
+
this.handleStepEnd({
|
|
219
|
+
runId,
|
|
220
|
+
output: finalOutput,
|
|
221
|
+
});
|
|
222
|
+
this.deregisterOpenlayerPrompt(runId);
|
|
223
|
+
}
|
|
224
|
+
catch (e) {
|
|
225
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
async handleChainError(err, runId, parentRunId) {
|
|
229
|
+
try {
|
|
230
|
+
console.debug(`Chain error: ${err} with ID: ${runId}`);
|
|
231
|
+
const azureRefusalError = this.parseAzureRefusalError(err);
|
|
232
|
+
this.handleStepEnd({
|
|
233
|
+
runId,
|
|
234
|
+
error: err.toString() + azureRefusalError,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// ============================================================================
|
|
242
|
+
// Agent Handlers
|
|
243
|
+
// ============================================================================
|
|
244
|
+
async handleAgentAction(action, runId, parentRunId) {
|
|
245
|
+
try {
|
|
246
|
+
console.debug(`Agent action ${action.tool} with ID: ${runId}`);
|
|
247
|
+
const { step, endStep } = (0, tracer_1.addAgentStepToTrace)({
|
|
248
|
+
name: action.tool,
|
|
249
|
+
inputs: action,
|
|
250
|
+
tool: action.tool,
|
|
251
|
+
action: action,
|
|
252
|
+
});
|
|
253
|
+
this.runMap.set(runId, { step, endStep });
|
|
254
|
+
}
|
|
255
|
+
catch (e) {
|
|
256
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async handleAgentEnd(action, runId, parentRunId) {
|
|
260
|
+
try {
|
|
261
|
+
console.debug(`Agent finish with ID: ${runId}`);
|
|
262
|
+
this.handleStepEnd({
|
|
263
|
+
runId,
|
|
264
|
+
output: action,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// ============================================================================
|
|
272
|
+
// Tool Handlers
|
|
273
|
+
// ============================================================================
|
|
274
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, name) {
|
|
275
|
+
try {
|
|
276
|
+
console.debug(`Tool start with ID: ${runId}`);
|
|
277
|
+
const { step, endStep } = (0, tracer_1.addToolStepToTrace)({
|
|
278
|
+
name: name ?? tool.id.at(-1)?.toString() ?? 'Tool execution',
|
|
279
|
+
inputs: input,
|
|
280
|
+
metadata: this.joinTagsAndMetaData(tags, metadata) || {},
|
|
281
|
+
});
|
|
282
|
+
this.runMap.set(runId, { step, endStep });
|
|
283
|
+
}
|
|
284
|
+
catch (e) {
|
|
285
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async handleToolEnd(output, runId, parentRunId) {
|
|
289
|
+
try {
|
|
290
|
+
console.debug(`Tool end with ID: ${runId}`);
|
|
291
|
+
this.handleStepEnd({
|
|
292
|
+
runId,
|
|
293
|
+
output: output,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async handleToolError(err, runId, parentRunId) {
|
|
301
|
+
try {
|
|
302
|
+
console.debug(`Tool error ${err} with ID: ${runId}`);
|
|
303
|
+
this.handleStepEnd({
|
|
304
|
+
runId,
|
|
305
|
+
error: err.toString(),
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// ============================================================================
|
|
313
|
+
// Retriever Handlers
|
|
314
|
+
// ============================================================================
|
|
315
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
316
|
+
try {
|
|
317
|
+
console.debug(`Retriever start with ID: ${runId}`);
|
|
318
|
+
const { step, endStep } = (0, tracer_1.addRetrieverStepToTrace)({
|
|
319
|
+
name: name ?? retriever.id.at(-1)?.toString() ?? 'Retriever',
|
|
320
|
+
inputs: query,
|
|
321
|
+
metadata: this.joinTagsAndMetaData(tags, metadata) || {},
|
|
322
|
+
});
|
|
323
|
+
this.runMap.set(runId, { step, endStep });
|
|
324
|
+
}
|
|
325
|
+
catch (e) {
|
|
326
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
async handleRetrieverEnd(documents, runId, parentRunId) {
|
|
330
|
+
try {
|
|
331
|
+
console.debug(`Retriever end with ID: ${runId}`);
|
|
332
|
+
this.handleStepEnd({
|
|
333
|
+
runId,
|
|
334
|
+
output: documents,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
catch (e) {
|
|
338
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
async handleRetrieverError(err, runId, parentRunId) {
|
|
342
|
+
try {
|
|
343
|
+
console.debug(`Retriever error: ${err} with ID: ${runId}`);
|
|
344
|
+
this.handleStepEnd({
|
|
345
|
+
runId,
|
|
346
|
+
error: err.toString(),
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
catch (e) {
|
|
350
|
+
console.debug(e instanceof Error ? e.message : String(e));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// ============================================================================
|
|
354
|
+
// Private Helper Methods
|
|
355
|
+
// ============================================================================
|
|
356
|
+
async handleGenerationStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name) {
|
|
357
|
+
console.debug(`Generation start with ID: ${runId} and parentRunId ${parentRunId}`);
|
|
358
|
+
const runName = name ?? llm.id?.at?.(-1)?.toString() ?? llm.id?.slice?.(-1)?.[0]?.toString() ?? 'Langchain Generation';
|
|
359
|
+
// Extract comprehensive model parameters
|
|
360
|
+
const modelParameters = {};
|
|
361
|
+
const invocationParams = extraParams?.['invocation_params'];
|
|
362
|
+
// Standard parameters
|
|
363
|
+
const standardParams = {
|
|
364
|
+
temperature: invocationParams?.['temperature'],
|
|
365
|
+
max_tokens: invocationParams?.['max_tokens'],
|
|
366
|
+
top_p: invocationParams?.['top_p'],
|
|
367
|
+
top_k: invocationParams?.['top_k'],
|
|
368
|
+
frequency_penalty: invocationParams?.['frequency_penalty'],
|
|
369
|
+
presence_penalty: invocationParams?.['presence_penalty'],
|
|
370
|
+
request_timeout: invocationParams?.['request_timeout'],
|
|
371
|
+
stop: invocationParams?.['stop'],
|
|
372
|
+
seed: invocationParams?.['seed'],
|
|
373
|
+
response_format: invocationParams?.['response_format'],
|
|
374
|
+
tools: invocationParams?.['tools'],
|
|
375
|
+
tool_choice: invocationParams?.['tool_choice'],
|
|
376
|
+
};
|
|
377
|
+
for (const [key, value] of Object.entries(standardParams)) {
|
|
378
|
+
if (value !== undefined && value !== null) {
|
|
379
|
+
modelParameters[key] = value;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
// Add any additional parameters that weren't in the standard list
|
|
383
|
+
if (invocationParams && typeof invocationParams === 'object') {
|
|
384
|
+
for (const [key, value] of Object.entries(invocationParams)) {
|
|
385
|
+
if (!(key in standardParams) && value !== undefined && value !== null) {
|
|
386
|
+
modelParameters[key] = value;
|
|
58
387
|
}
|
|
59
|
-
|
|
60
|
-
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
let extractedModelName;
|
|
391
|
+
if (extraParams) {
|
|
392
|
+
const invocationParamsModelName = extraParams['invocation_params']?.model;
|
|
393
|
+
const metadataModelName = metadata && 'ls_model_name' in metadata ? metadata['ls_model_name'] : undefined;
|
|
394
|
+
extractedModelName = invocationParamsModelName ?? metadataModelName;
|
|
395
|
+
}
|
|
396
|
+
// Extract provider with multiple fallbacks
|
|
397
|
+
let provider = metadata?.['ls_provider'];
|
|
398
|
+
// Fallback provider detection if not in metadata
|
|
399
|
+
if (!provider) {
|
|
400
|
+
// Try to detect from model name
|
|
401
|
+
if (extractedModelName) {
|
|
402
|
+
if (extractedModelName.includes('gpt') || extractedModelName.includes('openai')) {
|
|
403
|
+
provider = 'openai';
|
|
61
404
|
}
|
|
62
|
-
else {
|
|
63
|
-
|
|
405
|
+
else if (extractedModelName.includes('claude')) {
|
|
406
|
+
provider = 'anthropic';
|
|
407
|
+
}
|
|
408
|
+
else if (extractedModelName.includes('gemini') || extractedModelName.includes('google')) {
|
|
409
|
+
provider = 'google';
|
|
410
|
+
}
|
|
411
|
+
else if (extractedModelName.includes('llama') || extractedModelName.includes('meta')) {
|
|
412
|
+
provider = 'meta';
|
|
64
413
|
}
|
|
65
414
|
}
|
|
415
|
+
// Try to detect from LLM class name
|
|
416
|
+
if (!provider && llm.id && Array.isArray(llm.id)) {
|
|
417
|
+
const className = llm.id[0]?.toLowerCase() || '';
|
|
418
|
+
if (className.includes('openai') || className.includes('chatgpt')) {
|
|
419
|
+
provider = 'openai';
|
|
420
|
+
}
|
|
421
|
+
else if (className.includes('anthropic') || className.includes('claude')) {
|
|
422
|
+
provider = 'anthropic';
|
|
423
|
+
}
|
|
424
|
+
else if (className.includes('google') || className.includes('gemini')) {
|
|
425
|
+
provider = 'google';
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const mappedProvider = provider && LANGCHAIN_TO_OPENLAYER_PROVIDER_MAP[provider] ?
|
|
430
|
+
LANGCHAIN_TO_OPENLAYER_PROVIDER_MAP[provider]
|
|
431
|
+
: 'Unknown';
|
|
432
|
+
// Get registered prompt if available
|
|
433
|
+
const registeredPrompt = this.promptToParentRunMap.get(parentRunId ?? 'root');
|
|
434
|
+
if (registeredPrompt && parentRunId) {
|
|
435
|
+
this.deregisterOpenlayerPrompt(parentRunId);
|
|
66
436
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
extractOutput(output) {
|
|
94
|
-
const lastResponse = output?.generations?.at(-1)?.at(-1) ?? undefined;
|
|
95
|
-
this.output += lastResponse?.text ?? '';
|
|
96
|
-
}
|
|
97
|
-
addToTrace() {
|
|
98
|
-
let name = 'Chat Completion Model';
|
|
99
|
-
if (this.provider && this.provider in PROVIDER_TO_STEP_NAME) {
|
|
100
|
-
name = PROVIDER_TO_STEP_NAME[this.provider] ?? 'Chat Completion Model';
|
|
101
|
-
}
|
|
102
|
-
(0, tracer_1.addChatCompletionStepToTrace)({
|
|
103
|
-
name: name,
|
|
104
|
-
inputs: { prompt: this.prompt },
|
|
105
|
-
output: this.output,
|
|
106
|
-
latency: this.latency,
|
|
107
|
-
tokens: this.totalTokens,
|
|
108
|
-
promptTokens: this.promptTokens,
|
|
109
|
-
completionTokens: this.completionTokens,
|
|
110
|
-
model: this.model,
|
|
111
|
-
modelParameters: this.modelParameters,
|
|
112
|
-
metadata: this.metadata,
|
|
113
|
-
provider: this.provider ?? '',
|
|
114
|
-
startTime: this.startTime,
|
|
115
|
-
endTime: this.endTime,
|
|
437
|
+
// Create step but don't end it yet - we'll update it in handleLLMEnd
|
|
438
|
+
const stepName = mappedProvider && PROVIDER_TO_STEP_NAME[mappedProvider] ?
|
|
439
|
+
PROVIDER_TO_STEP_NAME[mappedProvider]
|
|
440
|
+
: runName;
|
|
441
|
+
// For generations, we need to track the start time and other data to use in handleLLMEnd
|
|
442
|
+
const startTime = performance.now();
|
|
443
|
+
// Enhanced metadata collection
|
|
444
|
+
const enhancedMetadata = this.joinTagsAndMetaData(tags, metadata, {
|
|
445
|
+
// LangChain specific metadata
|
|
446
|
+
langchain_provider: provider,
|
|
447
|
+
langchain_model: extractedModelName,
|
|
448
|
+
langchain_run_id: runId,
|
|
449
|
+
langchain_parent_run_id: parentRunId,
|
|
450
|
+
// Invocation details
|
|
451
|
+
invocation_params: invocationParams,
|
|
452
|
+
// Timing
|
|
453
|
+
start_time: new Date().toISOString(),
|
|
454
|
+
// LLM info
|
|
455
|
+
llm_class: llm.id ?
|
|
456
|
+
Array.isArray(llm.id) ?
|
|
457
|
+
llm.id.join('.')
|
|
458
|
+
: llm.id
|
|
459
|
+
: 'unknown',
|
|
460
|
+
// Additional context
|
|
461
|
+
...(Object.keys(modelParameters).length > 0 && { model_parameters: modelParameters }),
|
|
462
|
+
...(extraParams && { extra_params: extraParams }),
|
|
116
463
|
});
|
|
464
|
+
this.runMap.set(runId, {
|
|
465
|
+
step: {
|
|
466
|
+
name: stepName,
|
|
467
|
+
inputs: { prompt: messages },
|
|
468
|
+
startTime,
|
|
469
|
+
provider: mappedProvider,
|
|
470
|
+
model: extractedModelName,
|
|
471
|
+
modelParameters,
|
|
472
|
+
metadata: enhancedMetadata,
|
|
473
|
+
prompt: registeredPrompt,
|
|
474
|
+
},
|
|
475
|
+
endStep: () => { }, // Will be replaced in handleLLMEnd
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
handleStepEnd(params) {
|
|
479
|
+
const { runId, output, rawOutput, error, modelName, usageDetails, completionStartTime } = params;
|
|
480
|
+
const runData = this.runMap.get(runId);
|
|
481
|
+
if (!runData) {
|
|
482
|
+
console.warn('Step not found in runMap. Skipping operation');
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const { step } = runData;
|
|
486
|
+
// Handle LLM/Generation steps specially
|
|
487
|
+
if (step.provider) {
|
|
488
|
+
const endTime = performance.now();
|
|
489
|
+
const latency = endTime - step.startTime;
|
|
490
|
+
(0, tracer_1.addChatCompletionStepToTrace)({
|
|
491
|
+
name: step.name || 'Unknown Generation',
|
|
492
|
+
inputs: step.inputs || {},
|
|
493
|
+
output: output || '',
|
|
494
|
+
latency,
|
|
495
|
+
tokens: usageDetails?.['total'] || null,
|
|
496
|
+
promptTokens: usageDetails?.['input'] || null,
|
|
497
|
+
completionTokens: usageDetails?.['output'] || null,
|
|
498
|
+
model: modelName || step.model || null,
|
|
499
|
+
modelParameters: step.modelParameters || null,
|
|
500
|
+
metadata: error ?
|
|
501
|
+
{ ...step.metadata, error, rawOutput: rawOutput || null }
|
|
502
|
+
: { rawOutput: rawOutput || null, ...step.metadata },
|
|
503
|
+
provider: step.provider || 'Unknown',
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
// For other step types, update and end the existing step
|
|
508
|
+
if (step.log) {
|
|
509
|
+
step.log({
|
|
510
|
+
output: output,
|
|
511
|
+
metadata: error ? { ...step.metadata, error } : step.metadata,
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
if (runData.endStep) {
|
|
515
|
+
runData.endStep();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
this.runMap.delete(runId);
|
|
519
|
+
}
|
|
520
|
+
registerOpenlayerPrompt(parentRunId, metadata) {
|
|
521
|
+
if (metadata && 'openlayerPrompt' in metadata && parentRunId) {
|
|
522
|
+
this.promptToParentRunMap.set(parentRunId, metadata['openlayerPrompt']);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
deregisterOpenlayerPrompt(runId) {
|
|
526
|
+
this.promptToParentRunMap.delete(runId);
|
|
527
|
+
}
|
|
528
|
+
parseAzureRefusalError(err) {
|
|
529
|
+
let azureRefusalError = '';
|
|
530
|
+
if (typeof err == 'object' && 'error' in err) {
|
|
531
|
+
try {
|
|
532
|
+
azureRefusalError = '\n\nError details:\n' + JSON.stringify(err['error'], null, 2);
|
|
533
|
+
}
|
|
534
|
+
catch { }
|
|
535
|
+
}
|
|
536
|
+
return azureRefusalError;
|
|
537
|
+
}
|
|
538
|
+
joinTagsAndMetaData(tags, metadata1, metadata2) {
|
|
539
|
+
const finalDict = {};
|
|
540
|
+
if (tags && tags.length > 0) {
|
|
541
|
+
finalDict['tags'] = tags;
|
|
542
|
+
}
|
|
543
|
+
if (metadata1) {
|
|
544
|
+
Object.assign(finalDict, metadata1);
|
|
545
|
+
}
|
|
546
|
+
if (metadata2) {
|
|
547
|
+
Object.assign(finalDict, metadata2);
|
|
548
|
+
}
|
|
549
|
+
return this.stripOpenlayerKeysFromMetadata(finalDict);
|
|
550
|
+
}
|
|
551
|
+
stripOpenlayerKeysFromMetadata(metadata) {
|
|
552
|
+
if (!metadata) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const openlayerKeys = ['openlayerPrompt', 'openlayerUserId', 'openlayerSessionId'];
|
|
556
|
+
return Object.fromEntries(Object.entries(metadata).filter(([key, _]) => !openlayerKeys.includes(key)));
|
|
557
|
+
}
|
|
558
|
+
extractUsageMetadata(generation) {
|
|
559
|
+
try {
|
|
560
|
+
const usageMetadata = ('message' in generation &&
|
|
561
|
+
(generation['message'] instanceof messages_1.AIMessage || generation['message'] instanceof messages_1.AIMessageChunk)) ?
|
|
562
|
+
generation['message'].usage_metadata
|
|
563
|
+
: undefined;
|
|
564
|
+
return usageMetadata;
|
|
565
|
+
}
|
|
566
|
+
catch (err) {
|
|
567
|
+
console.debug(`Error extracting usage metadata: ${err}`);
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
extractModelNameFromMetadata(generation) {
|
|
572
|
+
try {
|
|
573
|
+
return ('message' in generation &&
|
|
574
|
+
(generation['message'] instanceof messages_1.AIMessage || generation['message'] instanceof messages_1.AIMessageChunk)) ?
|
|
575
|
+
generation['message'].response_metadata?.['model_name']
|
|
576
|
+
: undefined;
|
|
577
|
+
}
|
|
578
|
+
catch {
|
|
579
|
+
return undefined;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
extractChatMessageContent(message) {
|
|
583
|
+
let response = undefined;
|
|
584
|
+
if (message instanceof messages_1.HumanMessage) {
|
|
585
|
+
response = { content: message.content, role: 'user' };
|
|
586
|
+
}
|
|
587
|
+
else if (message instanceof messages_1.ChatMessage) {
|
|
588
|
+
response = { content: message.content, role: message.role };
|
|
589
|
+
}
|
|
590
|
+
else if (message instanceof messages_1.AIMessage) {
|
|
591
|
+
response = { content: message.content, role: 'assistant' };
|
|
592
|
+
if ('tool_calls' in message && (message.tool_calls?.length ?? 0) > 0) {
|
|
593
|
+
response['tool_calls'] = message['tool_calls'];
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
else if (message instanceof messages_1.SystemMessage) {
|
|
597
|
+
response = { content: message.content, role: 'system' };
|
|
598
|
+
}
|
|
599
|
+
else if (message instanceof messages_1.FunctionMessage) {
|
|
600
|
+
response = {
|
|
601
|
+
content: message.content,
|
|
602
|
+
additional_kwargs: message.additional_kwargs,
|
|
603
|
+
role: message.name,
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
else if (message instanceof messages_1.ToolMessage) {
|
|
607
|
+
response = {
|
|
608
|
+
content: message.content,
|
|
609
|
+
additional_kwargs: message.additional_kwargs,
|
|
610
|
+
role: message.name,
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
else if (!message.name) {
|
|
614
|
+
response = { content: message.content };
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
response = {
|
|
618
|
+
role: message.name,
|
|
619
|
+
content: message.content,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
if (message.additional_kwargs?.function_call || message.additional_kwargs?.tool_calls) {
|
|
623
|
+
return { ...response, additional_kwargs: message.additional_kwargs };
|
|
624
|
+
}
|
|
625
|
+
return response;
|
|
117
626
|
}
|
|
118
627
|
}
|
|
119
628
|
exports.OpenlayerHandler = OpenlayerHandler;
|