@langchain/core
Version:
Core LangChain.js abstractions and schemas
1 lines • 14.4 kB
Source Map (JSON)
{"version":3,"file":"tracer_langchain.cjs","names":["AIMessage","mergeUsageMetadata","BaseTracer","getDefaultLangChainClientSingleton","RunTree"],"sources":["../../src/tracers/tracer_langchain.ts"],"sourcesContent":["import {\n type Client,\n type LangSmithTracingClientInterface,\n getDefaultProjectName,\n} from \"langsmith\";\nimport { RunTree, type RunTreeConfig } from \"langsmith/run_trees\";\nimport { getCurrentRunTree } from \"langsmith/singletons/traceable\";\n\nimport {\n BaseRun,\n RunCreate,\n RunUpdate as BaseRunUpdate,\n KVMap,\n} from \"langsmith/schemas\";\nimport { BaseTracer, Run as BaseTracerRun } from \"./base.js\";\nimport { BaseCallbackHandlerInput } from \"../callbacks/base.js\";\nimport { getDefaultLangChainClientSingleton } from \"../singletons/tracer.js\";\nimport { ChatGeneration } from \"../outputs.js\";\nimport { AIMessage } from \"../messages/ai.js\";\nimport { mergeUsageMetadata, UsageMetadata } from \"../messages/metadata.js\";\n\nexport interface Run extends BaseRun {\n id: string;\n child_runs: this[];\n child_execution_order: number;\n dotted_order?: string;\n trace_id?: string;\n}\n\nexport interface RunCreate2 extends RunCreate {\n trace_id?: string;\n dotted_order?: string;\n}\n\nexport interface RunUpdate extends BaseRunUpdate {\n events: BaseRun[\"events\"];\n inputs: KVMap;\n trace_id?: string;\n dotted_order?: string;\n}\n\nexport interface LangChainTracerFields extends BaseCallbackHandlerInput {\n exampleId?: string;\n projectName?: string;\n client?: LangSmithTracingClientInterface;\n replicas?: RunTreeConfig[\"replicas\"];\n metadata?: Record<string, unknown>;\n tags?: string[];\n}\n\n/**\n * Keys that should be inherited from `tracerInheritableMetadata` even when\n * the run already has a value for them. This lets nested contexts\n * (e.g. a subagent invoked from inside a parent agent) override a\n * LangSmith-only tracing metadata value that was set by an ancestor.\n *\n * Keep this list very small: every key here loses the default\n * \"first wins\" protection and is always clobbered by the nearest\n * enclosing tracer config. Only keys that are strictly for LangSmith\n * tracing bookkeeping should be added.\n */\nexport const OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS = new Set<string>([\n \"ls_agent_type\",\n]);\n\n/**\n * Extract usage_metadata from chat generations.\n *\n * Iterates through generations to find and aggregates all usage_metadata\n * found in chat messages. This is typically present in chat model outputs.\n */\nfunction _getUsageMetadataFromGenerations(\n generations: ChatGeneration[][]\n): UsageMetadata | undefined {\n let output: UsageMetadata | undefined = undefined;\n for (const generationBatch of generations) {\n for (const generation of generationBatch) {\n if (\n AIMessage.isInstance(generation.message) &&\n generation.message.usage_metadata !== undefined\n ) {\n output = mergeUsageMetadata(output, generation.message.usage_metadata);\n }\n }\n }\n return output;\n}\n\nexport class LangChainTracer\n extends BaseTracer\n implements LangChainTracerFields\n{\n name = \"langchain_tracer\";\n\n projectName?: string;\n\n exampleId?: string;\n\n client: LangSmithTracingClientInterface;\n\n replicas?: RunTreeConfig[\"replicas\"];\n\n usesRunTreeMap = true;\n\n tracingMetadata?: Record<string, unknown>;\n\n tracingTags: string[] = [];\n\n constructor(protected fields: LangChainTracerFields = {}) {\n super(fields);\n const { exampleId, projectName, client, replicas, metadata, tags } = fields;\n\n this.projectName = projectName ?? getDefaultProjectName();\n this.replicas = replicas;\n this.exampleId = exampleId;\n this.client = client ?? getDefaultLangChainClientSingleton();\n this.tracingMetadata = metadata ? { ...metadata } : undefined;\n this.tracingTags = tags ?? [];\n\n const traceableTree = LangChainTracer.getTraceableRunTree();\n if (traceableTree) {\n this.updateFromRunTree(traceableTree);\n }\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // empty\n }\n\n async onRunCreate(run: Run): Promise<void> {\n _patchMissingTracingDefaults(this, run);\n if (!run.extra?.lc_defers_inputs) {\n const runTree = this.getRunTreeWithTracingConfig(run.id);\n await runTree?.postRun();\n }\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n _patchMissingTracingDefaults(this, run);\n const runTree = this.getRunTreeWithTracingConfig(run.id);\n if (run.extra?.lc_defers_inputs) {\n await runTree?.postRun();\n } else {\n await runTree?.patchRun();\n }\n }\n\n onLLMEnd(run: BaseTracerRun): void {\n // Extract usage_metadata from outputs and store in extra.metadata\n const outputs = run.outputs as\n | { generations?: ChatGeneration[][] }\n | undefined;\n if (outputs?.generations) {\n const usageMetadata = _getUsageMetadataFromGenerations(\n outputs.generations\n );\n if (usageMetadata !== undefined) {\n run.extra = run.extra ?? {};\n const metadata =\n (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n metadata.usage_metadata = usageMetadata;\n run.extra.metadata = metadata;\n }\n }\n }\n\n copyWithTracingConfig({\n metadata,\n tags,\n }: {\n metadata?: Record<string, unknown>;\n tags?: string[];\n }): LangChainTracer {\n let mergedMetadata: Record<string, unknown> | undefined;\n if (metadata === undefined) {\n mergedMetadata = this.tracingMetadata\n ? { ...this.tracingMetadata }\n : undefined;\n } else if (this.tracingMetadata === undefined) {\n mergedMetadata = { ...metadata };\n } else {\n mergedMetadata = { ...this.tracingMetadata };\n for (const [key, value] of Object.entries(metadata)) {\n // For allowlisted LangSmith-only inheritable metadata keys (e.g.\n // `ls_agent_type`), nested callers are allowed to OVERRIDE the\n // value inherited from an ancestor. For all other keys we keep\n // the existing \"first wins\" behavior so that ancestor-provided\n // tracing metadata is not accidentally clobbered by child runs.\n if (\n !Object.prototype.hasOwnProperty.call(mergedMetadata, key) ||\n OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS.has(key)\n ) {\n mergedMetadata[key] = value;\n }\n }\n }\n\n const mergedTags = tags\n ? Array.from(new Set([...this.tracingTags, ...tags]))\n : [...this.tracingTags];\n\n const copied = new LangChainTracer({\n ...this.fields,\n metadata: mergedMetadata,\n tags: mergedTags,\n });\n copied.runMap = this.runMap;\n copied.runTreeMap = this.runTreeMap;\n return copied;\n }\n\n /** @internal */\n _getRunStoreKey(): object {\n return this.runTreeMap;\n }\n\n getRun(id: string): Run | undefined {\n return this.runTreeMap.get(id);\n }\n\n updateFromRunTree(runTree: RunTree) {\n this.runTreeMap.set(runTree.id, runTree);\n let rootRun: RunTree = runTree;\n const visited = new Set<string>();\n while (rootRun.parent_run) {\n if (visited.has(rootRun.id)) break;\n visited.add(rootRun.id);\n\n if (!rootRun.parent_run) break;\n rootRun = rootRun.parent_run as RunTree;\n }\n visited.clear();\n\n const queue = [rootRun];\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current || visited.has(current.id)) continue;\n visited.add(current.id);\n\n this.runTreeMap.set(current.id, current);\n if (current.child_runs) {\n queue.push(...current.child_runs);\n }\n }\n\n this.client = runTree.client ?? this.client;\n this.replicas = runTree.replicas ?? this.replicas;\n this.projectName = runTree.project_name ?? this.projectName;\n this.exampleId = runTree.reference_example_id ?? this.exampleId;\n this.fields = {\n ...this.fields,\n client: this.client,\n replicas: this.replicas,\n projectName: this.projectName,\n exampleId: this.exampleId,\n };\n }\n\n getRunTreeWithTracingConfig(id: string): RunTree | undefined {\n const runTree = this.runTreeMap.get(id);\n if (!runTree) return undefined;\n\n return new RunTree({\n ...runTree,\n client: this.client as Client,\n project_name: this.projectName,\n replicas: this.replicas,\n reference_example_id: this.exampleId,\n tracingEnabled: true,\n });\n }\n\n static getTraceableRunTree(): RunTree | undefined {\n try {\n return (\n // The type cast here provides forward compatibility. Old versions of LangSmith will just\n // ignore the permitAbsentRunTree arg.\n (\n getCurrentRunTree as (\n permitAbsentRunTree: boolean\n ) => ReturnType<typeof getCurrentRunTree> | undefined\n )(true)\n );\n } catch {\n return undefined;\n }\n }\n\n static [Symbol.hasInstance](instance: unknown): boolean {\n if (typeof instance !== \"object\" || instance === null) {\n return false;\n }\n const candidate = instance as Record<string, unknown>;\n return (\n \"name\" in candidate &&\n candidate.name === \"langchain_tracer\" &&\n \"copyWithTracingConfig\" in candidate &&\n typeof candidate.copyWithTracingConfig === \"function\" &&\n \"getRunTreeWithTracingConfig\" in candidate &&\n typeof candidate.getRunTreeWithTracingConfig === \"function\"\n );\n }\n}\n\nfunction _patchMissingTracingDefaults(tracer: LangChainTracer, run: Run): void {\n if (tracer.tracingMetadata) {\n run.extra ??= {};\n const metadata: Record<string, unknown> =\n (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n let didPatchMetadata = false;\n for (const [key, value] of Object.entries(tracer.tracingMetadata)) {\n // `OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS` are a small, LangSmith-only\n // allowlist that bypasses the \"first wins\" merge so a nested caller\n // (e.g. a subagent) can override a parent-set value.\n if (\n !Object.prototype.hasOwnProperty.call(metadata, key) ||\n OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS.has(key)\n ) {\n if (metadata[key] !== value) {\n metadata[key] = value;\n didPatchMetadata = true;\n }\n }\n }\n if (didPatchMetadata) {\n run.extra.metadata = metadata;\n }\n }\n\n if (tracer.tracingTags.length > 0) {\n run.tags = Array.from(\n new Set([...(run.tags ?? []), ...tracer.tracingTags])\n );\n }\n}\n"],"mappings":"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"}