Skip to content

Commit e9a08aa

Browse files
authored
core[patch]: Fix formatting mustache image templates (#5666)
* core[patch]: Fix formatting mustache image templates * unfocus test * fix tests
1 parent e834086 commit e9a08aa

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

langchain-core/src/prompts/chat.ts

+27-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ import {
3232
ExtractedFStringParams,
3333
} from "./prompt.js";
3434
import { ImagePromptTemplate } from "./image.js";
35-
import { TemplateFormat, parseFString } from "./template.js";
35+
import {
36+
ParsedTemplateNode,
37+
TemplateFormat,
38+
parseFString,
39+
parseMustache,
40+
} from "./template.js";
3641

3742
/**
3843
* Abstract class that serves as a base for creating message prompt
@@ -495,13 +500,19 @@ class _StringImageMessagePromptTemplate<
495500
} else if (typeof item.text === "string") {
496501
text = item.text ?? "";
497502
}
498-
prompt.push(PromptTemplate.fromTemplate(text));
503+
prompt.push(PromptTemplate.fromTemplate(text, additionalOptions));
499504
} else if (typeof item === "object" && "image_url" in item) {
500505
let imgTemplate = item.image_url ?? "";
501506
let imgTemplateObject: ImagePromptTemplate<InputValues>;
502507
let inputVariables: string[] = [];
503508
if (typeof imgTemplate === "string") {
504-
const parsedTemplate = parseFString(imgTemplate);
509+
let parsedTemplate: ParsedTemplateNode[];
510+
if (additionalOptions?.templateFormat === "mustache") {
511+
parsedTemplate = parseMustache(imgTemplate);
512+
} else {
513+
parsedTemplate = parseFString(imgTemplate);
514+
}
515+
505516
const variables = parsedTemplate.flatMap((item) =>
506517
item.type === "variable" ? [item.name] : []
507518
);
@@ -524,7 +535,13 @@ class _StringImageMessagePromptTemplate<
524535
});
525536
} else if (typeof imgTemplate === "object") {
526537
if ("url" in imgTemplate) {
527-
const parsedTemplate = parseFString(imgTemplate.url);
538+
let parsedTemplate: ParsedTemplateNode[];
539+
if (additionalOptions?.templateFormat === "mustache") {
540+
parsedTemplate = parseMustache(imgTemplate.url);
541+
} else {
542+
parsedTemplate = parseFString(imgTemplate.url);
543+
}
544+
528545
inputVariables = parsedTemplate.flatMap((item) =>
529546
item.type === "variable" ? [item.name] : []
530547
);
@@ -913,7 +930,12 @@ export class ChatPromptTemplate<
913930
imageUrl = item.image_url.url;
914931
}
915932

916-
const promptTemplatePlaceholder = PromptTemplate.fromTemplate(imageUrl);
933+
const promptTemplatePlaceholder = PromptTemplate.fromTemplate(
934+
imageUrl,
935+
{
936+
templateFormat: this.templateFormat,
937+
}
938+
);
917939
const formattedUrl = await promptTemplatePlaceholder.format(
918940
inputValues
919941
);

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

+51-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { test, expect } from "@jest/globals";
22
import { AIMessage } from "../../messages/ai.js";
33
import { HumanMessage } from "../../messages/human.js";
44
import { SystemMessage } from "../../messages/system.js";
5-
import { ChatPromptTemplate } from "../chat.js";
5+
import { ChatPromptTemplate, HumanMessagePromptTemplate } from "../chat.js";
66

77
test("Test creating a chat prompt template from role string messages", async () => {
88
const template = ChatPromptTemplate.fromMessages(
@@ -67,3 +67,53 @@ test("Ignores f-string inputs input variables with repeats.", async () => {
6767
new HumanMessage("This {bar} is a {foo} test {foo}."),
6868
]);
6969
});
70+
71+
test("Mustache template with image and chat prompts inside one template (fromMessages)", async () => {
72+
const template = ChatPromptTemplate.fromMessages(
73+
[
74+
[
75+
"human",
76+
[
77+
{
78+
type: "image_url",
79+
image_url: "{{image_url}}",
80+
},
81+
{
82+
type: "text",
83+
text: "{{other_var}}",
84+
},
85+
],
86+
],
87+
["human", "hello {{name}}"],
88+
],
89+
{
90+
templateFormat: "mustache",
91+
}
92+
);
93+
94+
expect(template.inputVariables.sort()).toEqual([
95+
"image_url",
96+
"name",
97+
"other_var",
98+
]);
99+
});
100+
101+
test("Mustache image template with nested URL and chat prompts HumanMessagePromptTemplate.fromTemplate", async () => {
102+
const template = HumanMessagePromptTemplate.fromTemplate(
103+
[
104+
{
105+
text: "{{name}}",
106+
},
107+
{
108+
image_url: {
109+
url: "{{image_url}}",
110+
},
111+
},
112+
],
113+
{
114+
templateFormat: "mustache",
115+
}
116+
);
117+
118+
expect(template.inputVariables.sort()).toEqual(["image_url", "name"]);
119+
});

0 commit comments

Comments
 (0)