@langchain/core 0.2.9 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,10 +18,25 @@ class Document {
18
18
  writable: true,
19
19
  value: void 0
20
20
  });
21
- this.pageContent = fields.pageContent
22
- ? fields.pageContent.toString()
23
- : this.pageContent;
21
+ // The ID field is optional at the moment.
22
+ // It will likely become required in a future major release after
23
+ // it has been adopted by enough vectorstore implementations.
24
+ /**
25
+ * An optional identifier for the document.
26
+ *
27
+ * Ideally this should be unique across the document collection and formatted
28
+ * as a UUID, but this will not be enforced.
29
+ */
30
+ Object.defineProperty(this, "id", {
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true,
34
+ value: void 0
35
+ });
36
+ this.pageContent =
37
+ fields.pageContent !== undefined ? fields.pageContent.toString() : "";
24
38
  this.metadata = fields.metadata ?? {};
39
+ this.id = fields.id;
25
40
  }
26
41
  }
27
42
  exports.Document = Document;
@@ -1,10 +1,24 @@
1
1
  export interface DocumentInput<Metadata extends Record<string, any> = Record<string, any>> {
2
2
  pageContent: string;
3
3
  metadata?: Metadata;
4
+ /**
5
+ * An optional identifier for the document.
6
+ *
7
+ * Ideally this should be unique across the document collection and formatted
8
+ * as a UUID, but this will not be enforced.
9
+ */
10
+ id?: string;
4
11
  }
5
12
  export interface DocumentInterface<Metadata extends Record<string, any> = Record<string, any>> {
6
13
  pageContent: string;
7
14
  metadata: Metadata;
15
+ /**
16
+ * An optional identifier for the document.
17
+ *
18
+ * Ideally this should be unique across the document collection and formatted
19
+ * as a UUID, but this will not be enforced.
20
+ */
21
+ id?: string;
8
22
  }
9
23
  /**
10
24
  * Interface for interacting with a document.
@@ -12,5 +26,12 @@ export interface DocumentInterface<Metadata extends Record<string, any> = Record
12
26
  export declare class Document<Metadata extends Record<string, any> = Record<string, any>> implements DocumentInput, DocumentInterface {
13
27
  pageContent: string;
14
28
  metadata: Metadata;
29
+ /**
30
+ * An optional identifier for the document.
31
+ *
32
+ * Ideally this should be unique across the document collection and formatted
33
+ * as a UUID, but this will not be enforced.
34
+ */
35
+ id?: string;
15
36
  constructor(fields: DocumentInput<Metadata>);
16
37
  }
@@ -15,9 +15,24 @@ export class Document {
15
15
  writable: true,
16
16
  value: void 0
17
17
  });
18
- this.pageContent = fields.pageContent
19
- ? fields.pageContent.toString()
20
- : this.pageContent;
18
+ // The ID field is optional at the moment.
19
+ // It will likely become required in a future major release after
20
+ // it has been adopted by enough vectorstore implementations.
21
+ /**
22
+ * An optional identifier for the document.
23
+ *
24
+ * Ideally this should be unique across the document collection and formatted
25
+ * as a UUID, but this will not be enforced.
26
+ */
27
+ Object.defineProperty(this, "id", {
28
+ enumerable: true,
29
+ configurable: true,
30
+ writable: true,
31
+ value: void 0
32
+ });
33
+ this.pageContent =
34
+ fields.pageContent !== undefined ? fields.pageContent.toString() : "";
21
35
  this.metadata = fields.metadata ?? {};
36
+ this.id = fields.id;
22
37
  }
23
38
  }
@@ -65,7 +65,7 @@ class BaseLLM extends base_js_1.BaseLanguageModel {
65
65
  text: "",
66
66
  });
