140 lines
5.5 KiB
JavaScript
140 lines
5.5 KiB
JavaScript
|
"use strict";
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.RunnableTraceable = exports.getLangchainCallbacks = void 0;
|
||
|
// These `@langchain/core` imports are intentionally not peer dependencies
|
||
|
// to avoid package manager issues around circular dependencies.
|
||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||
|
const manager_1 = require("@langchain/core/callbacks/manager");
|
||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||
|
const tracer_langchain_1 = require("@langchain/core/tracers/tracer_langchain");
|
||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||
|
const runnables_1 = require("@langchain/core/runnables");
|
||
|
const traceable_js_1 = require("./traceable.cjs");
|
||
|
const asserts_js_1 = require("./utils/asserts.cjs");
|
||
|
/**
|
||
|
* Converts the current run tree active within a traceable-wrapped function
|
||
|
* into a LangChain compatible callback manager. This is useful to handoff tracing
|
||
|
* from LangSmith to LangChain Runnables and LLMs.
|
||
|
*
|
||
|
* @param {RunTree | undefined} currentRunTree Current RunTree from within a traceable-wrapped function. If not provided, the current run tree will be inferred from AsyncLocalStorage.
|
||
|
* @returns {CallbackManager | undefined} Callback manager used by LangChain Runnable objects.
|
||
|
*/
|
||
|
async function getLangchainCallbacks(currentRunTree) {
|
||
|
const runTree = currentRunTree ?? (0, traceable_js_1.getCurrentRunTree)();
|
||
|
if (!runTree)
|
||
|
return undefined;
|
||
|
// TODO: CallbackManager.configure() is only async due to LangChainTracer
|
||
|
// factory being unnecessarily async.
|
||
|
let callbacks = await manager_1.CallbackManager.configure();
|
||
|
if (!callbacks && runTree.tracingEnabled) {
|
||
|
callbacks = new manager_1.CallbackManager();
|
||
|
}
|
||
|
let langChainTracer = callbacks?.handlers.find((handler) => handler?.name === "langchain_tracer");
|
||
|
if (!langChainTracer && runTree.tracingEnabled) {
|
||
|
langChainTracer = new tracer_langchain_1.LangChainTracer();
|
||
|
callbacks?.addHandler(langChainTracer);
|
||
|
}
|
||
|
const runMap = new Map();
|
||
|
// find upward root run
|
||
|
let rootRun = runTree;
|
||
|
const rootVisited = new Set();
|
||
|
while (rootRun.parent_run) {
|
||
|
if (rootVisited.has(rootRun.id))
|
||
|
break;
|
||
|
rootVisited.add(rootRun.id);
|
||
|
rootRun = rootRun.parent_run;
|
||
|
}
|
||
|
const queue = [rootRun];
|
||
|
const visited = new Set();
|
||
|
while (queue.length > 0) {
|
||
|
const current = queue.shift();
|
||
|
if (!current || visited.has(current.id))
|
||
|
continue;
|
||
|
visited.add(current.id);
|
||
|
runMap.set(current.id, current);
|
||
|
if (current.child_runs) {
|
||
|
queue.push(...current.child_runs);
|
||
|
}
|
||
|
}
|
||
|
if (callbacks != null) {
|
||
|
Object.assign(callbacks, { _parentRunId: runTree.id });
|
||
|
}
|
||
|
if (langChainTracer != null) {
|
||
|
if ("updateFromRunTree" in langChainTracer &&
|
||
|
typeof langChainTracer === "function") {
|
||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||
|
// @ts-ignore @langchain/core can use a different version of LangSmith
|
||
|
langChainTracer.updateFromRunTree(runTree);
|
||
|
}
|
||
|
else {
|
||
|
Object.assign(langChainTracer, {
|
||
|
runMap,
|
||
|
client: runTree.client,
|
||
|
projectName: runTree.project_name || langChainTracer.projectName,
|
||
|
exampleId: runTree.reference_example_id || langChainTracer.exampleId,
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
return callbacks;
|
||
|
}
|
||
|
exports.getLangchainCallbacks = getLangchainCallbacks;
|
||
|
/**
|
||
|
* RunnableTraceable is a Runnable that wraps a traceable function.
|
||
|
* This allows adding Langsmith traced functions into LangChain sequences.
|
||
|
*/
|
||
|
class RunnableTraceable extends runnables_1.Runnable {
|
||
|
constructor(fields) {
|
||
|
super(fields);
|
||
|
Object.defineProperty(this, "lc_serializable", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: false
|
||
|
});
|
||
|
Object.defineProperty(this, "lc_namespace", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: ["langchain_core", "runnables"]
|
||
|
});
|
||
|
Object.defineProperty(this, "func", {
|
||
|
enumerable: true,
|
||
|
configurable: true,
|
||
|
writable: true,
|
||
|
value: void 0
|
||
|
});
|
||
|
if (!(0, traceable_js_1.isTraceableFunction)(fields.func)) {
|
||
|
throw new Error("RunnableTraceable requires a function that is wrapped in traceable higher-order function");
|
||
|
}
|
||
|
this.func = fields.func;
|
||
|
}
|
||
|
async invoke(input, options) {
|
||
|
const [config] = this._getOptionsList(options ?? {}, 1);
|
||
|
const callbacks = await (0, runnables_1.getCallbackManagerForConfig)(config);
|
||
|
return (await this.func((0, runnables_1.patchConfig)(config, { callbacks }), input));
|
||
|
}
|
||
|
async *_streamIterator(input, options) {
|
||
|
const result = await this.invoke(input, options);
|
||
|
if ((0, asserts_js_1.isAsyncIterable)(result)) {
|
||
|
for await (const item of result) {
|
||
|
yield item;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
if ((0, asserts_js_1.isIteratorLike)(result)) {
|
||
|
while (true) {
|
||
|
const state = result.next();
|
||
|
if (state.done)
|
||
|
break;
|
||
|
yield state.value;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
yield result;
|
||
|
}
|
||
|
static from(func) {
|
||
|
return new RunnableTraceable({ func });
|
||
|
}
|
||
|
}
|
||
|
exports.RunnableTraceable = RunnableTraceable;
|