import { BaseCallbackConfig, Callbacks } from "../callbacks/manager.js"; import { BasePromptValue, Generation, ChatGeneration, BaseMessage, } from "./index.js"; import { Runnable } from "./runnable/index.js"; import { RunnableConfig } from "./runnable/config.js"; /** * Options for formatting instructions. */ export interface FormatInstructionsOptions {} /** * Abstract base class for parsing the output of a Large Language Model * (LLM) call. It provides methods for parsing the result of an LLM call * and invoking the parser with a given input. */ export abstract class BaseLLMOutputParser extends Runnable< string | BaseMessage, T > { /** * Parses the result of an LLM call. This method is meant to be * implemented by subclasses to define how the output from the LLM should * be parsed. * @param generations The generations from an LLM call. * @param callbacks Optional callbacks. * @returns A promise of the parsed output. */ abstract parseResult( generations: Generation[] | ChatGeneration[], callbacks?: Callbacks ): Promise; /** * Parses the result of an LLM call with a given prompt. By default, it * simply calls `parseResult`. * @param generations The generations from an LLM call. * @param _prompt The prompt used in the LLM call. * @param callbacks Optional callbacks. * @returns A promise of the parsed output. */ parseResultWithPrompt( generations: Generation[] | ChatGeneration[], _prompt: BasePromptValue, callbacks?: Callbacks ): Promise { return this.parseResult(generations, callbacks); } /** * Calls the parser with a given input and optional configuration options. * If the input is a string, it creates a generation with the input as * text and calls `parseResult`. If the input is a `BaseMessage`, it * creates a generation with the input as a message and the content of the * input as text, and then calls `parseResult`. * @param input The input to the parser, which can be a string or a `BaseMessage`. * @param options Optional configuration options. * @returns A promise of the parsed output. */ async invoke( input: string | BaseMessage, options?: RunnableConfig ): Promise { if (typeof input === "string") { return this._callWithConfig( async (input: string): Promise => this.parseResult([{ text: input }]), input, { ...options, runType: "parser" } ); } else { return this._callWithConfig( async (input: BaseMessage): Promise => this.parseResult([{ message: input, text: input.content }]), input, { ...options, runType: "parser" } ); } } } /** * Class to parse the output of an LLM call. */ export abstract class BaseOutputParser< T = unknown > extends BaseLLMOutputParser { parseResult( generations: Generation[] | ChatGeneration[], callbacks?: Callbacks ): Promise { return this.parse(generations[0].text, callbacks); } /** * Parse the output of an LLM call. * * @param text - LLM output to parse. * @returns Parsed output. */ abstract parse(text: string, callbacks?: Callbacks): Promise; async parseWithPrompt( text: string, _prompt: BasePromptValue, callbacks?: Callbacks ): Promise { return this.parse(text, callbacks); } /** * Return a string describing the format of the output. * @returns Format instructions. * @param options - Options for formatting instructions. * @example * ```json * { * "foo": "bar" * } * ``` */ abstract getFormatInstructions(options?: FormatInstructionsOptions): string; /** * Return the string type key uniquely identifying this class of parser */ _type(): string { throw new Error("_type not implemented"); } } /** * Class to parse the output of an LLM call that also allows streaming inputs. */ export abstract class BaseTransformOutputParser< T = unknown > extends BaseOutputParser { async *_transform( inputGenerator: AsyncGenerator ): AsyncGenerator { for await (const chunk of inputGenerator) { if (typeof chunk === "string") { yield this.parseResult([{ text: chunk }]); } else { yield this.parseResult([{ message: chunk, text: chunk.content }]); } } } /** * Transforms an asynchronous generator of input into an asynchronous * generator of parsed output. * @param inputGenerator An asynchronous generator of input. * @param options A configuration object. * @returns An asynchronous generator of parsed output. */ async *transform( inputGenerator: AsyncGenerator, options: BaseCallbackConfig ): AsyncGenerator { yield* this._transformStreamWithConfig( inputGenerator, this._transform.bind(this), { ...options, runType: "parser", } ); } } /** * OutputParser that parses LLMResult into the top likely string. */ export class StringOutputParser extends BaseTransformOutputParser { static lc_name() { return "StrOutputParser"; } lc_namespace = ["langchain", "schema", "output_parser"]; lc_serializable = true; /** * Parses a string output from an LLM call. This method is meant to be * implemented by subclasses to define how a string output from an LLM * should be parsed. * @param text The string output from an LLM call. * @param callbacks Optional callbacks. * @returns A promise of the parsed output. */ parse(text: string): Promise { return Promise.resolve(text); } getFormatInstructions(): string { return ""; } } /** * OutputParser that parses LLMResult into the top likely string and * encodes it into bytes. */ export class BytesOutputParser extends BaseTransformOutputParser { static lc_name() { return "BytesOutputParser"; } lc_namespace = ["langchain", "schema", "output_parser"]; lc_serializable = true; protected textEncoder = new TextEncoder(); parse(text: string): Promise { return Promise.resolve(this.textEncoder.encode(text)); } getFormatInstructions(): string { return ""; } } /** * Custom error class used to handle exceptions related to output parsing. * It extends the built-in `Error` class and adds an optional `output` * property that can hold the output that caused the exception. */ export class OutputParserException extends Error { output?: string; constructor(message: string, output?: string) { super(message); this.output = output; } }