UNPKG

@langchain/core

Version:
1 lines 43.7 kB
{"version":3,"file":"transformers.cjs","names":["RunnableLambda","convertToChunk","isBaseMessageChunk","HumanMessage","HumanMessageChunk","AIMessage","AIMessageChunk","SystemMessage","SystemMessageChunk","ToolMessage","ToolMessageChunk","FunctionMessage","FunctionMessageChunk","ChatMessage","ChatMessageChunk","RemoveMessage"],"sources":["../../src/messages/transformers.ts"],"sourcesContent":["import { BaseLanguageModel } from \"../language_models/base.js\";\nimport { Runnable, RunnableLambda } from \"../runnables/base.js\";\nimport { AIMessage, AIMessageChunk, AIMessageChunkFields } from \"./ai.js\";\nimport {\n BaseMessage,\n BaseMessageChunk,\n BaseMessageFields,\n isBaseMessageChunk,\n} from \"./base.js\";\nimport { ChatMessage, ChatMessageChunk, ChatMessageFields } from \"./chat.js\";\nimport {\n FunctionMessage,\n FunctionMessageChunk,\n FunctionMessageFields,\n} from \"./function.js\";\nimport { HumanMessage, HumanMessageChunk } from \"./human.js\";\nimport { MessageType } from \"./message.js\";\nimport { RemoveMessage } from \"./modifier.js\";\nimport { SystemMessage, SystemMessageChunk } from \"./system.js\";\nimport { ToolMessage, ToolMessageChunk, ToolMessageFields } from \"./tool.js\";\nimport { convertToChunk } from \"./utils.js\";\n\nexport type MessageUnion =\n | typeof HumanMessage\n | typeof AIMessage\n | typeof SystemMessage\n | typeof ChatMessage\n | typeof FunctionMessage\n | typeof ToolMessage\n | typeof RemoveMessage;\nexport type MessageChunkUnion =\n | typeof HumanMessageChunk\n | typeof AIMessageChunk\n | typeof SystemMessageChunk\n | typeof FunctionMessageChunk\n | typeof ToolMessageChunk\n | typeof ChatMessageChunk\n | typeof RemoveMessage; // RemoveMessage does not have a chunk class.\nexport type MessageTypeOrClass = MessageType | MessageUnion | MessageChunkUnion;\n\nconst _isMessageType = (msg: BaseMessage, types: MessageTypeOrClass[]) => {\n const typesAsStrings = [\n ...new Set<string>(\n types?.map((t) => {\n if (typeof t === \"string\") {\n return t;\n }\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const instantiatedMsgClass = new (t as any)({});\n if (\n !(\"getType\" in instantiatedMsgClass) ||\n typeof instantiatedMsgClass.getType !== \"function\"\n ) {\n throw new Error(\"Invalid type provided.\");\n }\n return instantiatedMsgClass.getType();\n })\n ),\n ];\n const msgType = msg.getType();\n return typesAsStrings.some((t) => t === msgType);\n};\n\nexport interface FilterMessagesFields {\n /**\n * @param {string[] | undefined} includeNames Message names to include.\n */\n includeNames?: string[];\n /**\n * @param {string[] | undefined} excludeNames Messages names to exclude.\n */\n excludeNames?: string[];\n /**\n * @param {(MessageType | BaseMessage)[] | undefined} includeTypes Message types to include. Can be specified as string names (e.g.\n * \"system\", \"human\", \"ai\", ...) or as BaseMessage classes (e.g.\n * SystemMessage, HumanMessage, AIMessage, ...).\n */\n includeTypes?: MessageTypeOrClass[];\n /**\n * @param {(MessageType | BaseMessage)[] | undefined} excludeTypes Message types to exclude. Can be specified as string names (e.g.\n * \"system\", \"human\", \"ai\", ...) or as BaseMessage classes (e.g.\n * SystemMessage, HumanMessage, AIMessage, ...).\n */\n excludeTypes?: MessageTypeOrClass[];\n /**\n * @param {string[] | undefined} includeIds Message IDs to include.\n */\n includeIds?: string[];\n /**\n * @param {string[] | undefined} excludeIds Message IDs to exclude.\n */\n excludeIds?: string[];\n}\n\n/**\n * Filter messages based on name, type or id.\n *\n * @param {BaseMessage[] | FilterMessagesFields} messagesOrOptions - Either an array of BaseMessage objects to filter or the filtering options. If an array is provided, the `options` parameter should also be supplied. If filtering options are provided, a RunnableLambda is returned.\n * @param {FilterMessagesFields} [options] - Optional filtering options. Should only be provided if `messagesOrOptions` is an array of BaseMessage objects.\n * @returns A list of Messages that meets at least one of the include conditions and none\n * of the exclude conditions, or a RunnableLambda which does the same. If no include conditions are specified then\n * anything that is not explicitly excluded will be included.\n * @throws {Error} If two incompatible arguments are provided.\n *\n * @example\n * ```typescript\n * import { filterMessages, AIMessage, HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n *\n * const messages = [\n * new SystemMessage(\"you're a good assistant.\"),\n * new HumanMessage({ content: \"what's your name\", id: \"foo\", name: \"example_user\" }),\n * new AIMessage({ content: \"steve-o\", id: \"bar\", name: \"example_assistant\" }),\n * new HumanMessage({ content: \"what's your favorite color\", id: \"baz\" }),\n * new AIMessage({ content: \"silicon blue\" , id: \"blah\" }),\n * ];\n *\n * filterMessages(messages, {\n * includeNames: [\"example_user\", \"example_assistant\"],\n * includeTypes: [\"system\"],\n * excludeIds: [\"bar\"],\n * });\n * ```\n *\n * The above example would return:\n * ```typescript\n * [\n * new SystemMessage(\"you're a good assistant.\"),\n * new HumanMessage({ content: \"what's your name\", id: \"foo\", name: \"example_user\" }),\n * ]\n * ```\n */\nexport function filterMessages(\n options?: FilterMessagesFields\n): Runnable<BaseMessage[], BaseMessage[]>;\nexport function filterMessages(\n messages: BaseMessage[],\n options?: FilterMessagesFields\n): BaseMessage[];\nexport function filterMessages(\n messagesOrOptions?: BaseMessage[] | FilterMessagesFields,\n options?: FilterMessagesFields\n): BaseMessage[] | Runnable<BaseMessage[], BaseMessage[]> {\n if (Array.isArray(messagesOrOptions)) {\n return _filterMessages(messagesOrOptions, options);\n }\n return RunnableLambda.from((input: BaseMessage[]): BaseMessage[] => {\n return _filterMessages(input, messagesOrOptions);\n });\n}\n\nfunction _filterMessages(\n messages: BaseMessage[],\n options: FilterMessagesFields = {}\n): BaseMessage[] {\n const {\n includeNames,\n excludeNames,\n includeTypes,\n excludeTypes,\n includeIds,\n excludeIds,\n } = options;\n\n const filtered: BaseMessage[] = [];\n\n for (const msg of messages) {\n if (excludeNames && msg.name && excludeNames.includes(msg.name)) {\n continue;\n } else if (excludeTypes && _isMessageType(msg, excludeTypes)) {\n continue;\n } else if (excludeIds && msg.id && excludeIds.includes(msg.id)) {\n continue;\n }\n\n // default to inclusion when no inclusion criteria given.\n if (!(includeTypes || includeIds || includeNames)) {\n filtered.push(msg);\n } else if (\n includeNames &&\n msg.name &&\n includeNames.some((iName) => iName === msg.name)\n ) {\n filtered.push(msg);\n } else if (includeTypes && _isMessageType(msg, includeTypes)) {\n filtered.push(msg);\n } else if (includeIds && msg.id && includeIds.some((id) => id === msg.id)) {\n filtered.push(msg);\n }\n }\n\n return filtered;\n}\n\n/**\n * Merge consecutive Messages of the same type.\n *\n * **NOTE**: ToolMessages are not merged, as each has a distinct tool call id that\n * can't be merged.\n *\n * @param {BaseMessage[] | undefined} messages Sequence of Message-like objects to merge. Optional. If not provided, a RunnableLambda is returned.\n * @returns List of BaseMessages with consecutive runs of message types merged into single\n * messages, or a RunnableLambda which returns a list of BaseMessages If two messages being merged both have string contents, the merged\n * content is a concatenation of the two strings with a new-line separator. If at\n * least one of the messages has a list of content blocks, the merged content is a\n * list of content blocks.\n *\n * @example\n * ```typescript\n * import { mergeMessageRuns, AIMessage, HumanMessage, SystemMessage, ToolCall } from \"@langchain/core/messages\";\n *\n * const messages = [\n * new SystemMessage(\"you're a good assistant.\"),\n * new HumanMessage({ content: \"what's your favorite color\", id: \"foo\" }),\n * new HumanMessage({ content: \"wait your favorite food\", id: \"bar\" }),\n * new AIMessage({\n * content: \"my favorite colo\",\n * tool_calls: [{ name: \"blah_tool\", args: { x: 2 }, id: \"123\" }],\n * id: \"baz\",\n * }),\n * new AIMessage({\n * content: [{ type: \"text\", text: \"my favorite dish is lasagna\" }],\n * tool_calls: [{ name: \"blah_tool\", args: { x: -10 }, id: \"456\" }],\n * id: \"blur\",\n * }),\n * ];\n *\n * mergeMessageRuns(messages);\n * ```\n *\n * The above example would return:\n * ```typescript\n * [\n * new SystemMessage(\"you're a good assistant.\"),\n * new HumanMessage({\n * content: \"what's your favorite colorwait your favorite food\",\n * id: \"foo\",\n * }),\n * new AIMessage({\n * content: [\n * { type: \"text\", text: \"my favorite colo\" },\n * { type: \"text\", text: \"my favorite dish is lasagna\" },\n * ],\n * tool_calls: [\n * { name: \"blah_tool\", args: { x: 2 }, id: \"123\" },\n * { name: \"blah_tool\", args: { x: -10 }, id: \"456\" },\n * ],\n * id: \"baz\",\n * }),\n * ]\n * ```\n */\nexport function mergeMessageRuns(): Runnable<BaseMessage[], BaseMessage[]>;\nexport function mergeMessageRuns(messages: BaseMessage[]): BaseMessage[];\nexport function mergeMessageRuns(\n messages?: BaseMessage[]\n): BaseMessage[] | Runnable<BaseMessage[], BaseMessage[]> {\n if (Array.isArray(messages)) {\n return _mergeMessageRuns(messages);\n }\n return RunnableLambda.from(_mergeMessageRuns);\n}\n\nfunction _mergeMessageRuns(messages: BaseMessage[]): BaseMessage[] {\n if (!messages.length) {\n return [];\n }\n const merged: BaseMessage[] = [];\n for (const msg of messages) {\n const curr = msg;\n const last = merged.pop();\n if (!last) {\n merged.push(curr);\n } else if (\n curr.getType() === \"tool\" ||\n !(curr.getType() === last.getType())\n ) {\n merged.push(last, curr);\n } else {\n const lastChunk = convertToChunk(last) as BaseMessageChunk;\n const currChunk = convertToChunk(curr) as BaseMessageChunk;\n const mergedChunks = lastChunk.concat(currChunk);\n if (\n typeof lastChunk.content === \"string\" &&\n typeof currChunk.content === \"string\"\n ) {\n mergedChunks.content = `${lastChunk.content}\\n${currChunk.content}`;\n }\n merged.push(_chunkToMsg(mergedChunks));\n }\n }\n return merged;\n}\n\n// Since we can not import from `@langchain/textsplitters` we need\n// to reconstruct the interface here. Only `splitText` is used by\n// `trimMessages`, so we avoid coupling to the full `BaseDocumentTransformer`\n// surface and just require the method we call.\ninterface _TextSplitterInterface {\n splitText(text: string): Promise<string[]>;\n}\n\nexport interface TrimMessagesFields {\n /**\n * @param {number} maxTokens Max token count of trimmed messages.\n */\n maxTokens: number;\n /**\n * @param {((messages: BaseMessage[]) => number) | ((messages: BaseMessage[]) => Promise<number>) | BaseLanguageModel} tokenCounter\n * Function or LLM for counting tokens in an array of `BaseMessage`s.\n * If a `BaseLanguageModel` is passed in then `BaseLanguageModel.getNumTokens()` will be used.\n */\n tokenCounter:\n | ((messages: BaseMessage[]) => number)\n | ((messages: BaseMessage[]) => Promise<number>)\n | BaseLanguageModel;\n /**\n * @param {\"first\" | \"last\"} [strategy=\"last\"] Strategy for trimming.\n * - \"first\": Keep the first <= n_count tokens of the messages.\n * - \"last\": Keep the last <= n_count tokens of the messages.\n * @default \"last\"\n */\n strategy?: \"first\" | \"last\";\n /**\n * @param {boolean} [allowPartial=false] Whether to split a message if only part of the message can be included.\n * If `strategy: \"last\"` then the last partial contents of a message are included.\n * If `strategy: \"first\"` then the first partial contents of a message are included.\n * @default false\n */\n allowPartial?: boolean;\n /**\n * @param {MessageTypeOrClass | MessageTypeOrClass[]} [endOn] The message type to end on.\n * If specified then every message after the last occurrence of this type is ignored.\n * If `strategy === \"last\"` then this is done before we attempt to get the last `maxTokens`.\n * If `strategy === \"first\"` then this is done after we get the first `maxTokens`.\n * Can be specified as string names (e.g. \"system\", \"human\", \"ai\", ...) or as `BaseMessage` classes\n * (e.g. `SystemMessage`, `HumanMessage`, `AIMessage`, ...). Can be a single type or an array of types.\n */\n endOn?: MessageTypeOrClass | MessageTypeOrClass[];\n /**\n * @param {MessageTypeOrClass | MessageTypeOrClass[]} [startOn] The message type to start on.\n * Should only be specified if `strategy: \"last\"`. If specified then every message before the first occurrence\n * of this type is ignored. This is done after we trim the initial messages to the last `maxTokens`.\n * Does not apply to a `SystemMessage` at index 0 if `includeSystem: true`.\n * Can be specified as string names (e.g. \"system\", \"human\", \"ai\", ...) or as `BaseMessage` classes\n * (e.g. `SystemMessage`, `HumanMessage`, `AIMessage`, ...). Can be a single type or an array of types.\n */\n startOn?: MessageTypeOrClass | MessageTypeOrClass[];\n /**\n * @param {boolean} [includeSystem=false] Whether to keep the `SystemMessage` if there is one at index 0.\n * Should only be specified if `strategy: \"last\"`.\n * @default false\n */\n includeSystem?: boolean;\n /**\n * @param {((text: string) => string[]) | BaseDocumentTransformer} [textSplitter] Function or `BaseDocumentTransformer` for\n * splitting the string contents of a message. Only used if `allowPartial: true`.\n * If `strategy: \"last\"` then the last split tokens from a partial message will be included.\n * If `strategy: \"first\"` then the first split tokens from a partial message will be included.\n * Token splitter assumes that separators are kept, so that split contents can be directly concatenated\n * to recreate the original text. Defaults to splitting on newlines.\n */\n textSplitter?:\n | ((text: string) => string[])\n | ((text: string) => Promise<string[]>)\n | _TextSplitterInterface;\n}\n\n/**\n * Trim messages to be below a token count.\n *\n * @param {BaseMessage[]} messages Array of `BaseMessage` instances to trim.\n * @param {TrimMessagesFields} options Trimming options.\n * @returns An array of trimmed `BaseMessage`s or a `Runnable` that takes a sequence of `BaseMessage`-like objects and returns\n * an array of trimmed `BaseMessage`s.\n * @throws {Error} If two incompatible arguments are specified or an unrecognized `strategy` is specified.\n *\n * @example\n * ```typescript\n * import { trimMessages, AIMessage, BaseMessage, HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n *\n * const messages = [\n * new SystemMessage(\"This is a 4 token text. The full message is 10 tokens.\"),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"first\",\n * }),\n * new AIMessage({\n * content: [\n * { type: \"text\", text: \"This is the FIRST 4 token block.\" },\n * { type: \"text\", text: \"This is the SECOND 4 token block.\" },\n * ],\n * id: \"second\",\n * }),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"third\",\n * }),\n * new AIMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"fourth\",\n * }),\n * ];\n *\n * function dummyTokenCounter(messages: BaseMessage[]): number {\n * // treat each message like it adds 3 default tokens at the beginning\n * // of the message and at the end of the message. 3 + 4 + 3 = 10 tokens\n * // per message.\n *\n * const defaultContentLen = 4;\n * const defaultMsgPrefixLen = 3;\n * const defaultMsgSuffixLen = 3;\n *\n * let count = 0;\n * for (const msg of messages) {\n * if (typeof msg.content === \"string\") {\n * count += defaultMsgPrefixLen + defaultContentLen + defaultMsgSuffixLen;\n * }\n * if (Array.isArray(msg.content)) {\n * count +=\n * defaultMsgPrefixLen +\n * msg.content.length * defaultContentLen +\n * defaultMsgSuffixLen;\n * }\n * }\n * return count;\n * }\n * ```\n *\n * First 30 tokens, not allowing partial messages:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 30,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"first\",\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"first\",\n * }),\n * ]\n * ```\n *\n * First 30 tokens, allowing partial messages:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 30,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"first\",\n * allowPartial: true,\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"first\",\n * }),\n * new AIMessage({\n * content: [{ type: \"text\", text: \"This is the FIRST 4 token block.\" }],\n * id: \"second\",\n * }),\n * ]\n * ```\n *\n * First 30 tokens, allowing partial messages, have to end on HumanMessage:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 30,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"first\",\n * allowPartial: true,\n * endOn: \"human\",\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"first\",\n * }),\n * ]\n * ```\n *\n * Last 30 tokens, including system message, not allowing partial messages:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 30,\n * includeSystem: true,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"last\",\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"third\",\n * }),\n * new AIMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"fourth\",\n * }),\n * ]\n * ```\n *\n * Last 40 tokens, including system message, allowing partial messages:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 40,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"last\",\n * allowPartial: true,\n * includeSystem: true,\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new AIMessage({\n * content: [{ type: \"text\", text: \"This is the FIRST 4 token block.\" }],\n * id: \"second\",\n * }),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"third\",\n * }),\n * new AIMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"fourth\",\n * }),\n * ]\n * ```\n *\n * Last 30 tokens, including system message, allowing partial messages, end on HumanMessage:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 30,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"last\",\n * endOn: \"human\",\n * includeSystem: true,\n * allowPartial: true,\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new AIMessage({\n * content: [{ type: \"text\", text: \"This is the FIRST 4 token block.\" }],\n * id: \"second\",\n * }),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"third\",\n * }),\n * ]\n * ```\n *\n * Last 40 tokens, including system message, allowing partial messages, start on HumanMessage:\n * ```typescript\n * await trimMessages(messages, {\n * maxTokens: 40,\n * tokenCounter: dummyTokenCounter,\n * strategy: \"last\",\n * includeSystem: true,\n * allowPartial: true,\n * startOn: \"human\",\n * });\n * ```\n *\n * Output:\n * ```typescript\n * [\n * new SystemMessage(\n * \"This is a 4 token text. The full message is 10 tokens.\"\n * ),\n * new HumanMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"third\",\n * }),\n * new AIMessage({\n * content: \"This is a 4 token text. The full message is 10 tokens.\",\n * id: \"fourth\",\n * }),\n * ]\n * ```\n */\nexport function trimMessages(\n options: TrimMessagesFields\n): Runnable<BaseMessage[], BaseMessage[]>;\nexport function trimMessages(\n messages: BaseMessage[],\n options: TrimMessagesFields\n): Promise<BaseMessage[]>;\nexport function trimMessages(\n messagesOrOptions: BaseMessage[] | TrimMessagesFields,\n options?: TrimMessagesFields\n): Promise<BaseMessage[]> | Runnable<BaseMessage[], BaseMessage[]> {\n if (Array.isArray(messagesOrOptions)) {\n const messages = messagesOrOptions;\n if (!options) {\n throw new Error(\"Options parameter is required when providing messages.\");\n }\n return _trimMessagesHelper(messages, options);\n } else {\n const trimmerOptions = messagesOrOptions;\n return RunnableLambda.from((input: BaseMessage[]) =>\n _trimMessagesHelper(input, trimmerOptions)\n ).withConfig({\n runName: \"trim_messages\",\n });\n }\n}\n\nasync function _trimMessagesHelper(\n messages: BaseMessage[],\n options: TrimMessagesFields\n): Promise<Array<BaseMessage>> {\n const {\n maxTokens,\n tokenCounter,\n strategy = \"last\",\n allowPartial = false,\n endOn,\n startOn,\n includeSystem = false,\n textSplitter,\n } = options;\n if (startOn && strategy === \"first\") {\n throw new Error(\n \"`startOn` should only be specified if `strategy` is 'last'.\"\n );\n }\n if (includeSystem && strategy === \"first\") {\n throw new Error(\n \"`includeSystem` should only be specified if `strategy` is 'last'.\"\n );\n }\n\n let listTokenCounter: (msgs: BaseMessage[]) => Promise<number>;\n if (\"getNumTokens\" in tokenCounter) {\n listTokenCounter = async (msgs: BaseMessage[]): Promise<number> => {\n const tokenCounts = await Promise.all(\n msgs.map((msg) => tokenCounter.getNumTokens(msg.content))\n );\n return tokenCounts.reduce((sum, count) => sum + count, 0);\n };\n } else {\n listTokenCounter = async (msgs: BaseMessage[]): Promise<number> =>\n tokenCounter(msgs);\n }\n\n let textSplitterFunc: (text: string) => Promise<string[]> =\n defaultTextSplitter;\n if (textSplitter) {\n if (\"splitText\" in textSplitter) {\n textSplitterFunc = textSplitter.splitText.bind(textSplitter);\n } else {\n textSplitterFunc = async (text: string): Promise<string[]> =>\n textSplitter(text);\n }\n }\n\n if (strategy === \"first\") {\n return _firstMaxTokens(messages, {\n maxTokens,\n tokenCounter: listTokenCounter,\n textSplitter: textSplitterFunc,\n partialStrategy: allowPartial ? \"first\" : undefined,\n endOn,\n });\n } else if (strategy === \"last\") {\n return _lastMaxTokens(messages, {\n maxTokens,\n tokenCounter: listTokenCounter,\n textSplitter: textSplitterFunc,\n allowPartial,\n includeSystem,\n startOn,\n endOn,\n });\n } else {\n throw new Error(\n `Unrecognized strategy: '${strategy}'. Must be one of 'first' or 'last'.`\n );\n }\n}\n\nasync function _firstMaxTokens(\n messages: BaseMessage[],\n options: {\n maxTokens: number;\n tokenCounter: (messages: BaseMessage[]) => Promise<number>;\n textSplitter: (text: string) => Promise<string[]>;\n partialStrategy?: \"first\" | \"last\";\n endOn?: MessageTypeOrClass | MessageTypeOrClass[];\n }\n): Promise<BaseMessage[]> {\n const { maxTokens, tokenCounter, textSplitter, partialStrategy, endOn } =\n options;\n let messagesCopy = [...messages];\n let idx = 0;\n for (let i = 0; i < messagesCopy.length; i += 1) {\n const remainingMessages = i > 0 ? messagesCopy.slice(0, -i) : messagesCopy;\n if ((await tokenCounter(remainingMessages)) <= maxTokens) {\n idx = messagesCopy.length - i;\n break;\n }\n }\n if (idx < messagesCopy.length && partialStrategy) {\n let includedPartial = false;\n if (Array.isArray(messagesCopy[idx].content)) {\n const excluded = messagesCopy[idx];\n if (typeof excluded.content === \"string\") {\n throw new Error(\"Expected content to be an array.\");\n }\n\n const numBlock = excluded.content.length;\n const reversedContent =\n partialStrategy === \"last\"\n ? [...excluded.content].reverse()\n : excluded.content;\n for (let i = 1; i <= numBlock; i += 1) {\n const partialContent =\n partialStrategy === \"first\"\n ? reversedContent.slice(0, i)\n : reversedContent.slice(-i);\n const fields = Object.fromEntries(\n Object.entries(excluded).filter(\n ([k]) => k !== \"type\" && !k.startsWith(\"lc_\")\n )\n ) as BaseMessageFields;\n const updatedMessage = _switchTypeToMessage(excluded.getType(), {\n ...fields,\n content: partialContent,\n });\n const slicedMessages = [...messagesCopy.slice(0, idx), updatedMessage];\n if ((await tokenCounter(slicedMessages)) <= maxTokens) {\n messagesCopy = slicedMessages;\n idx += 1;\n includedPartial = true;\n } else {\n break;\n }\n }\n if (includedPartial && partialStrategy === \"last\") {\n excluded.content = [...reversedContent].reverse();\n }\n }\n if (!includedPartial) {\n const excluded = messagesCopy[idx];\n let text: string | undefined;\n if (\n Array.isArray(excluded.content) &&\n excluded.content.some(\n (block) => typeof block === \"string\" || block.type === \"text\"\n )\n ) {\n const textBlock = excluded.content.find(\n (block) => block.type === \"text\" && block.text\n ) as { type: \"text\"; text: string } | undefined;\n text = textBlock?.text;\n } else if (typeof excluded.content === \"string\") {\n text = excluded.content;\n }\n if (text) {\n const splitTexts = await textSplitter(text);\n const numSplits = splitTexts.length;\n if (partialStrategy === \"last\") {\n splitTexts.reverse();\n }\n for (let _ = 0; _ < numSplits - 1; _ += 1) {\n splitTexts.pop();\n excluded.content = splitTexts.join(\"\");\n if (\n (await tokenCounter([...messagesCopy.slice(0, idx), excluded])) <=\n maxTokens\n ) {\n if (partialStrategy === \"last\") {\n excluded.content = [...splitTexts].reverse().join(\"\");\n }\n messagesCopy = [...messagesCopy.slice(0, idx), excluded];\n idx += 1;\n break;\n }\n }\n }\n }\n }\n\n if (endOn) {\n const endOnArr = Array.isArray(endOn) ? endOn : [endOn];\n while (idx > 0 && !_isMessageType(messagesCopy[idx - 1], endOnArr)) {\n idx -= 1;\n }\n }\n\n return messagesCopy.slice(0, idx);\n}\n\nasync function _lastMaxTokens(\n messages: BaseMessage[],\n options: {\n maxTokens: number;\n tokenCounter: (messages: BaseMessage[]) => Promise<number>;\n textSplitter: (text: string) => Promise<string[]>;\n /**\n * @default {false}\n */\n allowPartial?: boolean;\n /**\n * @default {false}\n */\n includeSystem?: boolean;\n startOn?: MessageTypeOrClass | MessageTypeOrClass[];\n endOn?: MessageTypeOrClass | MessageTypeOrClass[];\n }\n): Promise<BaseMessage[]> {\n const {\n allowPartial = false,\n includeSystem = false,\n endOn,\n startOn,\n ...rest\n } = options;\n\n // Create a copy of messages to avoid mutation\n let messagesCopy = messages.map((message) => {\n const fields = Object.fromEntries(\n Object.entries(message).filter(\n ([k]) => k !== \"type\" && !k.startsWith(\"lc_\")\n )\n ) as BaseMessageFields;\n return _switchTypeToMessage(\n message.getType(),\n fields,\n isBaseMessageChunk(message)\n );\n });\n\n if (endOn) {\n const endOnArr = Array.isArray(endOn) ? endOn : [endOn];\n while (\n messagesCopy.length > 0 &&\n !_isMessageType(messagesCopy[messagesCopy.length - 1], endOnArr)\n ) {\n messagesCopy = messagesCopy.slice(0, -1);\n }\n }\n\n const swappedSystem =\n includeSystem && messagesCopy[0]?.getType() === \"system\";\n let reversed_ = swappedSystem\n ? messagesCopy.slice(0, 1).concat(messagesCopy.slice(1).reverse())\n : messagesCopy.reverse();\n\n reversed_ = await _firstMaxTokens(reversed_, {\n ...rest,\n partialStrategy: allowPartial ? \"last\" : undefined,\n endOn: startOn,\n });\n\n if (swappedSystem) {\n return [reversed_[0], ...reversed_.slice(1).reverse()];\n } else {\n return reversed_.reverse();\n }\n}\n\nconst _MSG_CHUNK_MAP: Record<\n MessageType,\n {\n message: MessageUnion;\n messageChunk: MessageChunkUnion;\n }\n> = {\n human: {\n message: HumanMessage,\n messageChunk: HumanMessageChunk,\n },\n ai: {\n message: AIMessage,\n messageChunk: AIMessageChunk,\n },\n system: {\n message: SystemMessage,\n messageChunk: SystemMessageChunk,\n },\n developer: {\n message: SystemMessage,\n messageChunk: SystemMessageChunk,\n },\n tool: {\n message: ToolMessage,\n messageChunk: ToolMessageChunk,\n },\n function: {\n message: FunctionMessage,\n messageChunk: FunctionMessageChunk,\n },\n generic: {\n message: ChatMessage,\n messageChunk: ChatMessageChunk,\n },\n remove: {\n message: RemoveMessage,\n messageChunk: RemoveMessage, // RemoveMessage does not have a chunk class.\n },\n};\n\nfunction _switchTypeToMessage(\n messageType: MessageType,\n fields: BaseMessageFields\n): BaseMessage;\nfunction _switchTypeToMessage(\n messageType: MessageType,\n fields: BaseMessageFields,\n returnChunk: true\n): BaseMessageChunk;\nfunction _switchTypeToMessage(\n messageType: MessageType,\n fields: BaseMessageFields,\n returnChunk?: boolean\n): BaseMessageChunk | BaseMessage;\nfunction _switchTypeToMessage(\n messageType: MessageType,\n fields: BaseMessageFields,\n returnChunk?: boolean\n): BaseMessageChunk | BaseMessage {\n let chunk: BaseMessageChunk | undefined;\n let msg: BaseMessage | undefined;\n\n switch (messageType) {\n case \"human\":\n if (returnChunk) {\n chunk = new HumanMessageChunk(fields);\n } else {\n msg = new HumanMessage(fields);\n }\n break;\n case \"ai\":\n if (returnChunk) {\n let aiChunkFields: AIMessageChunkFields = {\n ...fields,\n };\n if (\"tool_calls\" in aiChunkFields) {\n aiChunkFields = {\n ...aiChunkFields,\n tool_call_chunks: aiChunkFields.tool_calls?.map((tc) => ({\n ...tc,\n type: \"tool_call_chunk\",\n index: undefined,\n args: JSON.stringify(tc.args),\n })),\n };\n }\n chunk = new AIMessageChunk(aiChunkFields);\n } else {\n msg = new AIMessage(fields);\n }\n break;\n case \"system\":\n if (returnChunk) {\n chunk = new SystemMessageChunk(fields);\n } else {\n msg = new SystemMessage(fields);\n }\n break;\n case \"developer\":\n if (returnChunk) {\n chunk = new SystemMessageChunk({\n ...fields,\n additional_kwargs: {\n ...fields.additional_kwargs,\n __openai_role__: \"developer\",\n },\n });\n } else {\n msg = new SystemMessage({\n ...fields,\n additional_kwargs: {\n ...fields.additional_kwargs,\n __openai_role__: \"developer\",\n },\n });\n }\n break;\n case \"tool\":\n if (\"tool_call_id\" in fields) {\n if (returnChunk) {\n chunk = new ToolMessageChunk(fields as ToolMessageFields);\n } else {\n msg = new ToolMessage(fields as ToolMessageFields);\n }\n } else {\n throw new Error(\n \"Can not convert ToolMessage to ToolMessageChunk if 'tool_call_id' field is not defined.\"\n );\n }\n break;\n case \"function\":\n if (returnChunk) {\n chunk = new FunctionMessageChunk(fields as FunctionMessageFields);\n } else {\n if (!fields.name) {\n throw new Error(\"FunctionMessage must have a 'name' field\");\n }\n msg = new FunctionMessage(fields as FunctionMessageFields);\n }\n break;\n case \"generic\":\n if (\"role\" in fields) {\n if (returnChunk) {\n chunk = new ChatMessageChunk(fields as ChatMessageFields);\n } else {\n msg = new ChatMessage(fields as ChatMessageFields);\n }\n } else {\n throw new Error(\n \"Can not convert ChatMessage to ChatMessageChunk if 'role' field is not defined.\"\n );\n }\n break;\n default:\n throw new Error(`Unrecognized message type ${messageType}`);\n }\n\n if (returnChunk && chunk) {\n return chunk;\n }\n if (msg) {\n return msg;\n }\n throw new Error(`Unrecognized message type ${messageType}`);\n}\n\nfunction _chunkToMsg(chunk: BaseMessageChunk): BaseMessage {\n const chunkType = chunk.getType();\n let msg: BaseMessage | undefined;\n const fields = Object.fromEntries(\n Object.entries(chunk).filter(\n ([k]) => ![\"type\", \"tool_call_chunks\"].includes(k) && !k.startsWith(\"lc_\")\n )\n ) as BaseMessageFields;\n\n if (chunkType in _MSG_CHUNK_MAP) {\n msg = _switchTypeToMessage(chunkType, fields);\n }\n\n if (!msg) {\n throw new Error(\n `Unrecognized message chunk class ${chunkType}. Supported classes are ${Object.keys(\n _MSG_CHUNK_MAP\n )}`\n );\n }\n\n return msg;\n}\n\n/**\n * The default text splitter function that splits text by newlines.\n *\n * @param {string} text\n * @returns A promise that resolves to an array of strings split by newlines.\n */\nexport function defaultTextSplitter(text: string): Promise<string[]> {\n const splits = text.split(\"\\n\");\n return Promise.resolve([\n ...splits.slice(0, -1).map((s) => `${s}\\n`),\n splits[splits.length - 1],\n ]);\n}\n"],"mappings":"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"}