@langchain/core 0.2.0 → 0.2.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/dist/callbacks/tests/callbacks.test.d.ts +1 -0
- package/dist/callbacks/tests/callbacks.test.js +492 -0
- package/dist/callbacks/tests/manager.int.test.d.ts +1 -0
- package/dist/callbacks/tests/manager.int.test.js +29 -0
- package/dist/callbacks/tests/run_collector.test.d.ts +1 -0
- package/dist/callbacks/tests/run_collector.test.js +58 -0
- package/dist/chat_history.cjs +13 -0
- package/dist/chat_history.d.ts +9 -0
- package/dist/chat_history.js +13 -0
- package/dist/language_models/chat_models.d.ts +2 -2
- package/dist/language_models/tests/chat_models.test.d.ts +1 -0
- package/dist/language_models/tests/chat_models.test.js +154 -0
- package/dist/language_models/tests/count_tokens.test.d.ts +1 -0
- package/dist/language_models/tests/count_tokens.test.js +19 -0
- package/dist/language_models/tests/llms.test.d.ts +1 -0
- package/dist/language_models/tests/llms.test.js +39 -0
- package/dist/messages/tests/base_message.test.d.ts +1 -0
- package/dist/messages/tests/base_message.test.js +97 -0
- package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.d.ts +1 -0
- package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.js +81 -0
- package/dist/output_parsers/tests/json.test.d.ts +1 -0
- package/dist/output_parsers/tests/json.test.js +427 -0
- package/dist/output_parsers/tests/output_parser.test.d.ts +1 -0
- package/dist/output_parsers/tests/output_parser.test.js +78 -0
- package/dist/output_parsers/tests/string.test.d.ts +1 -0
- package/dist/output_parsers/tests/string.test.js +68 -0
- package/dist/output_parsers/tests/structured.test.d.ts +1 -0
- package/dist/output_parsers/tests/structured.test.js +166 -0
- package/dist/output_parsers/tests/xml.test.d.ts +1 -0
- package/dist/output_parsers/tests/xml.test.js +81 -0
- package/dist/prompts/tests/chat.mustache.test.d.ts +1 -0
- package/dist/prompts/tests/chat.mustache.test.js +61 -0
- package/dist/prompts/tests/chat.test.d.ts +1 -0
- package/dist/prompts/tests/chat.test.js +507 -0
- package/dist/prompts/tests/few_shot.test.d.ts +1 -0
- package/dist/prompts/tests/few_shot.test.js +224 -0
- package/dist/prompts/tests/pipeline.test.d.ts +1 -0
- package/dist/prompts/tests/pipeline.test.js +101 -0
- package/dist/prompts/tests/prompt.mustache.test.d.ts +1 -0
- package/dist/prompts/tests/prompt.mustache.test.js +85 -0
- package/dist/prompts/tests/prompt.test.d.ts +1 -0
- package/dist/prompts/tests/prompt.test.js +78 -0
- package/dist/prompts/tests/structured.test.d.ts +1 -0
- package/dist/prompts/tests/structured.test.js +37 -0
- package/dist/prompts/tests/template.test.d.ts +1 -0
- package/dist/prompts/tests/template.test.js +24 -0
- package/dist/runnables/base.cjs +87 -6
- package/dist/runnables/base.d.ts +45 -26
- package/dist/runnables/base.js +87 -6
- package/dist/runnables/history.cjs +87 -32
- package/dist/runnables/history.d.ts +1 -1
- package/dist/runnables/history.js +87 -32
- package/dist/runnables/remote.cjs +2 -2
- package/dist/runnables/remote.d.ts +3 -3
- package/dist/runnables/remote.js +2 -2
- package/dist/runnables/tests/runnable.test.d.ts +1 -0
- package/dist/runnables/tests/runnable.test.js +491 -0
- package/dist/runnables/tests/runnable_binding.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_binding.test.js +46 -0
- package/dist/runnables/tests/runnable_branch.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_branch.test.js +116 -0
- package/dist/runnables/tests/runnable_graph.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_graph.test.js +84 -0
- package/dist/runnables/tests/runnable_history.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_history.test.js +177 -0
- package/dist/runnables/tests/runnable_interface.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_interface.test.js +209 -0
- package/dist/runnables/tests/runnable_map.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_map.test.js +238 -0
- package/dist/runnables/tests/runnable_passthrough.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_passthrough.test.js +96 -0
- package/dist/runnables/tests/runnable_remote.int.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_remote.int.test.js +138 -0
- package/dist/runnables/tests/runnable_remote.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_remote.test.js +200 -0
- package/dist/runnables/tests/runnable_retry.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_retry.test.js +125 -0
- package/dist/runnables/tests/runnable_stream_events.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_stream_events.test.js +1013 -0
- package/dist/runnables/tests/runnable_stream_events_v2.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_stream_events_v2.test.js +973 -0
- package/dist/runnables/tests/runnable_stream_log.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_stream_log.test.js +282 -0
- package/dist/runnables/tests/runnable_tracing.int.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_tracing.int.test.js +37 -0
- package/dist/runnables/tests/runnable_with_fallbacks.test.d.ts +1 -0
- package/dist/runnables/tests/runnable_with_fallbacks.test.js +36 -0
- package/dist/runnables/utils.d.ts +1 -1
- package/dist/singletons/tests/async_local_storage.test.d.ts +1 -0
- package/dist/singletons/tests/async_local_storage.test.js +120 -0
- package/dist/structured_query/tests/utils.test.d.ts +1 -0
- package/dist/structured_query/tests/utils.test.js +47 -0
- package/dist/tracers/event_stream.cjs +493 -0
- package/dist/tracers/event_stream.d.ts +137 -0
- package/dist/tracers/event_stream.js +489 -0
- package/dist/tracers/log_stream.d.ts +2 -77
- package/dist/tracers/tests/langchain_tracer.int.test.d.ts +1 -0
- package/dist/tracers/tests/langchain_tracer.int.test.js +74 -0
- package/dist/tracers/tests/tracer.test.d.ts +1 -0
- package/dist/tracers/tests/tracer.test.js +378 -0
- package/dist/utils/testing/tests/chatfake.test.d.ts +1 -0
- package/dist/utils/testing/tests/chatfake.test.js +112 -0
- package/dist/utils/tests/async_caller.test.d.ts +1 -0
- package/dist/utils/tests/async_caller.test.js +27 -0
- package/dist/utils/tests/enviroment.test.d.ts +1 -0
- package/dist/utils/tests/enviroment.test.js +6 -0
- package/dist/utils/tests/function_calling.test.d.ts +1 -0
- package/dist/utils/tests/function_calling.test.js +107 -0
- package/dist/utils/tests/math_utils.test.d.ts +1 -0
- package/dist/utils/tests/math_utils.test.js +139 -0
- package/dist/utils/tests/polyfill_stream.test.d.ts +1 -0
- package/dist/utils/tests/polyfill_stream.test.js +15 -0
- package/package.json +6 -6
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { BaseTracer } from "./base.js";
|
|
2
|
+
import { IterableReadableStream } from "../utils/stream.js";
|
|
3
|
+
import { AIMessageChunk } from "../messages/ai.js";
|
|
4
|
+
import { GenerationChunk } from "../outputs.js";
|
|
5
|
+
function assignName({ name, serialized, }) {
|
|
6
|
+
if (name !== undefined) {
|
|
7
|
+
return name;
|
|
8
|
+
}
|
|
9
|
+
if (serialized?.name !== undefined) {
|
|
10
|
+
return serialized.name;
|
|
11
|
+
}
|
|
12
|
+
else if (serialized?.id !== undefined && Array.isArray(serialized?.id)) {
|
|
13
|
+
return serialized.id[serialized.id.length - 1];
|
|
14
|
+
}
|
|
15
|
+
return "Unnamed";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Class that extends the `BaseTracer` class from the
|
|
19
|
+
* `langchain.callbacks.tracers.base` module. It represents a callback
|
|
20
|
+
* handler that logs the execution of runs and emits `RunLog` instances to a
|
|
21
|
+
* `RunLogStream`.
|
|
22
|
+
*/
|
|
23
|
+
export class EventStreamCallbackHandler extends BaseTracer {
|
|
24
|
+
constructor(fields) {
|
|
25
|
+
super({ _awaitHandler: true, ...fields });
|
|
26
|
+
Object.defineProperty(this, "autoClose", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: true
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(this, "includeNames", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
value: void 0
|
|
37
|
+
});
|
|
38
|
+
Object.defineProperty(this, "includeTypes", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: void 0
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(this, "includeTags", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
47
|
+
writable: true,
|
|
48
|
+
value: void 0
|
|
49
|
+
});
|
|
50
|
+
Object.defineProperty(this, "excludeNames", {
|
|
51
|
+
enumerable: true,
|
|
52
|
+
configurable: true,
|
|
53
|
+
writable: true,
|
|
54
|
+
value: void 0
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(this, "excludeTypes", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
configurable: true,
|
|
59
|
+
writable: true,
|
|
60
|
+
value: void 0
|
|
61
|
+
});
|
|
62
|
+
Object.defineProperty(this, "excludeTags", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
configurable: true,
|
|
65
|
+
writable: true,
|
|
66
|
+
value: void 0
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(this, "rootId", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
configurable: true,
|
|
71
|
+
writable: true,
|
|
72
|
+
value: void 0
|
|
73
|
+
});
|
|
74
|
+
Object.defineProperty(this, "runInfoMap", {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
configurable: true,
|
|
77
|
+
writable: true,
|
|
78
|
+
value: new Map()
|
|
79
|
+
});
|
|
80
|
+
Object.defineProperty(this, "tappedPromises", {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
configurable: true,
|
|
83
|
+
writable: true,
|
|
84
|
+
value: new Map()
|
|
85
|
+
});
|
|
86
|
+
Object.defineProperty(this, "transformStream", {
|
|
87
|
+
enumerable: true,
|
|
88
|
+
configurable: true,
|
|
89
|
+
writable: true,
|
|
90
|
+
value: void 0
|
|
91
|
+
});
|
|
92
|
+
Object.defineProperty(this, "writer", {
|
|
93
|
+
enumerable: true,
|
|
94
|
+
configurable: true,
|
|
95
|
+
writable: true,
|
|
96
|
+
value: void 0
|
|
97
|
+
});
|
|
98
|
+
Object.defineProperty(this, "receiveStream", {
|
|
99
|
+
enumerable: true,
|
|
100
|
+
configurable: true,
|
|
101
|
+
writable: true,
|
|
102
|
+
value: void 0
|
|
103
|
+
});
|
|
104
|
+
Object.defineProperty(this, "name", {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
configurable: true,
|
|
107
|
+
writable: true,
|
|
108
|
+
value: "event_stream_tracer"
|
|
109
|
+
});
|
|
110
|
+
this.autoClose = fields?.autoClose ?? true;
|
|
111
|
+
this.includeNames = fields?.includeNames;
|
|
112
|
+
this.includeTypes = fields?.includeTypes;
|
|
113
|
+
this.includeTags = fields?.includeTags;
|
|
114
|
+
this.excludeNames = fields?.excludeNames;
|
|
115
|
+
this.excludeTypes = fields?.excludeTypes;
|
|
116
|
+
this.excludeTags = fields?.excludeTags;
|
|
117
|
+
this.transformStream = new TransformStream();
|
|
118
|
+
this.writer = this.transformStream.writable.getWriter();
|
|
119
|
+
this.receiveStream = IterableReadableStream.fromReadableStream(this.transformStream.readable);
|
|
120
|
+
}
|
|
121
|
+
[Symbol.asyncIterator]() {
|
|
122
|
+
return this.receiveStream;
|
|
123
|
+
}
|
|
124
|
+
async persistRun(_run) {
|
|
125
|
+
// This is a legacy method only called once for an entire run tree
|
|
126
|
+
// and is therefore not useful here
|
|
127
|
+
}
|
|
128
|
+
_includeRun(run) {
|
|
129
|
+
const runTags = run.tags ?? [];
|
|
130
|
+
let include = this.includeNames === undefined &&
|
|
131
|
+
this.includeTags === undefined &&
|
|
132
|
+
this.includeTypes === undefined;
|
|
133
|
+
if (this.includeNames !== undefined) {
|
|
134
|
+
include = include || this.includeNames.includes(run.name);
|
|
135
|
+
}
|
|
136
|
+
if (this.includeTypes !== undefined) {
|
|
137
|
+
include = include || this.includeTypes.includes(run.runType);
|
|
138
|
+
}
|
|
139
|
+
if (this.includeTags !== undefined) {
|
|
140
|
+
include =
|
|
141
|
+
include ||
|
|
142
|
+
runTags.find((tag) => this.includeTags?.includes(tag)) !== undefined;
|
|
143
|
+
}
|
|
144
|
+
if (this.excludeNames !== undefined) {
|
|
145
|
+
include = include && !this.excludeNames.includes(run.name);
|
|
146
|
+
}
|
|
147
|
+
if (this.excludeTypes !== undefined) {
|
|
148
|
+
include = include && !this.excludeTypes.includes(run.runType);
|
|
149
|
+
}
|
|
150
|
+
if (this.excludeTags !== undefined) {
|
|
151
|
+
include =
|
|
152
|
+
include && runTags.every((tag) => !this.excludeTags?.includes(tag));
|
|
153
|
+
}
|
|
154
|
+
return include;
|
|
155
|
+
}
|
|
156
|
+
async *tapOutputIterable(runId, outputStream) {
|
|
157
|
+
const firstChunk = await outputStream.next();
|
|
158
|
+
if (firstChunk.done) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const runInfo = this.runInfoMap.get(runId);
|
|
162
|
+
// run has finished, don't issue any stream events
|
|
163
|
+
if (runInfo === undefined) {
|
|
164
|
+
yield firstChunk.value;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let tappedPromise = this.tappedPromises.get(runId);
|
|
168
|
+
// if we are the first to tap, issue stream events
|
|
169
|
+
if (tappedPromise === undefined) {
|
|
170
|
+
let tappedPromiseResolver;
|
|
171
|
+
tappedPromise = new Promise((resolve) => {
|
|
172
|
+
tappedPromiseResolver = resolve;
|
|
173
|
+
});
|
|
174
|
+
this.tappedPromises.set(runId, tappedPromise);
|
|
175
|
+
try {
|
|
176
|
+
const event = {
|
|
177
|
+
event: `on_${runInfo.runType}_stream`,
|
|
178
|
+
run_id: runId,
|
|
179
|
+
name: runInfo.name,
|
|
180
|
+
tags: runInfo.tags,
|
|
181
|
+
metadata: runInfo.metadata,
|
|
182
|
+
data: {},
|
|
183
|
+
};
|
|
184
|
+
await this.send({
|
|
185
|
+
...event,
|
|
186
|
+
data: { chunk: firstChunk.value },
|
|
187
|
+
}, runInfo);
|
|
188
|
+
yield firstChunk.value;
|
|
189
|
+
for await (const chunk of outputStream) {
|
|
190
|
+
// Don't yield tool and retriever stream events
|
|
191
|
+
if (runInfo.runType !== "tool" && runInfo.runType !== "retriever") {
|
|
192
|
+
await this.send({
|
|
193
|
+
...event,
|
|
194
|
+
data: {
|
|
195
|
+
chunk,
|
|
196
|
+
},
|
|
197
|
+
}, runInfo);
|
|
198
|
+
}
|
|
199
|
+
yield chunk;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
204
|
+
tappedPromiseResolver();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// otherwise just pass through
|
|
209
|
+
yield firstChunk.value;
|
|
210
|
+
for await (const chunk of outputStream) {
|
|
211
|
+
yield chunk;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async send(payload, run) {
|
|
216
|
+
if (this._includeRun(run)) {
|
|
217
|
+
await this.writer.write(payload);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async sendEndEvent(payload, run) {
|
|
221
|
+
const tappedPromise = this.tappedPromises.get(payload.run_id);
|
|
222
|
+
if (tappedPromise !== undefined) {
|
|
223
|
+
void tappedPromise.then(() => {
|
|
224
|
+
void this.send(payload, run);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
await this.send(payload, run);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async onLLMStart(run) {
|
|
232
|
+
const runName = assignName(run);
|
|
233
|
+
const runType = run.inputs.messages !== undefined ? "chat_model" : "llm";
|
|
234
|
+
const runInfo = {
|
|
235
|
+
tags: run.tags ?? [],
|
|
236
|
+
metadata: run.extra?.metadata ?? {},
|
|
237
|
+
name: runName,
|
|
238
|
+
runType,
|
|
239
|
+
inputs: run.inputs,
|
|
240
|
+
};
|
|
241
|
+
this.runInfoMap.set(run.id, runInfo);
|
|
242
|
+
const eventName = `on_${runType}_start`;
|
|
243
|
+
await this.send({
|
|
244
|
+
event: eventName,
|
|
245
|
+
data: {
|
|
246
|
+
input: run.inputs,
|
|
247
|
+
},
|
|
248
|
+
name: runName,
|
|
249
|
+
tags: run.tags ?? [],
|
|
250
|
+
run_id: run.id,
|
|
251
|
+
metadata: run.extra?.metadata ?? {},
|
|
252
|
+
}, runInfo);
|
|
253
|
+
}
|
|
254
|
+
async onLLMNewToken(run, token,
|
|
255
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
256
|
+
kwargs) {
|
|
257
|
+
const runInfo = this.runInfoMap.get(run.id);
|
|
258
|
+
let chunk;
|
|
259
|
+
let eventName;
|
|
260
|
+
if (runInfo === undefined) {
|
|
261
|
+
throw new Error(`onLLMNewToken: Run ID ${run.id} not found in run map.`);
|
|
262
|
+
}
|
|
263
|
+
if (runInfo.runType === "chat_model") {
|
|
264
|
+
eventName = "on_chat_model_stream";
|
|
265
|
+
if (kwargs?.chunk === undefined) {
|
|
266
|
+
chunk = new AIMessageChunk({ content: token });
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
chunk = kwargs.chunk.message;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else if (runInfo.runType === "llm") {
|
|
273
|
+
eventName = "on_llm_stream";
|
|
274
|
+
if (kwargs?.chunk === undefined) {
|
|
275
|
+
chunk = new GenerationChunk({ text: token });
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
chunk = kwargs.chunk;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
throw new Error(`Unexpected run type ${runInfo.runType}`);
|
|
283
|
+
}
|
|
284
|
+
await this.send({
|
|
285
|
+
event: eventName,
|
|
286
|
+
data: {
|
|
287
|
+
chunk,
|
|
288
|
+
},
|
|
289
|
+
run_id: run.id,
|
|
290
|
+
name: runInfo.name,
|
|
291
|
+
tags: runInfo.tags,
|
|
292
|
+
metadata: runInfo.metadata,
|
|
293
|
+
}, runInfo);
|
|
294
|
+
}
|
|
295
|
+
async onLLMEnd(run) {
|
|
296
|
+
const runInfo = this.runInfoMap.get(run.id);
|
|
297
|
+
this.runInfoMap.delete(run.id);
|
|
298
|
+
let eventName;
|
|
299
|
+
if (runInfo === undefined) {
|
|
300
|
+
throw new Error(`onLLMEnd: Run ID ${run.id} not found in run map.`);
|
|
301
|
+
}
|
|
302
|
+
const generations = run.outputs?.generations;
|
|
303
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
304
|
+
let output;
|
|
305
|
+
if (runInfo.runType === "chat_model") {
|
|
306
|
+
for (const generation of generations ?? []) {
|
|
307
|
+
if (output !== undefined) {
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
output = generation[0]?.message;
|
|
311
|
+
}
|
|
312
|
+
eventName = "on_chat_model_end";
|
|
313
|
+
}
|
|
314
|
+
else if (runInfo.runType === "llm") {
|
|
315
|
+
output = {
|
|
316
|
+
generations: generations?.map((generation) => {
|
|
317
|
+
return generation.map((chunk) => {
|
|
318
|
+
return {
|
|
319
|
+
text: chunk.text,
|
|
320
|
+
generationInfo: chunk.generationInfo,
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
}),
|
|
324
|
+
llmOutput: run.outputs?.llmOutput ?? {},
|
|
325
|
+
};
|
|
326
|
+
eventName = "on_llm_end";
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
throw new Error(`onLLMEnd: Unexpected run type: ${runInfo.runType}`);
|
|
330
|
+
}
|
|
331
|
+
await this.sendEndEvent({
|
|
332
|
+
event: eventName,
|
|
333
|
+
data: {
|
|
334
|
+
output,
|
|
335
|
+
input: runInfo.inputs,
|
|
336
|
+
},
|
|
337
|
+
run_id: run.id,
|
|
338
|
+
name: runInfo.name,
|
|
339
|
+
tags: runInfo.tags,
|
|
340
|
+
metadata: runInfo.metadata,
|
|
341
|
+
}, runInfo);
|
|
342
|
+
}
|
|
343
|
+
async onChainStart(run) {
|
|
344
|
+
const runName = assignName(run);
|
|
345
|
+
const runType = run.run_type ?? "chain";
|
|
346
|
+
const runInfo = {
|
|
347
|
+
tags: run.tags ?? [],
|
|
348
|
+
metadata: run.extra?.metadata ?? {},
|
|
349
|
+
name: runName,
|
|
350
|
+
runType: run.run_type,
|
|
351
|
+
};
|
|
352
|
+
let eventData = {};
|
|
353
|
+
// Workaround Runnable core code not sending input when transform streaming.
|
|
354
|
+
if (run.inputs.input === "" && Object.keys(run.inputs).length === 1) {
|
|
355
|
+
eventData = {};
|
|
356
|
+
runInfo.inputs = {};
|
|
357
|
+
}
|
|
358
|
+
else if (run.inputs.input !== undefined) {
|
|
359
|
+
eventData.input = run.inputs.input;
|
|
360
|
+
runInfo.inputs = run.inputs.input;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
eventData.input = run.inputs;
|
|
364
|
+
runInfo.inputs = run.inputs;
|
|
365
|
+
}
|
|
366
|
+
this.runInfoMap.set(run.id, runInfo);
|
|
367
|
+
await this.send({
|
|
368
|
+
event: `on_${runType}_start`,
|
|
369
|
+
data: eventData,
|
|
370
|
+
name: runName,
|
|
371
|
+
tags: run.tags ?? [],
|
|
372
|
+
run_id: run.id,
|
|
373
|
+
metadata: run.extra?.metadata ?? {},
|
|
374
|
+
}, runInfo);
|
|
375
|
+
}
|
|
376
|
+
async onChainEnd(run) {
|
|
377
|
+
const runInfo = this.runInfoMap.get(run.id);
|
|
378
|
+
this.runInfoMap.delete(run.id);
|
|
379
|
+
if (runInfo === undefined) {
|
|
380
|
+
throw new Error(`onChainEnd: Run ID ${run.id} not found in run map.`);
|
|
381
|
+
}
|
|
382
|
+
const eventName = `on_${run.run_type}_end`;
|
|
383
|
+
const inputs = run.inputs ?? runInfo.inputs ?? {};
|
|
384
|
+
const outputs = run.outputs?.output ?? run.outputs;
|
|
385
|
+
const data = {
|
|
386
|
+
output: outputs,
|
|
387
|
+
input: inputs,
|
|
388
|
+
};
|
|
389
|
+
if (inputs.input && Object.keys(inputs).length === 1) {
|
|
390
|
+
data.input = inputs.input;
|
|
391
|
+
runInfo.inputs = inputs.input;
|
|
392
|
+
}
|
|
393
|
+
await this.sendEndEvent({
|
|
394
|
+
event: eventName,
|
|
395
|
+
data,
|
|
396
|
+
run_id: run.id,
|
|
397
|
+
name: runInfo.name,
|
|
398
|
+
tags: runInfo.tags,
|
|
399
|
+
metadata: runInfo.metadata ?? {},
|
|
400
|
+
}, runInfo);
|
|
401
|
+
}
|
|
402
|
+
async onToolStart(run) {
|
|
403
|
+
const runName = assignName(run);
|
|
404
|
+
const runInfo = {
|
|
405
|
+
tags: run.tags ?? [],
|
|
406
|
+
metadata: run.extra?.metadata ?? {},
|
|
407
|
+
name: runName,
|
|
408
|
+
runType: "tool",
|
|
409
|
+
inputs: run.inputs ?? {},
|
|
410
|
+
};
|
|
411
|
+
this.runInfoMap.set(run.id, runInfo);
|
|
412
|
+
await this.send({
|
|
413
|
+
event: "on_tool_start",
|
|
414
|
+
data: {
|
|
415
|
+
input: run.inputs ?? {},
|
|
416
|
+
},
|
|
417
|
+
name: runName,
|
|
418
|
+
run_id: run.id,
|
|
419
|
+
tags: run.tags ?? [],
|
|
420
|
+
metadata: run.extra?.metadata ?? {},
|
|
421
|
+
}, runInfo);
|
|
422
|
+
}
|
|
423
|
+
async onToolEnd(run) {
|
|
424
|
+
const runInfo = this.runInfoMap.get(run.id);
|
|
425
|
+
this.runInfoMap.delete(run.id);
|
|
426
|
+
if (runInfo === undefined) {
|
|
427
|
+
throw new Error(`onToolEnd: Run ID ${run.id} not found in run map.`);
|
|
428
|
+
}
|
|
429
|
+
if (runInfo.inputs === undefined) {
|
|
430
|
+
throw new Error(`onToolEnd: Run ID ${run.id} is a tool call, and is expected to have traced inputs.`);
|
|
431
|
+
}
|
|
432
|
+
const output = run.outputs?.output === undefined ? run.outputs : run.outputs.output;
|
|
433
|
+
await this.sendEndEvent({
|
|
434
|
+
event: "on_tool_end",
|
|
435
|
+
data: {
|
|
436
|
+
output,
|
|
437
|
+
input: runInfo.inputs,
|
|
438
|
+
},
|
|
439
|
+
run_id: run.id,
|
|
440
|
+
name: runInfo.name,
|
|
441
|
+
tags: runInfo.tags,
|
|
442
|
+
metadata: runInfo.metadata,
|
|
443
|
+
}, runInfo);
|
|
444
|
+
}
|
|
445
|
+
async onRetrieverStart(run) {
|
|
446
|
+
const runName = assignName(run);
|
|
447
|
+
const runType = "retriever";
|
|
448
|
+
const runInfo = {
|
|
449
|
+
tags: run.tags ?? [],
|
|
450
|
+
metadata: run.extra?.metadata ?? {},
|
|
451
|
+
name: runName,
|
|
452
|
+
runType,
|
|
453
|
+
inputs: {
|
|
454
|
+
query: run.inputs.query,
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
this.runInfoMap.set(run.id, runInfo);
|
|
458
|
+
await this.send({
|
|
459
|
+
event: "on_retriever_start",
|
|
460
|
+
data: {
|
|
461
|
+
input: {
|
|
462
|
+
query: run.inputs.query,
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
name: runName,
|
|
466
|
+
tags: run.tags ?? [],
|
|
467
|
+
run_id: run.id,
|
|
468
|
+
metadata: run.extra?.metadata ?? {},
|
|
469
|
+
}, runInfo);
|
|
470
|
+
}
|
|
471
|
+
async onRetrieverEnd(run) {
|
|
472
|
+
const runInfo = this.runInfoMap.get(run.id);
|
|
473
|
+
this.runInfoMap.delete(run.id);
|
|
474
|
+
if (runInfo === undefined) {
|
|
475
|
+
throw new Error(`onRetrieverEnd: Run ID ${run.id} not found in run map.`);
|
|
476
|
+
}
|
|
477
|
+
await this.sendEndEvent({
|
|
478
|
+
event: "on_retriever_end",
|
|
479
|
+
data: {
|
|
480
|
+
output: run.outputs?.documents ?? run.outputs,
|
|
481
|
+
input: runInfo.inputs,
|
|
482
|
+
},
|
|
483
|
+
run_id: run.id,
|
|
484
|
+
name: runInfo.name,
|
|
485
|
+
tags: runInfo.tags,
|
|
486
|
+
metadata: runInfo.metadata,
|
|
487
|
+
}, runInfo);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
@@ -2,6 +2,8 @@ import { type Operation as JSONPatchOperation } from "../utils/fast-json-patch/i
|
|
|
2
2
|
import { BaseTracer, type Run } from "./base.js";
|
|
3
3
|
import { BaseCallbackHandlerInput, HandleLLMNewTokenCallbackFields } from "../callbacks/base.js";
|
|
4
4
|
import { IterableReadableStream } from "../utils/stream.js";
|
|
5
|
+
import type { StreamEvent, StreamEventData } from "./event_stream.js";
|
|
6
|
+
export type { StreamEvent, StreamEventData };
|
|
5
7
|
/**
|
|
6
8
|
* Interface that represents the structure of a log entry in the
|
|
7
9
|
* `LogStreamCallbackHandler`.
|
|
@@ -70,83 +72,6 @@ export declare class RunLog extends RunLogPatch {
|
|
|
70
72
|
concat(other: RunLogPatch): RunLog;
|
|
71
73
|
static fromRunLogPatch(patch: RunLogPatch): RunLog;
|
|
72
74
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Data associated with a StreamEvent.
|
|
75
|
-
*/
|
|
76
|
-
export type StreamEventData = {
|
|
77
|
-
/**
|
|
78
|
-
* The input passed to the runnable that generated the event.
|
|
79
|
-
* Inputs will sometimes be available at the *START* of the runnable, and
|
|
80
|
-
* sometimes at the *END* of the runnable.
|
|
81
|
-
* If a runnable is able to stream its inputs, then its input by definition
|
|
82
|
-
* won't be known until the *END* of the runnable when it has finished streaming
|
|
83
|
-
* its inputs.
|
|
84
|
-
*/
|
|
85
|
-
input?: any;
|
|
86
|
-
/**
|
|
87
|
-
* The output of the runnable that generated the event.
|
|
88
|
-
* Outputs will only be available at the *END* of the runnable.
|
|
89
|
-
* For most runnables, this field can be inferred from the `chunk` field,
|
|
90
|
-
* though there might be some exceptions for special cased runnables (e.g., like
|
|
91
|
-
* chat models), which may return more information.
|
|
92
|
-
*/
|
|
93
|
-
output?: any;
|
|
94
|
-
/**
|
|
95
|
-
* A streaming chunk from the output that generated the event.
|
|
96
|
-
* chunks support addition in general, and adding them up should result
|
|
97
|
-
* in the output of the runnable that generated the event.
|
|
98
|
-
*/
|
|
99
|
-
chunk?: any;
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* A streaming event.
|
|
103
|
-
*
|
|
104
|
-
* Schema of a streaming event which is produced from the streamEvents method.
|
|
105
|
-
*/
|
|
106
|
-
export type StreamEvent = {
|
|
107
|
-
/**
|
|
108
|
-
* Event names are of the format: on_[runnable_type]_(start|stream|end).
|
|
109
|
-
*
|
|
110
|
-
* Runnable types are one of:
|
|
111
|
-
* - llm - used by non chat models
|
|
112
|
-
* - chat_model - used by chat models
|
|
113
|
-
* - prompt -- e.g., ChatPromptTemplate
|
|
114
|
-
* - tool -- from tools defined via @tool decorator or inheriting from Tool/BaseTool
|
|
115
|
-
* - chain - most Runnables are of this type
|
|
116
|
-
*
|
|
117
|
-
* Further, the events are categorized as one of:
|
|
118
|
-
* - start - when the runnable starts
|
|
119
|
-
* - stream - when the runnable is streaming
|
|
120
|
-
* - end - when the runnable ends
|
|
121
|
-
*
|
|
122
|
-
* start, stream and end are associated with slightly different `data` payload.
|
|
123
|
-
*
|
|
124
|
-
* Please see the documentation for `EventData` for more details.
|
|
125
|
-
*/
|
|
126
|
-
event: string;
|
|
127
|
-
/** The name of the runnable that generated the event. */
|
|
128
|
-
name: string;
|
|
129
|
-
/**
|
|
130
|
-
* An randomly generated ID to keep track of the execution of the given runnable.
|
|
131
|
-
*
|
|
132
|
-
* Each child runnable that gets invoked as part of the execution of a parent runnable
|
|
133
|
-
* is assigned its own unique ID.
|
|
134
|
-
*/
|
|
135
|
-
run_id: string;
|
|
136
|
-
/**
|
|
137
|
-
* Tags associated with the runnable that generated this event.
|
|
138
|
-
* Tags are always inherited from parent runnables.
|
|
139
|
-
*/
|
|
140
|
-
tags?: string[];
|
|
141
|
-
/** Metadata associated with the runnable that generated this event. */
|
|
142
|
-
metadata: Record<string, any>;
|
|
143
|
-
/**
|
|
144
|
-
* Event data.
|
|
145
|
-
*
|
|
146
|
-
* The contents of the event data depend on the event type.
|
|
147
|
-
*/
|
|
148
|
-
data: StreamEventData;
|
|
149
|
-
};
|
|
150
75
|
export type SchemaFormat = "original" | "streaming_events";
|
|
151
76
|
export interface LogStreamCallbackHandlerInput extends BaseCallbackHandlerInput {
|
|
152
77
|
autoClose?: boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* eslint-disable no-process-env */
|
|
2
|
+
import * as uuid from "uuid";
|
|
3
|
+
import { test } from "@jest/globals";
|
|
4
|
+
import { LangChainTracer } from "../tracer_langchain.js";
|
|
5
|
+
import { HumanMessage } from "../../messages/index.js";
|
|
6
|
+
const serialized = {
|
|
7
|
+
lc: 1,
|
|
8
|
+
type: "constructor",
|
|
9
|
+
id: ["test"],
|
|
10
|
+
kwargs: {},
|
|
11
|
+
};
|
|
12
|
+
test("LangChain V2 tracer does not throw errors for its methods", async () => {
|
|
13
|
+
const tracer = new LangChainTracer({
|
|
14
|
+
projectName: `JS Int Test - ${uuid.v4()}`,
|
|
15
|
+
});
|
|
16
|
+
const chainRunId = uuid.v4();
|
|
17
|
+
const toolRunId = uuid.v4();
|
|
18
|
+
const llmRunId = uuid.v4();
|
|
19
|
+
const chatRunId = uuid.v4();
|
|
20
|
+
await tracer.handleChainStart(serialized, { foo: "bar" }, chainRunId);
|
|
21
|
+
await tracer.handleToolStart(serialized, "test", toolRunId, chainRunId);
|
|
22
|
+
await tracer.handleLLMStart(serialized, ["test"], llmRunId, toolRunId);
|
|
23
|
+
await tracer.handleLLMEnd({ generations: [[]] }, llmRunId);
|
|
24
|
+
await tracer.handleChatModelStart(serialized, [[new HumanMessage("I'm a human.")]], chatRunId);
|
|
25
|
+
await tracer.handleLLMEnd({ generations: [[]] }, chatRunId);
|
|
26
|
+
await tracer.handleToolEnd("output", toolRunId);
|
|
27
|
+
const llmRunId2 = uuid.v4();
|
|
28
|
+
await tracer.handleLLMStart(serialized, ["test"], llmRunId2, chainRunId);
|
|
29
|
+
await tracer.handleLLMEnd({ generations: [[]] }, llmRunId2);
|
|
30
|
+
await tracer.handleChainEnd({ foo: "bar" }, chainRunId);
|
|
31
|
+
const llmRunId3 = uuid.v4();
|
|
32
|
+
await tracer.handleLLMStart(serialized, ["test"], llmRunId3);
|
|
33
|
+
await tracer.handleLLMEnd({ generations: [[]] }, llmRunId3);
|
|
34
|
+
});
|
|
35
|
+
class FakeTracer extends LangChainTracer {
|
|
36
|
+
constructor() {
|
|
37
|
+
super(...arguments);
|
|
38
|
+
Object.defineProperty(this, "createOperations", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: {}
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(this, "updateOperations", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
47
|
+
writable: true,
|
|
48
|
+
value: {}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async onRunCreate(run) {
|
|
52
|
+
this.createOperations[run.id] = run;
|
|
53
|
+
}
|
|
54
|
+
async onRunUpdate(run) {
|
|
55
|
+
this.updateOperations[run.id] = run;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
test("LangChain V2 tracer creates and updates runs with trace_id and dotted_order", async () => {
|
|
59
|
+
const tracer = new FakeTracer({
|
|
60
|
+
projectName: `JS Int Test - ${uuid.v4()}`,
|
|
61
|
+
});
|
|
62
|
+
const chainRunId = uuid.v4();
|
|
63
|
+
const llmRunId = uuid.v4();
|
|
64
|
+
await tracer.handleChainStart(serialized, { foo: "bar" }, chainRunId);
|
|
65
|
+
await tracer.handleLLMStart(serialized, ["test"], llmRunId, chainRunId);
|
|
66
|
+
await tracer.handleLLMEnd({ generations: [[]] }, llmRunId);
|
|
67
|
+
await tracer.handleChainEnd({ foo: "bar" }, chainRunId);
|
|
68
|
+
expect(tracer.createOperations[chainRunId].trace_id).toBeDefined();
|
|
69
|
+
expect(tracer.createOperations[chainRunId].trace_id).toEqual(chainRunId);
|
|
70
|
+
expect(tracer.createOperations[chainRunId].dotted_order).toBeDefined();
|
|
71
|
+
expect(tracer.updateOperations[llmRunId].trace_id).toBeDefined();
|
|
72
|
+
expect(tracer.updateOperations[llmRunId].trace_id).toEqual(chainRunId);
|
|
73
|
+
expect(tracer.updateOperations[llmRunId].dotted_order).toBeDefined();
|
|
74
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|