UNPKG

@langchain/core

Version:
443 lines (441 loc) 14.8 kB
import { __export } from "../_virtual/rolldown_runtime.js"; import { getRuntimeEnvironment } from "../utils/env.js"; import { BaseCallbackHandler } from "../callbacks/base.js"; import { RunTree, convertToDottedOrderFormat } from "langsmith/run_trees"; //#region src/tracers/base.ts var base_exports = {}; __export(base_exports, { BaseTracer: () => BaseTracer, isBaseTracer: () => isBaseTracer }); const convertRunTreeToRun = (runTree) => { if (!runTree) return void 0; runTree.events = runTree.events ?? []; runTree.child_runs = runTree.child_runs ?? []; return runTree; }; function convertRunToRunTree(run, parentRun) { if (!run) return void 0; return new RunTree({ ...run, start_time: run._serialized_start_time ?? run.start_time, parent_run: convertRunToRunTree(parentRun), child_runs: run.child_runs.map((r) => convertRunToRunTree(r)).filter((r) => r !== void 0), extra: { ...run.extra, runtime: getRuntimeEnvironment() }, tracingEnabled: false }); } function _coerceToDict(value, defaultKey) { return value && !Array.isArray(value) && typeof value === "object" ? value : { [defaultKey]: value }; } function isBaseTracer(x) { return typeof x._addRunToRunMap === "function"; } var BaseTracer = class extends BaseCallbackHandler { /** @deprecated Use `runTreeMap` instead. */ runMap = /* @__PURE__ */ new Map(); runTreeMap = /* @__PURE__ */ new Map(); usesRunTreeMap = false; constructor(_fields) { super(...arguments); } copy() { return this; } getRunById(runId) { if (runId === void 0) return void 0; return this.usesRunTreeMap ? convertRunTreeToRun(this.runTreeMap.get(runId)) : this.runMap.get(runId); } stringifyError(error) { if (error instanceof Error) return error.message + (error?.stack ? `\n\n${error.stack}` : ""); if (typeof error === "string") return error; return `${error}`; } _addChildRun(parentRun, childRun) { parentRun.child_runs.push(childRun); } _addRunToRunMap(run) { const { dottedOrder: currentDottedOrder, microsecondPrecisionDatestring } = convertToDottedOrderFormat(new Date(run.start_time).getTime(), run.id, run.execution_order); const storedRun = { ...run }; const parentRun = this.getRunById(storedRun.parent_run_id); if (storedRun.parent_run_id !== void 0) { if (parentRun) { this._addChildRun(parentRun, storedRun); parentRun.child_execution_order = Math.max(parentRun.child_execution_order, storedRun.child_execution_order); storedRun.trace_id = parentRun.trace_id; if (parentRun.dotted_order !== void 0) { storedRun.dotted_order = [parentRun.dotted_order, currentDottedOrder].join("."); storedRun._serialized_start_time = microsecondPrecisionDatestring; } } } else { storedRun.trace_id = storedRun.id; storedRun.dotted_order = currentDottedOrder; storedRun._serialized_start_time = microsecondPrecisionDatestring; } if (this.usesRunTreeMap) { const runTree = convertRunToRunTree(storedRun, parentRun); if (runTree !== void 0) this.runTreeMap.set(storedRun.id, runTree); } else this.runMap.set(storedRun.id, storedRun); return storedRun; } async _endTrace(run) { const parentRun = run.parent_run_id !== void 0 && this.getRunById(run.parent_run_id); if (parentRun) parentRun.child_execution_order = Math.max(parentRun.child_execution_order, run.child_execution_order); else await this.persistRun(run); await this.onRunUpdate?.(run); if (this.usesRunTreeMap) this.runTreeMap.delete(run.id); else this.runMap.delete(run.id); } _getExecutionOrder(parentRunId) { const parentRun = parentRunId !== void 0 && this.getRunById(parentRunId); if (!parentRun) return 1; return parentRun.child_execution_order + 1; } /** * Create and add a run to the run map for LLM start events. * This must sometimes be done synchronously to avoid race conditions * when callbacks are backgrounded, so we expose it as a separate method here. */ _createRunForLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, name) { const execution_order = this._getExecutionOrder(parentRunId); const start_time = Date.now(); const finalExtraParams = metadata ? { ...extraParams, metadata } : extraParams; const run = { id: runId, name: name ?? llm.id[llm.id.length - 1], parent_run_id: parentRunId, start_time, serialized: llm, events: [{ name: "start", time: new Date(start_time).toISOString() }], inputs: { prompts }, execution_order, child_runs: [], child_execution_order: execution_order, run_type: "llm", extra: finalExtraParams ?? {}, tags: tags || [] }; return this._addRunToRunMap(run); } async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, name) { const run = this.getRunById(runId) ?? this._createRunForLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, name); await this.onRunCreate?.(run); await this.onLLMStart?.(run); return run; } /** * Create and add a run to the run map for chat model start events. * This must sometimes be done synchronously to avoid race conditions * when callbacks are backgrounded, so we expose it as a separate method here. */ _createRunForChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name) { const execution_order = this._getExecutionOrder(parentRunId); const start_time = Date.now(); const finalExtraParams = metadata ? { ...extraParams, metadata } : extraParams; const run = { id: runId, name: name ?? llm.id[llm.id.length - 1], parent_run_id: parentRunId, start_time, serialized: llm, events: [{ name: "start", time: new Date(start_time).toISOString() }], inputs: { messages }, execution_order, child_runs: [], child_execution_order: execution_order, run_type: "llm", extra: finalExtraParams ?? {}, tags: tags || [] }; return this._addRunToRunMap(run); } async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name) { const run = this.getRunById(runId) ?? this._createRunForChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name); await this.onRunCreate?.(run); await this.onLLMStart?.(run); return run; } async handleLLMEnd(output, runId, _parentRunId, _tags, extraParams) { const run = this.getRunById(runId); if (!run || run?.run_type !== "llm") throw new Error("No LLM run to end."); run.end_time = Date.now(); run.outputs = output; run.events.push({ name: "end", time: new Date(run.end_time).toISOString() }); run.extra = { ...run.extra, ...extraParams }; await this.onLLMEnd?.(run); await this._endTrace(run); return run; } async handleLLMError(error, runId, _parentRunId, _tags, extraParams) { const run = this.getRunById(runId); if (!run || run?.run_type !== "llm") throw new Error("No LLM run to end."); run.end_time = Date.now(); run.error = this.stringifyError(error); run.events.push({ name: "error", time: new Date(run.end_time).toISOString() }); run.extra = { ...run.extra, ...extraParams }; await this.onLLMError?.(run); await this._endTrace(run); return run; } /** * Create and add a run to the run map for chain start events. * This must sometimes be done synchronously to avoid race conditions * when callbacks are backgrounded, so we expose it as a separate method here. */ _createRunForChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name) { const execution_order = this._getExecutionOrder(parentRunId); const start_time = Date.now(); const run = { id: runId, name: name ?? chain.id[chain.id.length - 1], parent_run_id: parentRunId, start_time, serialized: chain, events: [{ name: "start", time: new Date(start_time).toISOString() }], inputs, execution_order, child_execution_order: execution_order, run_type: runType ?? "chain", child_runs: [], extra: metadata ? { metadata } : {}, tags: tags || [] }; return this._addRunToRunMap(run); } async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name) { const run = this.getRunById(runId) ?? this._createRunForChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name); await this.onRunCreate?.(run); await this.onChainStart?.(run); return run; } async handleChainEnd(outputs, runId, _parentRunId, _tags, kwargs) { const run = this.getRunById(runId); if (!run) throw new Error("No chain run to end."); run.end_time = Date.now(); run.outputs = _coerceToDict(outputs, "output"); run.events.push({ name: "end", time: new Date(run.end_time).toISOString() }); if (kwargs?.inputs !== void 0) run.inputs = _coerceToDict(kwargs.inputs, "input"); await this.onChainEnd?.(run); await this._endTrace(run); return run; } async handleChainError(error, runId, _parentRunId, _tags, kwargs) { const run = this.getRunById(runId); if (!run) throw new Error("No chain run to end."); run.end_time = Date.now(); run.error = this.stringifyError(error); run.events.push({ name: "error", time: new Date(run.end_time).toISOString() }); if (kwargs?.inputs !== void 0) run.inputs = _coerceToDict(kwargs.inputs, "input"); await this.onChainError?.(run); await this._endTrace(run); return run; } /** * Create and add a run to the run map for tool start events. * This must sometimes be done synchronously to avoid race conditions * when callbacks are backgrounded, so we expose it as a separate method here. */ _createRunForToolStart(tool, input, runId, parentRunId, tags, metadata, name) { const execution_order = this._getExecutionOrder(parentRunId); const start_time = Date.now(); const run = { id: runId, name: name ?? tool.id[tool.id.length - 1], parent_run_id: parentRunId, start_time, serialized: tool, events: [{ name: "start", time: new Date(start_time).toISOString() }], inputs: { input }, execution_order, child_execution_order: execution_order, run_type: "tool", child_runs: [], extra: metadata ? { metadata } : {}, tags: tags || [] }; return this._addRunToRunMap(run); } async handleToolStart(tool, input, runId, parentRunId, tags, metadata, name) { const run = this.getRunById(runId) ?? this._createRunForToolStart(tool, input, runId, parentRunId, tags, metadata, name); await this.onRunCreate?.(run); await this.onToolStart?.(run); return run; } async handleToolEnd(output, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "tool") throw new Error("No tool run to end"); run.end_time = Date.now(); run.outputs = { output }; run.events.push({ name: "end", time: new Date(run.end_time).toISOString() }); await this.onToolEnd?.(run); await this._endTrace(run); return run; } async handleToolError(error, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "tool") throw new Error("No tool run to end"); run.end_time = Date.now(); run.error = this.stringifyError(error); run.events.push({ name: "error", time: new Date(run.end_time).toISOString() }); await this.onToolError?.(run); await this._endTrace(run); return run; } async handleAgentAction(action, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "chain") return; const agentRun = run; agentRun.actions = agentRun.actions || []; agentRun.actions.push(action); agentRun.events.push({ name: "agent_action", time: (/* @__PURE__ */ new Date()).toISOString(), kwargs: { action } }); await this.onAgentAction?.(run); } async handleAgentEnd(action, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "chain") return; run.events.push({ name: "agent_end", time: (/* @__PURE__ */ new Date()).toISOString(), kwargs: { action } }); await this.onAgentEnd?.(run); } /** * Create and add a run to the run map for retriever start events. * This must sometimes be done synchronously to avoid race conditions * when callbacks are backgrounded, so we expose it as a separate method here. */ _createRunForRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) { const execution_order = this._getExecutionOrder(parentRunId); const start_time = Date.now(); const run = { id: runId, name: name ?? retriever.id[retriever.id.length - 1], parent_run_id: parentRunId, start_time, serialized: retriever, events: [{ name: "start", time: new Date(start_time).toISOString() }], inputs: { query }, execution_order, child_execution_order: execution_order, run_type: "retriever", child_runs: [], extra: metadata ? { metadata } : {}, tags: tags || [] }; return this._addRunToRunMap(run); } async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) { const run = this.getRunById(runId) ?? this._createRunForRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name); await this.onRunCreate?.(run); await this.onRetrieverStart?.(run); return run; } async handleRetrieverEnd(documents, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "retriever") throw new Error("No retriever run to end"); run.end_time = Date.now(); run.outputs = { documents }; run.events.push({ name: "end", time: new Date(run.end_time).toISOString() }); await this.onRetrieverEnd?.(run); await this._endTrace(run); return run; } async handleRetrieverError(error, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "retriever") throw new Error("No retriever run to end"); run.end_time = Date.now(); run.error = this.stringifyError(error); run.events.push({ name: "error", time: new Date(run.end_time).toISOString() }); await this.onRetrieverError?.(run); await this._endTrace(run); return run; } async handleText(text, runId) { const run = this.getRunById(runId); if (!run || run?.run_type !== "chain") return; run.events.push({ name: "text", time: (/* @__PURE__ */ new Date()).toISOString(), kwargs: { text } }); await this.onText?.(run); } async handleLLMNewToken(token, idx, runId, _parentRunId, _tags, fields) { const run = this.getRunById(runId); if (!run || run?.run_type !== "llm") throw new Error(`Invalid "runId" provided to "handleLLMNewToken" callback.`); run.events.push({ name: "new_token", time: (/* @__PURE__ */ new Date()).toISOString(), kwargs: { token, idx, chunk: fields?.chunk } }); await this.onLLMNewToken?.(run, token, { chunk: fields?.chunk }); return run; } }; //#endregion export { BaseTracer, base_exports, isBaseTracer }; //# sourceMappingURL=base.js.map