UNPKG

@langchain/core

Version:
1 lines 11.9 kB
{"version":3,"file":"template.cjs","names":["template: string","nodes: ParsedTemplateNode[]","bracket: \"}\" | \"{\" | \"{}\"","start: number","i","template: mustache.TemplateSpans","context: string[]","values: InputValues","DEFAULT_FORMATTER_MAPPING: Record<TemplateFormat, Interpolator>","DEFAULT_PARSER_MAPPING: Record<TemplateFormat, Parser>","templateFormat: TemplateFormat","inputValues: InputValues","addLangChainErrorFields","template: MessageContent","inputVariables: string[]","dummyInputs: InputValues","e: any"],"sources":["../../src/prompts/template.ts"],"sourcesContent":["import mustache from \"mustache\";\nimport { MessageContent } from \"../messages/index.js\";\nimport type { InputValues } from \"../utils/types/index.js\";\nimport { addLangChainErrorFields } from \"../errors/index.js\";\n\nfunction configureMustache() {\n // Use unescaped HTML\n // https://github.com/janl/mustache.js?tab=readme-ov-file#variables\n mustache.escape = (text) => text;\n}\n\n/**\n * Type that specifies the format of a template.\n */\nexport type TemplateFormat = \"f-string\" | \"mustache\";\n\n/**\n * Type that represents a node in a parsed format string. It can be either\n * a literal text or a variable name.\n */\nexport type ParsedTemplateNode =\n | { type: \"literal\"; text: string }\n | { type: \"variable\"; name: string };\n\n/**\n * Alias for `ParsedTemplateNode` since it is the same for\n * both f-string and mustache templates.\n */\nexport type ParsedFStringNode = ParsedTemplateNode;\n\nexport const parseFString = (template: string): ParsedTemplateNode[] => {\n // Core logic replicated from internals of pythons built in Formatter class.\n // https://github.com/python/cpython/blob/135ec7cefbaffd516b77362ad2b2ad1025af462e/Objects/stringlib/unicode_format.h#L700-L706\n const chars = template.split(\"\");\n const nodes: ParsedTemplateNode[] = [];\n\n const nextBracket = (bracket: \"}\" | \"{\" | \"{}\", start: number) => {\n for (let i = start; i < chars.length; i += 1) {\n if (bracket.includes(chars[i])) {\n return i;\n }\n }\n return -1;\n };\n\n let i = 0;\n while (i < chars.length) {\n if (chars[i] === \"{\" && i + 1 < chars.length && chars[i + 1] === \"{\") {\n nodes.push({ type: \"literal\", text: \"{\" });\n i += 2;\n } else if (\n chars[i] === \"}\" &&\n i + 1 < chars.length &&\n chars[i + 1] === \"}\"\n ) {\n nodes.push({ type: \"literal\", text: \"}\" });\n i += 2;\n } else if (chars[i] === \"{\") {\n const j = nextBracket(\"}\", i);\n if (j < 0) {\n throw new Error(\"Unclosed '{' in template.\");\n }\n\n nodes.push({\n type: \"variable\",\n name: chars.slice(i + 1, j).join(\"\"),\n });\n i = j + 1;\n } else if (chars[i] === \"}\") {\n throw new Error(\"Single '}' in template.\");\n } else {\n const next = nextBracket(\"{}\", i);\n const text = (next < 0 ? chars.slice(i) : chars.slice(i, next)).join(\"\");\n nodes.push({ type: \"literal\", text });\n i = next < 0 ? chars.length : next;\n }\n }\n return nodes;\n};\n\n/**\n * Convert the result of mustache.parse into an array of ParsedTemplateNode,\n * to make it compatible with other LangChain string parsing template formats.\n *\n * @param {mustache.TemplateSpans} template The result of parsing a mustache template with the mustache.js library.\n * @param {string[]} context Array of section variable names for nested context\n * @returns {ParsedTemplateNode[]}\n */\nconst mustacheTemplateToNodes = (\n template: mustache.TemplateSpans,\n context: string[] = []\n): ParsedTemplateNode[] => {\n const nodes: ParsedTemplateNode[] = [];\n\n for (const temp of template) {\n if (temp[0] === \"name\") {\n const name = temp[1].includes(\".\") ? temp[1].split(\".\")[0] : temp[1];\n nodes.push({ type: \"variable\", name });\n } else if ([\"#\", \"&\", \"^\", \">\"].includes(temp[0])) {\n // # represents a section, \"&\" represents an unescaped variable.\n // These should both be considered variables.\n nodes.push({ type: \"variable\", name: temp[1] });\n\n // If this is a section with nested content, recursively process it\n if (temp[0] === \"#\" && temp.length > 4 && Array.isArray(temp[4])) {\n const newContext = [...context, temp[1]];\n const nestedNodes = mustacheTemplateToNodes(temp[4], newContext);\n nodes.push(...nestedNodes);\n }\n } else {\n nodes.push({ type: \"literal\", text: temp[1] });\n }\n }\n\n return nodes;\n};\n\nexport const parseMustache = (template: string) => {\n configureMustache();\n const parsed = mustache.parse(template);\n return mustacheTemplateToNodes(parsed);\n};\n\nexport const interpolateFString = (template: string, values: InputValues) => {\n return parseFString(template).reduce((res, node) => {\n if (node.type === \"variable\") {\n if (node.name in values) {\n const stringValue =\n typeof values[node.name] === \"string\"\n ? values[node.name]\n : JSON.stringify(values[node.name]);\n return res + stringValue;\n }\n throw new Error(`(f-string) Missing value for input ${node.name}`);\n }\n\n return res + node.text;\n }, \"\");\n};\n\nexport const interpolateMustache = (template: string, values: InputValues) => {\n configureMustache();\n return mustache.render(template, values);\n};\n\n/**\n * Type that represents a function that takes a template string and a set\n * of input values, and returns a string where all variables in the\n * template have been replaced with their corresponding values.\n */\ntype Interpolator = (template: string, values: InputValues) => string;\n\n/**\n * Type that represents a function that takes a template string and\n * returns an array of `ParsedTemplateNode`.\n */\ntype Parser = (template: string) => ParsedTemplateNode[];\n\nexport const DEFAULT_FORMATTER_MAPPING: Record<TemplateFormat, Interpolator> = {\n \"f-string\": interpolateFString,\n mustache: interpolateMustache,\n};\n\nexport const DEFAULT_PARSER_MAPPING: Record<TemplateFormat, Parser> = {\n \"f-string\": parseFString,\n mustache: parseMustache,\n};\n\nexport const renderTemplate = (\n template: string,\n templateFormat: TemplateFormat,\n inputValues: InputValues\n) => {\n try {\n return DEFAULT_FORMATTER_MAPPING[templateFormat](template, inputValues);\n } catch (e) {\n const error = addLangChainErrorFields(e, \"INVALID_PROMPT_INPUT\");\n throw error;\n }\n};\n\nexport const parseTemplate = (\n template: string,\n templateFormat: TemplateFormat\n) => DEFAULT_PARSER_MAPPING[templateFormat](template);\n\nexport const checkValidTemplate = (\n template: MessageContent,\n templateFormat: TemplateFormat,\n inputVariables: string[]\n) => {\n if (!(templateFormat in DEFAULT_FORMATTER_MAPPING)) {\n const validFormats = Object.keys(DEFAULT_FORMATTER_MAPPING);\n throw new Error(`Invalid template format. Got \\`${templateFormat}\\`;\n should be one of ${validFormats}`);\n }\n try {\n const dummyInputs: InputValues = inputVariables.reduce((acc, v) => {\n acc[v] = \"foo\";\n return acc;\n }, {} as Record<string, string>);\n if (Array.isArray(template)) {\n template.forEach((message) => {\n if (\n message.type === \"text\" &&\n \"text\" in message &&\n typeof message.text === \"string\"\n ) {\n renderTemplate(message.text, templateFormat, dummyInputs);\n } else if (message.type === \"image_url\") {\n if (typeof message.image_url === \"string\") {\n renderTemplate(message.image_url, templateFormat, dummyInputs);\n } else if (\n typeof message.image_url === \"object\" &&\n message.image_url !== null &&\n \"url\" in message.image_url &&\n typeof message.image_url.url === \"string\"\n ) {\n const imageUrl = message.image_url.url;\n renderTemplate(imageUrl, templateFormat, dummyInputs);\n }\n } else {\n throw new Error(\n `Invalid message template received. ${JSON.stringify(\n message,\n null,\n 2\n )}`\n );\n }\n });\n } else {\n renderTemplate(template, templateFormat, dummyInputs);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n throw new Error(`Invalid prompt schema: ${e.message}`);\n }\n};\n"],"mappings":"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"}