123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.checkValidTemplate = exports.parseTemplate = exports.renderTemplate = exports.DEFAULT_PARSER_MAPPING = exports.DEFAULT_FORMATTER_MAPPING = exports.interpolateMustache = exports.interpolateFString = exports.parseMustache = exports.parseFString = void 0;
- const mustache_1 = __importDefault(require("mustache"));
- const index_js_1 = require("../errors/index.cjs");
- function configureMustache() {
- // Use unescaped HTML
- // https://github.com/janl/mustache.js?tab=readme-ov-file#variables
- mustache_1.default.escape = (text) => text;
- }
- const parseFString = (template) => {
- // Core logic replicated from internals of pythons built in Formatter class.
- // https://github.com/python/cpython/blob/135ec7cefbaffd516b77362ad2b2ad1025af462e/Objects/stringlib/unicode_format.h#L700-L706
- const chars = template.split("");
- const nodes = [];
- const nextBracket = (bracket, start) => {
- for (let i = start; i < chars.length; i += 1) {
- if (bracket.includes(chars[i])) {
- return i;
- }
- }
- return -1;
- };
- let i = 0;
- while (i < chars.length) {
- if (chars[i] === "{" && i + 1 < chars.length && chars[i + 1] === "{") {
- nodes.push({ type: "literal", text: "{" });
- i += 2;
- }
- else if (chars[i] === "}" &&
- i + 1 < chars.length &&
- chars[i + 1] === "}") {
- nodes.push({ type: "literal", text: "}" });
- i += 2;
- }
- else if (chars[i] === "{") {
- const j = nextBracket("}", i);
- if (j < 0) {
- throw new Error("Unclosed '{' in template.");
- }
- nodes.push({
- type: "variable",
- name: chars.slice(i + 1, j).join(""),
- });
- i = j + 1;
- }
- else if (chars[i] === "}") {
- throw new Error("Single '}' in template.");
- }
- else {
- const next = nextBracket("{}", i);
- const text = (next < 0 ? chars.slice(i) : chars.slice(i, next)).join("");
- nodes.push({ type: "literal", text });
- i = next < 0 ? chars.length : next;
- }
- }
- return nodes;
- };
- exports.parseFString = parseFString;
- /**
- * Convert the result of mustache.parse into an array of ParsedTemplateNode,
- * to make it compatible with other LangChain string parsing template formats.
- *
- * @param {mustache.TemplateSpans} template The result of parsing a mustache template with the mustache.js library.
- * @returns {ParsedTemplateNode[]}
- */
- const mustacheTemplateToNodes = (template) => template.map((temp) => {
- if (temp[0] === "name") {
- const name = temp[1].includes(".") ? temp[1].split(".")[0] : temp[1];
- return { type: "variable", name };
- }
- else if (["#", "&", "^", ">"].includes(temp[0])) {
- // # represents a section, "&" represents an unescaped variable.
- // These should both be considered variables.
- return { type: "variable", name: temp[1] };
- }
- else {
- return { type: "literal", text: temp[1] };
- }
- });
- const parseMustache = (template) => {
- configureMustache();
- const parsed = mustache_1.default.parse(template);
- return mustacheTemplateToNodes(parsed);
- };
- exports.parseMustache = parseMustache;
- const interpolateFString = (template, values) => {
- return (0, exports.parseFString)(template).reduce((res, node) => {
- if (node.type === "variable") {
- if (node.name in values) {
- const stringValue = typeof values[node.name] === "string"
- ? values[node.name]
- : JSON.stringify(values[node.name]);
- return res + stringValue;
- }
- throw new Error(`(f-string) Missing value for input ${node.name}`);
- }
- return res + node.text;
- }, "");
- };
- exports.interpolateFString = interpolateFString;
- const interpolateMustache = (template, values) => {
- configureMustache();
- return mustache_1.default.render(template, values);
- };
- exports.interpolateMustache = interpolateMustache;
- exports.DEFAULT_FORMATTER_MAPPING = {
- "f-string": exports.interpolateFString,
- mustache: exports.interpolateMustache,
- };
- exports.DEFAULT_PARSER_MAPPING = {
- "f-string": exports.parseFString,
- mustache: exports.parseMustache,
- };
- const renderTemplate = (template, templateFormat, inputValues) => {
- try {
- return exports.DEFAULT_FORMATTER_MAPPING[templateFormat](template, inputValues);
- }
- catch (e) {
- const error = (0, index_js_1.addLangChainErrorFields)(e, "INVALID_PROMPT_INPUT");
- throw error;
- }
- };
- exports.renderTemplate = renderTemplate;
- const parseTemplate = (template, templateFormat) => exports.DEFAULT_PARSER_MAPPING[templateFormat](template);
- exports.parseTemplate = parseTemplate;
- const checkValidTemplate = (template, templateFormat, inputVariables) => {
- if (!(templateFormat in exports.DEFAULT_FORMATTER_MAPPING)) {
- const validFormats = Object.keys(exports.DEFAULT_FORMATTER_MAPPING);
- throw new Error(`Invalid template format. Got \`${templateFormat}\`;
- should be one of ${validFormats}`);
- }
- try {
- const dummyInputs = inputVariables.reduce((acc, v) => {
- acc[v] = "foo";
- return acc;
- }, {});
- if (Array.isArray(template)) {
- template.forEach((message) => {
- if (message.type === "text") {
- (0, exports.renderTemplate)(message.text, templateFormat, dummyInputs);
- }
- else if (message.type === "image_url") {
- if (typeof message.image_url === "string") {
- (0, exports.renderTemplate)(message.image_url, templateFormat, dummyInputs);
- }
- else {
- const imageUrl = message.image_url.url;
- (0, exports.renderTemplate)(imageUrl, templateFormat, dummyInputs);
- }
- }
- else {
- throw new Error(`Invalid message template received. ${JSON.stringify(message, null, 2)}`);
- }
- });
- }
- else {
- (0, exports.renderTemplate)(template, templateFormat, dummyInputs);
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- }
- catch (e) {
- throw new Error(`Invalid prompt schema: ${e.message}`);
- }
- };
- exports.checkValidTemplate = checkValidTemplate;
|