67
67
  try {
68
- for await (const chunk of this._streamResponseChunks(input.toString(), callOptions, runManagers?.[0])) {
68
+ for await (const chunk of this._streamResponseChunks(prompt.toString(), callOptions, runManagers?.[0])) {
69
69
  if (!generation) {
70
70
  generation = chunk;
71
71
  }
@@ -62,7 +62,7 @@ export class BaseLLM extends BaseLanguageModel {
62
62
  text: "",
63
63
  });
64
64
  try {
65
- for await (const chunk of this._streamResponseChunks(input.toString(), callOptions, runManagers?.[0])) {
65
+ for await (const chunk of this._streamResponseChunks(prompt.toString(), callOptions, runManagers?.[0])) {
66
66
  if (!generation) {
67
67
  generation = chunk;
68
68
  }
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable no-promise-executor-return */
2
2
  import { test } from "@jest/globals";
3
- import { FakeLLM } from "../../utils/testing/index.js";
3
+ import { FakeLLM, FakeStreamingLLM } from "../../utils/testing/index.js";
4
+ import { HumanMessagePromptTemplate } from "../../prompts/chat.js";
4
5
  test("Test FakeLLM uses callbacks", async () => {
5
6
  const model = new FakeLLM({});
6
7
  let acc = "";
@@ -37,3 +38,15 @@ test("Test FakeLLM uses callbacks with a cache", async () => {
37
38
  expect(response).toEqual(response2);
38
39
  expect(response2).toEqual(acc);
39
40
  });
41
+ test("Test FakeStreamingLLM works when streaming through a prompt", async () => {
42
+ const prompt = HumanMessagePromptTemplate.fromTemplate("hello there {name}");
43
+ const model = new FakeStreamingLLM({});
44
+ const chain = prompt.pipe(model);
45
+ const stream = await chain.stream({ name: "test" });
46
+ const chunks = [];
47
+ for await (const chunk of stream) {
48
+ chunks.push(chunk);
49
+ }
50
+ expect(chunks.length).toBeGreaterThan(1);
51
+ expect(chunks.join("")).toEqual("Human: hello there test");
52
+ });
@@ -329,6 +329,7 @@ class _StringImageMessagePromptTemplate extends BaseMessagePromptTemplate {
329
329
  imgTemplateObject = new image_js_1.ImagePromptTemplate({
330
330
  template: imgTemplate,
331
331
  inputVariables,
332
+ templateFormat: additionalOptions?.templateFormat,
332
333
  });
333
334
  }
334
335
  else if (typeof imgTemplate === "object") {
@@ -348,6 +349,7 @@ class _StringImageMessagePromptTemplate extends BaseMessagePromptTemplate {
348
349
  imgTemplateObject = new image_js_1.ImagePromptTemplate({
349
350
  template: imgTemplate,
350
351
  inputVariables,
352
+ templateFormat: additionalOptions?.templateFormat,
351
353
  });
352
354
  }
353
355
  else {
@@ -321,6 +321,7 @@ class _StringImageMessagePromptTemplate extends BaseMessagePromptTemplate {
321
321
  imgTemplateObject = new ImagePromptTemplate({
322
322
  template: imgTemplate,
323
323
  inputVariables,
324
+ templateFormat: additionalOptions?.templateFormat,
324
325
  });
325
326
  }
326
327
  else if (typeof imgTemplate === "object") {
@@ -340,6 +341,7 @@ class _StringImageMessagePromptTemplate extends BaseMessagePromptTemplate {
340
341
  imgTemplateObject = new ImagePromptTemplate({
341
342
  template: imgTemplate,
342
343
  inputVariables,
344
+ templateFormat: additionalOptions?.templateFormat,
343
345
  });
344
346
  }
345
347
  else {
@@ -81,13 +81,7 @@ class ImagePromptTemplate extends base_js_1.BasePromptTemplate {
81
81
  const formatted = {};
82
82
  for (const [key, value] of Object.entries(this.template)) {
83
83
  if (typeof value === "string") {
84
- formatted[key] = value.replace(/{([^{}]*)}/g, (match, group) => {
85
- const replacement = values[group];
86
- return typeof replacement === "string" ||
87
- typeof replacement === "number"
88
- ? String(replacement)
89
- : match;
90
- });
84
+ formatted[key] = (0, template_js_1.renderTemplate)(value, this.templateFormat, values);
91
85
  }
92
86
  else {
93
87
  formatted[key] = value;
@@ -1,6 +1,6 @@
1
1
  import { ImagePromptValue } from "../prompt_values.js";
2
2
  import { BasePromptTemplate, } from "./base.js";
3
- import { checkValidTemplate } from "./template.js";
3
+ import { checkValidTemplate, renderTemplate, } from "./template.js";
4
4
  /**
5
5
  * An image prompt template for a multimodal model.
6
6
  */
@@ -78,13 +78,7 @@ export class ImagePromptTemplate extends BasePromptTemplate {
78
78
  const formatted = {};
79
79
  for (const [key, value] of Object.entries(this.template)) {
80
80
  if (typeof value === "string") {
81
- formatted[key] = value.replace(/{([^{}]*)}/g, (match, group) => {
82
- const replacement = values[group];
83
- return typeof replacement === "string" ||
84
- typeof replacement === "number"
85
- ? String(replacement)
86
- : match;
87
- });
81
+ formatted[key] = renderTemplate(value, this.templateFormat, values);
88
82
  }
89
83
  else {
90
84
  formatted[key] = value;
@@ -5,6 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.checkValidTemplate = exports.parseTemplate = exports.renderTemplate = exports.DEFAULT_PARSER_MAPPING = exports.DEFAULT_FORMATTER_MAPPING = exports.interpolateMustache = exports.interpolateFString = exports.parseMustache = exports.parseFString = void 0;
7
7
  const mustache_1 = __importDefault(require("mustache"));
8
+ function configureMustache() {
9
+ // Use unescaped HTML
10
+ // https://github.com/janl/mustache.js?tab=readme-ov-file#variables
11
+ mustache_1.default.escape = (text) => text;
12
+ }
8
13
  const parseFString = (template) => {
9
14
  // Core logic replicated from internals of pythons built in Formatter class.
10
15
  // https://github.com/python/cpython/blob/135ec7cefbaffd516b77362ad2b2ad1025af462e/Objects/stringlib/unicode_format.h#L700-L706
@@ -76,6 +81,7 @@ const mustacheTemplateToNodes = (template) => template.map((temp) => {
76
81
  }
77
82
  });
78
83
  const parseMustache = (template) => {
84
+ configureMustache();
79
85
  const parsed = mustache_1.default.parse(template);
80
86
  return mustacheTemplateToNodes(parsed);
81
87
  };
@@ -90,7 +96,10 @@ const interpolateFString = (template, values) => (0, exports.parseFString)(templ
90
96
  return res + node.text;
91
97
  }, "");
92
98
  exports.interpolateFString = interpolateFString;
93
- const interpolateMustache = (template, values) => mustache_1.default.render(template, values);
99
+ const interpolateMustache = (template, values) => {
100
+ configureMustache();
101
+ return mustache_1.default.render(template, values);
102
+ };
94
103
  exports.interpolateMustache = interpolateMustache;
95
104
  exports.DEFAULT_FORMATTER_MAPPING = {
96
105
  "f-string": exports.interpolateFString,
@@ -1,4 +1,9 @@
1
1
  import mustache from "mustache";
2
+ function configureMustache() {
3
+ // Use unescaped HTML
4
+ // https://github.com/janl/mustache.js?tab=readme-ov-file#variables
5
+ mustache.escape = (text) => text;
6
+ }
2
7
  export const parseFString = (template) => {
3
8
  // Core logic replicated from internals of pythons built in Formatter class.
4
9
  // https://github.com/python/cpython/blob/135ec7cefbaffd516b77362ad2b2ad1025af462e/Objects/stringlib/unicode_format.h#L700-L706
@@ -69,6 +74,7 @@ const mustacheTemplateToNodes = (template) => template.map((temp) => {
69
74
  }
70
75
  });
71
76
  export const parseMustache = (template) => {
77
+ configureMustache();
72
78
  const parsed = mustache.parse(template);
73
79
  return mustacheTemplateToNodes(parsed);
74
80
  };
@@ -81,7 +87,10 @@ export const interpolateFString = (template, values) => parseFString(template).r
81
87
  }
82
88
  return res + node.text;
83
89
  }, "");
84
- export const interpolateMustache = (template, values) => mustache.render(template, values);
90
+ export const interpolateMustache = (template, values) => {
91
+ configureMustache();
92
+ return mustache.render(template, values);
93
+ };
85
94
  export const DEFAULT_FORMATTER_MAPPING = {
86
95
  "f-string": interpolateFString,
87
96
  mustache: interpolateMustache,
@@ -78,6 +78,22 @@ test("Mustache template with image and chat prompts inside one template (fromMes
78
78
  ], {
79
79
  templateFormat: "mustache",
80
80
  });
81
+ const messages = await template.formatMessages({
82
+ name: "Bob",
83
+ image_url: "https://foo.com/bar.png",
84
+ other_var: "bar",
85
+ });
86
+ expect(messages).toEqual([
87
+ new HumanMessage({
88
+ content: [
89
+ { type: "image_url", image_url: { url: "https://foo.com/bar.png" } },
90
+ { type: "text", text: "bar" },
91
+ ],
92
+ }),
93
+ new HumanMessage({
94
+ content: "hello Bob",
95
+ }),
96
+ ]);
81
97
  expect(template.inputVariables.sort()).toEqual([
82
98
  "image_url",
83
99
  "name",
@@ -97,5 +113,17 @@ test("Mustache image template with nested URL and chat prompts HumanMessagePromp
97
113
  ], {
98
114
  templateFormat: "mustache",
99
115
  });
116
+ const messages = await template.formatMessages({
117
+ name: "Bob",
118
+ image_url: "https://foo.com/bar.png",
119
+ });
120
+ expect(messages).toEqual([
121
+ new HumanMessage({
122
+ content: [
123
+ { type: "text", text: "Bob" },
124
+ { type: "image_url", image_url: { url: "https://foo.com/bar.png" } },
125
+ ],
126
+ }),
127
+ ]);
100
128
  expect(template.inputVariables.sort()).toEqual(["image_url", "name"]);
101
129
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {