UNPKG

@langchain/core

Version:
1 lines 20.3 kB
{"version":3,"file":"log_stream.cjs","names":["applyPatch","BaseTracer","IterableReadableStream","AIMessageChunk"],"sources":["../../src/tracers/log_stream.ts"],"sourcesContent":["import {\n applyPatch,\n type Operation as JSONPatchOperation,\n} from \"../utils/fast-json-patch/index.js\";\nimport { BaseTracer, type Run } from \"./base.js\";\nimport {\n BaseCallbackHandler,\n BaseCallbackHandlerInput,\n CallbackHandlerPrefersStreaming,\n HandleLLMNewTokenCallbackFields,\n} from \"../callbacks/base.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { ChatGenerationChunk, GenerationChunk } from \"../outputs.js\";\nimport { AIMessageChunk } from \"../messages/ai.js\";\nimport type { StreamEvent, StreamEventData } from \"./event_stream.js\";\n\nexport type { StreamEvent, StreamEventData };\n\n/**\n * Interface that represents the structure of a log entry in the\n * `LogStreamCallbackHandler`.\n */\nexport type LogEntry = {\n /** ID of the sub-run. */\n id: string;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n /** List of tags for the run. */\n tags: string[];\n /** Key-value pairs of metadata for the run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n metadata: Record<string, any>;\n /** ISO-8601 timestamp of when the run started. */\n start_time: string;\n /** List of general output chunks streamed by this run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** List of LLM tokens streamed by this run, if applicable. */\n streamed_output_str: string[];\n /** Inputs to this run. Not available currently via streamLog. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n inputs?: any;\n /** Final output of this run. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /** ISO-8601 timestamp of when the run ended. Only available after the run has finished. */\n end_time?: string;\n};\n\nexport type RunState = {\n /** ID of the sub-run. */\n id: string;\n /** List of output chunks streamed by Runnable.stream() */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** Final output of the run, usually the result of aggregating streamed_output. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /**\n * List of sub-runs contained in this run, if any, in the order they were started.\n * If filters were supplied, this list will contain only the runs that matched the filters.\n */\n logs: Record<string, LogEntry>;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n};\n\n/**\n * List of jsonpatch JSONPatchOperations, which describe how to create the run state\n * from an empty dict. This is the minimal representation of the log, designed to\n * be serialized as JSON and sent over the wire to reconstruct the log on the other\n * side. Reconstruction of the state can be done with any jsonpatch-compliant library,\n * see https://jsonpatch.com for more information.\n */\nexport class RunLogPatch {\n ops: JSONPatchOperation[];\n\n constructor(fields: { ops?: JSONPatchOperation[] }) {\n this.ops = fields.ops ?? [];\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch({}, ops);\n // oxlint-disable-next-line @typescript-eslint/no-use-before-define\n return new RunLog({\n ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport class RunLog extends RunLogPatch {\n state: RunState;\n\n constructor(fields: { ops?: JSONPatchOperation[]; state: RunState }) {\n super(fields);\n this.state = fields.state;\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch(this.state, other.ops);\n return new RunLog({ ops, state: states[states.length - 1].newDocument });\n }\n\n static fromRunLogPatch(patch: RunLogPatch) {\n const states = applyPatch({}, patch.ops);\n return new RunLog({\n ops: patch.ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport type SchemaFormat = \"original\" | \"streaming_events\";\n\nexport interface LogStreamCallbackHandlerInput extends BaseCallbackHandlerInput {\n autoClose?: boolean;\n includeNames?: string[];\n includeTypes?: string[];\n includeTags?: string[];\n excludeNames?: string[];\n excludeTypes?: string[];\n excludeTags?: string[];\n _schemaFormat?: SchemaFormat;\n}\n\nexport const isLogStreamHandler = (\n handler: BaseCallbackHandler\n): handler is LogStreamCallbackHandler => handler.name === \"log_stream_tracer\";\n\n/**\n * Extract standardized inputs from a run.\n *\n * Standardizes the inputs based on the type of the runnable used.\n *\n * @param run - Run object\n * @param schemaFormat - The schema format to use.\n *\n * @returns Valid inputs are only dict. By conventions, inputs always represented\n * invocation using named arguments.\n * A null means that the input is not yet known!\n */\nasync function _getStandardizedInputs(run: Run, schemaFormat: SchemaFormat) {\n if (schemaFormat === \"original\") {\n throw new Error(\n \"Do not assign inputs with original schema drop the key for now. \" +\n \"When inputs are added to streamLog they should be added with \" +\n \"standardized schema for streaming events.\"\n );\n }\n\n const { inputs } = run;\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return inputs;\n }\n\n if (Object.keys(inputs).length === 1 && inputs?.input === \"\") {\n return undefined;\n }\n\n // new style chains\n // These nest an additional 'input' key inside the 'inputs' to make sure\n // the input is always a dict. We need to unpack and user the inner value.\n // We should try to fix this in Runnables and callbacks/tracers\n // Runnables should be using a null type here not a placeholder\n // dict.\n return inputs.input;\n}\n\nasync function _getStandardizedOutputs(run: Run, schemaFormat: SchemaFormat) {\n const { outputs } = run;\n if (schemaFormat === \"original\") {\n // Return the old schema, without standardizing anything\n return outputs;\n }\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return outputs;\n }\n\n // TODO: Remove this hacky check\n if (\n outputs !== undefined &&\n Object.keys(outputs).length === 1 &&\n outputs?.output !== undefined\n ) {\n return outputs.output;\n }\n\n return outputs;\n}\n\nfunction isChatGenerationChunk(\n x?: ChatGenerationChunk | GenerationChunk\n): x is ChatGenerationChunk {\n return x !== undefined && (x as ChatGenerationChunk).message !== undefined;\n}\n\n/**\n * Class that extends the `BaseTracer` class from the\n * `langchain.callbacks.tracers.base` module. It represents a callback\n * handler that logs the execution of runs and emits `RunLog` instances to a\n * `RunLogStream`.\n */\nexport class LogStreamCallbackHandler\n extends BaseTracer\n implements CallbackHandlerPrefersStreaming\n{\n protected autoClose = true;\n\n protected includeNames?: string[];\n\n protected includeTypes?: string[];\n\n protected includeTags?: string[];\n\n protected excludeNames?: string[];\n\n protected excludeTypes?: string[];\n\n protected excludeTags?: string[];\n\n protected _schemaFormat: SchemaFormat = \"original\";\n\n protected rootId?: string;\n\n private keyMapByRunId: Record<string, string> = {};\n\n private counterMapByRunName: Record<string, number> = {};\n\n protected transformStream: TransformStream;\n\n public writer: WritableStreamDefaultWriter;\n\n public receiveStream: IterableReadableStream<RunLogPatch>;\n\n name = \"log_stream_tracer\";\n\n lc_prefer_streaming = true;\n\n constructor(fields?: LogStreamCallbackHandlerInput) {\n super({ _awaitHandler: true, ...fields });\n this.autoClose = fields?.autoClose ?? true;\n this.includeNames = fields?.includeNames;\n this.includeTypes = fields?.includeTypes;\n this.includeTags = fields?.includeTags;\n this.excludeNames = fields?.excludeNames;\n this.excludeTypes = fields?.excludeTypes;\n this.excludeTags = fields?.excludeTags;\n this._schemaFormat = fields?._schemaFormat ?? this._schemaFormat;\n this.transformStream = new TransformStream();\n this.writer = this.transformStream.writable.getWriter();\n this.receiveStream = IterableReadableStream.fromReadableStream(\n this.transformStream.readable\n );\n }\n\n [Symbol.asyncIterator]() {\n return this.receiveStream;\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // This is a legacy method only called once for an entire run tree\n // and is therefore not useful here\n }\n\n _includeRun(run: Run): boolean {\n if (run.id === this.rootId) {\n return false;\n }\n const runTags = run.tags ?? [];\n let include =\n this.includeNames === undefined &&\n this.includeTags === undefined &&\n this.includeTypes === undefined;\n if (this.includeNames !== undefined) {\n include = include || this.includeNames.includes(run.name);\n }\n if (this.includeTypes !== undefined) {\n include = include || this.includeTypes.includes(run.run_type);\n }\n if (this.includeTags !== undefined) {\n include =\n include ||\n runTags.find((tag) => this.includeTags?.includes(tag)) !== undefined;\n }\n if (this.excludeNames !== undefined) {\n include = include && !this.excludeNames.includes(run.name);\n }\n if (this.excludeTypes !== undefined) {\n include = include && !this.excludeTypes.includes(run.run_type);\n }\n if (this.excludeTags !== undefined) {\n include =\n include && runTags.every((tag) => !this.excludeTags?.includes(tag));\n }\n return include;\n }\n\n async *tapOutputIterable<T>(\n runId: string,\n output: AsyncGenerator<T>\n ): AsyncGenerator<T> {\n // Tap an output async iterator to stream its values to the log.\n for await (const chunk of output) {\n // root run is handled in .streamLog()\n if (runId !== this.rootId) {\n // if we can't find the run silently ignore\n // eg. because this run wasn't included in the log\n const key = this.keyMapByRunId[runId];\n if (key) {\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${key}/streamed_output/-`,\n value: chunk,\n },\n ],\n })\n );\n }\n }\n yield chunk;\n }\n }\n\n async onRunCreate(run: Run): Promise<void> {\n if (this.rootId === undefined) {\n this.rootId = run.id;\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"\",\n value: {\n id: run.id,\n name: run.name,\n type: run.run_type,\n streamed_output: [],\n final_output: undefined,\n logs: {},\n },\n },\n ],\n })\n );\n }\n\n if (!this._includeRun(run)) {\n return;\n }\n\n if (this.counterMapByRunName[run.name] === undefined) {\n this.counterMapByRunName[run.name] = 0;\n }\n this.counterMapByRunName[run.name] += 1;\n const count = this.counterMapByRunName[run.name];\n this.keyMapByRunId[run.id] =\n count === 1 ? run.name : `${run.name}:${count}`;\n\n const logEntry: LogEntry = {\n id: run.id,\n name: run.name,\n type: run.run_type,\n tags: run.tags ?? [],\n metadata: run.extra?.metadata ?? {},\n start_time: new Date(run.start_time).toISOString(),\n streamed_output: [],\n streamed_output_str: [],\n final_output: undefined,\n end_time: undefined,\n };\n\n if (this._schemaFormat === \"streaming_events\") {\n logEntry.inputs = await _getStandardizedInputs(run, this._schemaFormat);\n }\n\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${this.keyMapByRunId[run.id]}`,\n value: logEntry,\n },\n ],\n })\n );\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n try {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n const ops: JSONPatchOperation[] = [];\n if (this._schemaFormat === \"streaming_events\") {\n ops.push({\n op: \"replace\",\n path: `/logs/${runName}/inputs`,\n value: await _getStandardizedInputs(run, this._schemaFormat),\n });\n }\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/final_output`,\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n });\n if (run.end_time !== undefined) {\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/end_time`,\n value: new Date(run.end_time).toISOString(),\n });\n }\n const patch = new RunLogPatch({ ops });\n await this.writer.write(patch);\n } finally {\n if (run.id === this.rootId) {\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"/final_output\",\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n },\n ],\n });\n await this.writer.write(patch);\n if (this.autoClose) {\n await this.writer.close();\n }\n }\n }\n }\n\n async onLLMNewToken(\n run: Run,\n token: string,\n kwargs?: HandleLLMNewTokenCallbackFields\n ): Promise<void> {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n // TODO: Remove hack\n const isChatModel = run.inputs.messages !== undefined;\n let streamedOutputValue;\n if (isChatModel) {\n if (isChatGenerationChunk(kwargs?.chunk)) {\n streamedOutputValue = kwargs?.chunk;\n } else {\n streamedOutputValue = new AIMessageChunk({\n id: `run-${run.id}`,\n content: token,\n });\n }\n } else {\n streamedOutputValue = token;\n }\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output_str/-`,\n value: token,\n },\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output/-`,\n value: streamedOutputValue,\n },\n ],\n });\n await this.writer.write(patch);\n }\n}\n"],"mappings":"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"}