@langchain/core 0.2.11 → 0.2.12

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.
package/README.md CHANGED
@@ -85,7 +85,7 @@ Rather than having to write multiple implementations for all of those, LCEL allo
85
85
 
86
86
  For more check out the [LCEL docs](https://js.langchain.com/v0.2/docs/concepts#langchain-expression-language).
87
87
 
88
- ![LangChain Stack](../docs/core_docs/static/img/langchain_stack_feb_2024.webp)
88
+ ![LangChain Stack](../docs/core_docs/static/svg/langchain_stack_062024.svg)
89
89
 
90
90
  ## 📕 Releases & Versioning
91
91
 
@@ -3,6 +3,23 @@ import { test } from "@jest/globals";
3
3
  import { z } from "zod";
4
4
  import { zodToJsonSchema } from "zod-to-json-schema";
5
5
  import { FakeChatModel, FakeListChatModel } from "../../utils/testing/index.js";
6
+ test("Test ChatModel accepts array shorthand for messages", async () => {
7
+ const model = new FakeChatModel({});
8
+ const response = await model.invoke([["human", "Hello there!"]]);
9
+ expect(response.content).toEqual("Hello there!");
10
+ });
11
+ test("Test ChatModel accepts object shorthand for messages", async () => {
12
+ const model = new FakeChatModel({});
13
+ const response = await model.invoke([
14
+ {
15
+ type: "human",
16
+ content: "Hello there!",
17
+ additional_kwargs: {},
18
+ example: true,
19
+ },
20
+ ]);
21
+ expect(response.content).toEqual("Hello there!");
22
+ });
6
23
  test("Test ChatModel uses callbacks", async () => {
7
24
  const model = new FakeChatModel({});
8
25
  let acc = "";
@@ -140,7 +140,9 @@ export declare function _mergeLists(left?: any[], right?: any[]): any[] | undefi
140
140
  export declare abstract class BaseMessageChunk extends BaseMessage {
141
141
  abstract concat(chunk: BaseMessageChunk): BaseMessageChunk;
142
142
  }
143
- export type BaseMessageLike = BaseMessage | [
143
+ export type BaseMessageLike = BaseMessage | ({
144
+ type: MessageType | "user" | "assistant" | "placeholder";
145
+ } & BaseMessageFields & Record<string, unknown>) | [
144
146
  StringWithAutocomplete<MessageType | "user" | "assistant" | "placeholder">,
145
147
  MessageContent
146
148
  ] | string;
@@ -8,6 +8,21 @@ const function_js_1 = require("./function.cjs");
8
8
  const human_js_1 = require("./human.cjs");
9
9
  const system_js_1 = require("./system.cjs");
10
10
  const tool_js_1 = require("./tool.cjs");
11
+ function _constructMessageFromParams(params) {
12
+ const { type, ...rest } = params;
13
+ if (type === "human" || type === "user") {
14
+ return new human_js_1.HumanMessage(rest);
15
+ }
16
+ else if (type === "ai" || type === "assistant") {
17
+ return new ai_js_1.AIMessage(rest);
18
+ }
19
+ else if (type === "system") {
20
+ return new system_js_1.SystemMessage(rest);
21
+ }
22
+ else {
23
+ throw new Error(`Unable to coerce message from array: only human, AI, or system message coercion is currently supported.`);
24
+ }
25
+ }
11
26
  function coerceMessageLikeToMessage(messageLike) {
12
27
  if (typeof messageLike === "string") {
13
28
  return new human_js_1.HumanMessage(messageLike);
@@ -15,18 +30,12 @@ function coerceMessageLikeToMessage(messageLike) {
15
30
  else if ((0, base_js_1.isBaseMessage)(messageLike)) {
16
31
  return messageLike;
17
32
  }
18
- const [type, content] = messageLike;
19
- if (type === "human" || type === "user") {
20
- return new human_js_1.HumanMessage({ content });
21
- }
22
- else if (type === "ai" || type === "assistant") {
23
- return new ai_js_1.AIMessage({ content });
24
- }
25
- else if (type === "system") {
26
- return new system_js_1.SystemMessage({ content });
33
+ if (Array.isArray(messageLike)) {
34
+ const [type, content] = messageLike;
35
+ return _constructMessageFromParams({ type, content });
27
36
  }
28
37
  else {
29
- throw new Error(`Unable to coerce message from array: only human, AI, or system message coercion is currently supported.`);
38
+ return _constructMessageFromParams(messageLike);
30
39
  }
31
40
  }
32
41
  exports.coerceMessageLikeToMessage = coerceMessageLikeToMessage;
@@ -5,6 +5,21 @@ import { FunctionMessage, FunctionMessageChunk, } from "./function.js";
5
5
  import { HumanMessage, HumanMessageChunk } from "./human.js";
6
6
  import { SystemMessage, SystemMessageChunk } from "./system.js";
7
7
  import { ToolMessage } from "./tool.js";
8
+ function _constructMessageFromParams(params) {
9
+ const { type, ...rest } = params;
10
+ if (type === "human" || type === "user") {
11
+ return new HumanMessage(rest);
12
+ }
13
+ else if (type === "ai" || type === "assistant") {
14
+ return new AIMessage(rest);
15
+ }
16
+ else if (type === "system") {
17
+ return new SystemMessage(rest);
18
+ }
19
+ else {
20
+ throw new Error(`Unable to coerce message from array: only human, AI, or system message coercion is currently supported.`);
21
+ }
22
+ }
8
23
  export function coerceMessageLikeToMessage(messageLike) {
9
24
  if (typeof messageLike === "string") {
10
25
  return new HumanMessage(messageLike);
@@ -12,18 +27,12 @@ export function coerceMessageLikeToMessage(messageLike) {
12
27
  else if (isBaseMessage(messageLike)) {
13
28
  return messageLike;
14
29
  }
15
- const [type, content] = messageLike;
16
- if (type === "human" || type === "user") {
17
- return new HumanMessage({ content });
18
- }
19
- else if (type === "ai" || type === "assistant") {
20
- return new AIMessage({ content });
21
- }
22
- else if (type === "system") {
23
- return new SystemMessage({ content });
30
+ if (Array.isArray(messageLike)) {
31
+ const [type, content] = messageLike;
32
+ return _constructMessageFromParams({ type, content });
24
33
  }
25
34
  else {
26
- throw new Error(`Unable to coerce message from array: only human, AI, or system message coercion is currently supported.`);
35
+ return _constructMessageFromParams(messageLike);
27
36
  }
28
37
  }
29
38
  /**
@@ -75,33 +75,37 @@ class MessagesPlaceholder extends BaseMessagePromptTemplate {
75
75
  get inputVariables() {
76
76
  return [this.variableName];
77
77
  }
78
- validateInputOrThrow(input, variableName) {
78
+ async formatMessages(values) {
79
+ const input = values[this.variableName];
79
80
  if (this.optional && !input) {
80
- return false;
81
+ return [];
81
82
  }
82
83
  else if (!input) {
83
- const error = new Error(`Error: Field "${variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: undefined`);
84
+ const error = new Error(`Field "${this.variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: undefined`);
84
85
  error.name = "InputFormatError";
85
86
  throw error;
86
87
  }
87
- let isInputBaseMessage = false;
88
- if (Array.isArray(input)) {
89
- isInputBaseMessage = input.every((message) => (0, index_js_1.isBaseMessage)(message));
90
- }
91
- else {
92
- isInputBaseMessage = (0, index_js_1.isBaseMessage)(input);
88
+ let formattedMessages;
89
+ try {
90
+ if (Array.isArray(input)) {
91
+ formattedMessages = input.map(index_js_1.coerceMessageLikeToMessage);
92
+ }
93
+ else {
94
+ formattedMessages = [(0, index_js_1.coerceMessageLikeToMessage)(input)];
95
+ }
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
97
  }
94
- if (!isInputBaseMessage) {
98
+ catch (e) {
95
99
  const readableInput = typeof input === "string" ? input : JSON.stringify(input, null, 2);
96
- const error = new Error(`Error: Field "${variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: ${readableInput}`);
100
+ const error = new Error([
101
+ `Field "${this.variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages or coerceable values as input.`,
102
+ `Received value: ${readableInput}`,
103
+ `Additional message: ${e.message}`,
104
+ ].join("\n\n"));
97
105
  error.name = "InputFormatError";
98
106
  throw error;
99
107
  }
100
- return true;
101
- }
102
- async formatMessages(values) {
103
- this.validateInputOrThrow(values[this.variableName], this.variableName);
104
- return values[this.variableName] ?? [];
108
+ return formattedMessages;
105
109
  }
106
110
  }
107
111
  exports.MessagesPlaceholder = MessagesPlaceholder;
@@ -50,7 +50,6 @@ export declare class MessagesPlaceholder<RunInput extends InputValues = any> ext
50
50
  constructor(variableName: Extract<keyof RunInput, string>);
51
51
  constructor(fields: MessagesPlaceholderFields<Extract<keyof RunInput, string>>);
52
52
  get inputVariables(): Extract<keyof RunInput, string>[];
53
- validateInputOrThrow(input: Array<unknown> | undefined, variableName: Extract<keyof RunInput, string>): input is BaseMessage[];
54
53
  formatMessages(values: TypedPromptInputValues<RunInput>): Promise<BaseMessage[]>;
55
54
  }
56
55
  /**
@@ -71,33 +71,37 @@ export class MessagesPlaceholder extends BaseMessagePromptTemplate {
71
71
  get inputVariables() {
72
72
  return [this.variableName];
73
73
  }
74
- validateInputOrThrow(input, variableName) {
74
+ async formatMessages(values) {
75
+ const input = values[this.variableName];
75
76
  if (this.optional && !input) {
76
- return false;
77
+ return [];
77
78
  }
78
79
  else if (!input) {
79
- const error = new Error(`Error: Field "${variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: undefined`);
80
+ const error = new Error(`Field "${this.variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: undefined`);
80
81
  error.name = "InputFormatError";
81
82
  throw error;
82
83
  }
83
- let isInputBaseMessage = false;
84
- if (Array.isArray(input)) {
85
- isInputBaseMessage = input.every((message) => isBaseMessage(message));
86
- }
87
- else {
88
- isInputBaseMessage = isBaseMessage(input);
84
+ let formattedMessages;
85
+ try {
86
+ if (Array.isArray(input)) {
87
+ formattedMessages = input.map(coerceMessageLikeToMessage);
88
+ }
89
+ else {
90
+ formattedMessages = [coerceMessageLikeToMessage(input)];
91
+ }
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
93
  }
90
- if (!isInputBaseMessage) {
94
+ catch (e) {
91
95
  const readableInput = typeof input === "string" ? input : JSON.stringify(input, null, 2);
92
- const error = new Error(`Error: Field "${variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: ${readableInput}`);
96
+ const error = new Error([
97
+ `Field "${this.variableName}" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages or coerceable values as input.`,
98
+ `Received value: ${readableInput}`,
99
+ `Additional message: ${e.message}`,
100
+ ].join("\n\n"));
93
101
  error.name = "InputFormatError";
94
102
  throw error;
95
103
  }
96
- return true;
97
- }
98
- async formatMessages(values) {
99
- this.validateInputOrThrow(values[this.variableName], this.variableName);
100
- return values[this.variableName] ?? [];
104
+ return formattedMessages;
101
105
  }
102
106
  }
103
107
  /**
@@ -258,7 +258,7 @@ test("Test MessagesPlaceholder not optional", async () => {
258
258
  variableName: "foo",
259
259
  });
260
260
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
261
- await expect(prompt.formatMessages({})).rejects.toThrow('Error: Field "foo" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: undefined');
261
+ await expect(prompt.formatMessages({})).rejects.toThrow('Field "foo" in prompt uses a MessagesPlaceholder, which expects an array of BaseMessages as an input value. Received: undefined');
262
262
  });
263
263
  test("Test MessagesPlaceholder shorthand in a chat prompt template should throw for invalid syntax", async () => {
264
264
  expect(() => ChatPromptTemplate.fromMessages([["placeholder", "foo"]])).toThrow();
@@ -273,6 +273,56 @@ test("Test MessagesPlaceholder shorthand in a chat prompt template", async () =>
273
273
  new AIMessage("how r u"),
274
274
  ]);
275
275
  });
276
+ test("Test MessagesPlaceholder shorthand in a chat prompt template with object format", async () => {
277
+ const prompt = ChatPromptTemplate.fromMessages([["placeholder", "{foo}"]]);
278
+ const messages = await prompt.formatMessages({
279
+ foo: [
280
+ {
281
+ type: "system",
282
+ content: "some initial content",
283
+ },
284
+ {
285
+ type: "human",
286
+ content: [
287
+ {
288
+ text: "page: 1\ndescription: One Purchase Flow\ntimestamp: '2024-06-04T14:46:46.062Z'\ntype: navigate\nscreenshot_present: true\n",
289
+ type: "text",
290
+ },
291
+ {
292
+ text: "page: 3\ndescription: intent_str=buy,mode_str=redirect,screenName_str=order-completed,\ntimestamp: '2024-06-04T14:46:58.846Z'\ntype: Screen View\nscreenshot_present: false\n",
293
+ type: "text",
294
+ },
295
+ ],
296
+ },
297
+ {
298
+ type: "assistant",
299
+ content: "some captivating response",
300
+ },
301
+ ],
302
+ });
303
+ expect(messages).toEqual([
304
+ new SystemMessage("some initial content"),
305
+ new HumanMessage({
306
+ content: [
307
+ {
308
+ text: "page: 1\ndescription: One Purchase Flow\ntimestamp: '2024-06-04T14:46:46.062Z'\ntype: navigate\nscreenshot_present: true\n",
309
+ type: "text",
310
+ },
311
+ {
312
+ text: "page: 3\ndescription: intent_str=buy,mode_str=redirect,screenName_str=order-completed,\ntimestamp: '2024-06-04T14:46:58.846Z'\ntype: Screen View\nscreenshot_present: false\n",
313
+ type: "text",
314
+ },
315
+ ],
316
+ }),
317
+ new AIMessage("some captivating response"),
318
+ ]);
319
+ });
320
+ test("Test MessagesPlaceholder with invalid shorthand should throw", async () => {
321
+ const prompt = ChatPromptTemplate.fromMessages([["placeholder", "{foo}"]]);
322
+ await expect(() => prompt.formatMessages({
323
+ foo: [{ badFormatting: true }],
324
+ })).rejects.toThrow();
325
+ });
276
326
  test("Test using partial", async () => {
277
327
  const userPrompt = new PromptTemplate({
278
328
  template: "{foo}{bar}",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {