Skip to content

Commit d09f63a

Browse files
authored
core[patch]: Account for escaped variables in mustache templates (langchain-ai#5775)
1 parent a2ded31 commit d09f63a

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

langchain-core/src/prompts/template.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ const mustacheTemplateToNodes = (
8585
if (temp[0] === "name") {
8686
const name = temp[1].includes(".") ? temp[1].split(".")[0] : temp[1];
8787
return { type: "variable", name };
88-
} else if (temp[0] === "#") {
88+
} else if (["#", "&"].includes(temp[0])) {
89+
// # represents a section, "&" represents an unescaped variable.
90+
// These should both be considered variables.
8991
return { type: "variable", name: temp[1] };
9092
} else {
9193
return { type: "literal", text: temp[1] };

langchain-core/src/prompts/tests/prompt.mustache.test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { test, expect } from "@jest/globals";
22
import { PromptTemplate } from "../prompt.js";
3+
import { parseTemplate } from "../template.js";
34

45
test("Single input variable.", async () => {
56
const template = "This is a {{foo}} test.";
@@ -91,3 +92,24 @@ hello
9192
is a test.`);
9293
expect(promptWithRepeats.inputVariables).toEqual(["foo"]);
9394
});
95+
96+
test("Escaped variables", async () => {
97+
const template = `test: {{{text}}}`;
98+
const parsed = parseTemplate(template, "mustache");
99+
expect(parsed[0]).toStrictEqual({
100+
type: "literal",
101+
text: "test: ",
102+
});
103+
expect(parsed[1]).toStrictEqual({
104+
type: "variable",
105+
name: "text",
106+
});
107+
108+
const promptTemplate = PromptTemplate.fromTemplate(template, {
109+
templateFormat: "mustache",
110+
});
111+
const result = await promptTemplate.invoke({
112+
text: `hello i have a "quote`,
113+
});
114+
expect(result.value).toBe(`test: hello i have a "quote`);
115+
});

0 commit comments

Comments
 (0)