@langchain/core 0.2.19 → 0.2.21

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.
Files changed (39) hide show
  1. package/dist/language_models/base.d.ts +8 -10
  2. package/dist/language_models/chat_models.cjs +5 -6
  3. package/dist/language_models/chat_models.d.ts +12 -12
  4. package/dist/language_models/chat_models.js +5 -6
  5. package/dist/language_models/llms.cjs +5 -6
  6. package/dist/language_models/llms.d.ts +10 -12
  7. package/dist/language_models/llms.js +5 -6
  8. package/dist/runnables/base.cjs +34 -9
  9. package/dist/runnables/base.js +34 -9
  10. package/dist/runnables/config.cjs +41 -0
  11. package/dist/runnables/config.js +41 -0
  12. package/dist/runnables/remote.cjs +14 -13
  13. package/dist/runnables/remote.js +14 -13
  14. package/dist/runnables/types.d.ts +10 -0
  15. package/dist/tools/index.d.ts +15 -0
  16. package/dist/utils/function_calling.cjs +50 -6
  17. package/dist/utils/function_calling.d.ts +31 -3
  18. package/dist/utils/function_calling.js +47 -5
  19. package/dist/utils/math.cjs +6 -4
  20. package/dist/utils/math.js +6 -4
  21. package/dist/utils/ml-distance/distances.cjs +18 -0
  22. package/dist/utils/ml-distance/distances.d.ts +8 -0
  23. package/dist/utils/ml-distance/distances.js +14 -0
  24. package/dist/utils/ml-distance/similarities.cjs +21 -0
  25. package/dist/utils/ml-distance/similarities.d.ts +7 -0
  26. package/dist/utils/ml-distance/similarities.js +17 -0
  27. package/dist/utils/ml-distance-euclidean/euclidean.cjs +15 -0
  28. package/dist/utils/ml-distance-euclidean/euclidean.d.ts +2 -0
  29. package/dist/utils/ml-distance-euclidean/euclidean.js +10 -0
  30. package/dist/utils/signal.cjs +28 -0
  31. package/dist/utils/signal.d.ts +1 -0
  32. package/dist/utils/signal.js +24 -0
  33. package/dist/utils/stream.cjs +19 -4
  34. package/dist/utils/stream.d.ts +3 -1
  35. package/dist/utils/stream.js +19 -4
  36. package/dist/utils/testing/index.cjs +9 -3
  37. package/dist/utils/testing/index.d.ts +9 -6
  38. package/dist/utils/testing/index.js +9 -3
  39. package/package.json +2 -3
@@ -24,6 +24,31 @@ function mergeConfigs(...configs) {
24
24
  else if (key === "configurable") {
25
25
  copy[key] = { ...copy[key], ...options[key] };
26
26
  }
27
+ else if (key === "timeout") {
28
+ if (copy.timeout === undefined) {
29
+ copy.timeout = options.timeout;
30
+ }
31
+ else if (options.timeout !== undefined) {
32
+ copy.timeout = Math.min(copy.timeout, options.timeout);
33
+ }
34
+ }
35
+ else if (key === "signal") {
36
+ if (copy.signal === undefined) {
37
+ copy.signal = options.signal;
38
+ }
39
+ else if (options.signal !== undefined) {
40
+ if ("any" in AbortSignal) {
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ copy.signal = AbortSignal.any([
43
+ copy.signal,
44
+ options.signal,
45
+ ]);
46
+ }
47
+ else {
48
+ copy.signal = options.signal;
49
+ }
50
+ }
51
+ }
27
52
  else if (key === "callbacks") {
28
53
  const baseCallbacks = copy.callbacks;
29
54
  const providedCallbacks = options.callbacks;
@@ -130,6 +155,22 @@ function ensureConfig(config) {
130
155
  }
131
156
  }
132
157
  }
158
+ if (empty.timeout !== undefined) {
159
+ if (empty.timeout <= 0) {
160
+ throw new Error("Timeout must be a positive number");
161
+ }
162
+ const timeoutSignal = AbortSignal.timeout(empty.timeout);
163
+ if (empty.signal !== undefined) {
164
+ if ("any" in AbortSignal) {
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ empty.signal = AbortSignal.any([empty.signal, timeoutSignal]);
167
+ }
168
+ }
169
+ else {
170
+ empty.signal = timeoutSignal;
171
+ }
172
+ delete empty.timeout;
173
+ }
133
174
  return empty;
134
175
  }
135
176
  exports.ensureConfig = ensureConfig;
@@ -20,6 +20,31 @@ export function mergeConfigs(...configs) {
20
20
  else if (key === "configurable") {
21
21
  copy[key] = { ...copy[key], ...options[key] };
22
22
  }
23
+ else if (key === "timeout") {
24
+ if (copy.timeout === undefined) {
25
+ copy.timeout = options.timeout;
26
+ }
27
+ else if (options.timeout !== undefined) {
28
+ copy.timeout = Math.min(copy.timeout, options.timeout);
29
+ }
30
+ }
31
+ else if (key === "signal") {
32
+ if (copy.signal === undefined) {
33
+ copy.signal = options.signal;
34
+ }
35
+ else if (options.signal !== undefined) {
36
+ if ("any" in AbortSignal) {
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ copy.signal = AbortSignal.any([
39
+ copy.signal,
40
+ options.signal,
41
+ ]);
42
+ }
43
+ else {
44
+ copy.signal = options.signal;
45
+ }
46
+ }
47
+ }
23
48
  else if (key === "callbacks") {
24
49
  const baseCallbacks = copy.callbacks;
25
50
  const providedCallbacks = options.callbacks;
@@ -125,6 +150,22 @@ export function ensureConfig(config) {
125
150
  }
126
151
  }
127
152
  }
153
+ if (empty.timeout !== undefined) {
154
+ if (empty.timeout <= 0) {
155
+ throw new Error("Timeout must be a positive number");
156
+ }
157
+ const timeoutSignal = AbortSignal.timeout(empty.timeout);
158
+ if (empty.signal !== undefined) {
159
+ if ("any" in AbortSignal) {
160
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
+ empty.signal = AbortSignal.any([empty.signal, timeoutSignal]);
162
+ }
163
+ }
164
+ else {
165
+ empty.signal = timeoutSignal;
166
+ }
167
+ delete empty.timeout;
168
+ }
128
169
  return empty;
129
170
  }
130
171
  /**
@@ -186,9 +186,10 @@ function deserialize(str) {
186
186
  const obj = JSON.parse(str);
187
187
  return revive(obj);
188
188
  }
189
- function removeCallbacks(options) {
189
+ function removeCallbacksAndSignal(options) {
190
190
  const rest = { ...options };
191
191
  delete rest.callbacks;
192
+ delete rest.signal;
192
193
  return rest;
193
194
  }
194
195
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -253,7 +254,7 @@ class RemoteRunnable extends base_js_1.Runnable {
253
254
  this.url = url.replace(/\/$/, ""); // remove trailing slash
254
255
  this.options = options;
255
256
  }
256
- async post(path, body) {
257
+ async post(path, body, signal) {
257
258
  return fetch(`${this.url}${path}`, {
258
259
  method: "POST",
259
260
  body: JSON.stringify(serialize(body)),
@@ -261,16 +262,16 @@ class RemoteRunnable extends base_js_1.Runnable {
261
262
  "Content-Type": "application/json",
262
263
  ...this.options?.headers,
263
264
  },
264
- signal: AbortSignal.timeout(this.options?.timeout ?? 60000),
265
+ signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
265
266
  });
266
267
  }
267
268
  async _invoke(input, options, _) {
268
269
  const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
269
270
  const response = await this.post("/invoke", {
270
271
  input,
271
- config: removeCallbacks(config),
272
+ config: removeCallbacksAndSignal(config),
272
273
  kwargs: kwargs ?? {},
273
- });
274
+ }, config.signal);
274
275
  if (!response.ok) {
275
276
  throw new Error(`${response.status} Error: ${await response.text()}`);
276
277
  }
@@ -291,10 +292,10 @@ class RemoteRunnable extends base_js_1.Runnable {
291
292
  const response = await this.post("/batch", {
292
293
  inputs,
293
294
  config: (configs ?? [])
294
- .map(removeCallbacks)
295
+ .map(removeCallbacksAndSignal)
295
296
  .map((config) => ({ ...config, ...batchOptions })),
296
297
  kwargs,
297
- });
298
+ }, options?.[0]?.signal);
298
299
  if (!response.ok) {
299
300
  throw new Error(`${response.status} Error: ${await response.text()}`);
300
301
  }
@@ -319,9 +320,9 @@ class RemoteRunnable extends base_js_1.Runnable {
319
320
  try {
320
321
  const response = await this.post("/stream", {
321
322
  input,
322
- config: removeCallbacks(config),
323
+ config: removeCallbacksAndSignal(config),
323
324
  kwargs,
324
- });
325
+ }, config.signal);
325
326
  if (!response.ok) {
326
327
  const json = await response.json();
327
328
  const error = new Error(`RemoteRunnable call failed with status code ${response.status}: ${json.message}`);
@@ -378,11 +379,11 @@ class RemoteRunnable extends base_js_1.Runnable {
378
379
  try {
379
380
  const response = await this.post("/stream_log", {
380
381
  input,
381
- config: removeCallbacks(config),
382
+ config: removeCallbacksAndSignal(config),
382
383
  kwargs,
383
384
  ...camelCaseStreamOptions,
384
385
  diff: false,
385
- });
386
+ }, config.signal);
386
387
  const { body, ok } = response;
387
388
  if (!ok) {
388
389
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -430,11 +431,11 @@ class RemoteRunnable extends base_js_1.Runnable {
430
431
  try {
431
432
  const response = await outerThis.post("/stream_events", {
432
433
  input,
433
- config: removeCallbacks(config),
434
+ config: removeCallbacksAndSignal(config),
434
435
  kwargs,
435
436
  ...camelCaseStreamOptions,
436
437
  diff: false,
437
- });
438
+ }, config.signal);
438
439
  const { body, ok } = response;
439
440
  if (!ok) {
440
441
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -183,9 +183,10 @@ function deserialize(str) {
183
183
  const obj = JSON.parse(str);
184
184
  return revive(obj);
185
185
  }
186
- function removeCallbacks(options) {
186
+ function removeCallbacksAndSignal(options) {
187
187
  const rest = { ...options };
188
188
  delete rest.callbacks;
189
+ delete rest.signal;
189
190
  return rest;
190
191
  }
191
192
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -250,7 +251,7 @@ export class RemoteRunnable extends Runnable {
250
251
  this.url = url.replace(/\/$/, ""); // remove trailing slash
251
252
  this.options = options;
252
253
  }
253
- async post(path, body) {
254
+ async post(path, body, signal) {
254
255
  return fetch(`${this.url}${path}`, {
255
256
  method: "POST",
256
257
  body: JSON.stringify(serialize(body)),
@@ -258,16 +259,16 @@ export class RemoteRunnable extends Runnable {
258
259
  "Content-Type": "application/json",
259
260
  ...this.options?.headers,
260
261
  },
261
- signal: AbortSignal.timeout(this.options?.timeout ?? 60000),
262
+ signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
262
263
  });
263
264
  }
264
265
  async _invoke(input, options, _) {
265
266
  const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
266
267
  const response = await this.post("/invoke", {
267
268
  input,
268
- config: removeCallbacks(config),
269
+ config: removeCallbacksAndSignal(config),
269
270
  kwargs: kwargs ?? {},
270
- });
271
+ }, config.signal);
271
272
  if (!response.ok) {
272
273
  throw new Error(`${response.status} Error: ${await response.text()}`);
273
274
  }
@@ -288,10 +289,10 @@ export class RemoteRunnable extends Runnable {
288
289
  const response = await this.post("/batch", {
289
290
  inputs,
290
291
  config: (configs ?? [])
291
- .map(removeCallbacks)
292
+ .map(removeCallbacksAndSignal)
292
293
  .map((config) => ({ ...config, ...batchOptions })),
293
294
  kwargs,
294
- });
295
+ }, options?.[0]?.signal);
295
296
  if (!response.ok) {
296
297
  throw new Error(`${response.status} Error: ${await response.text()}`);
297
298
  }
@@ -316,9 +317,9 @@ export class RemoteRunnable extends Runnable {
316
317
  try {
317
318
  const response = await this.post("/stream", {
318
319
  input,
319
- config: removeCallbacks(config),
320
+ config: removeCallbacksAndSignal(config),
320
321
  kwargs,
321
- });
322
+ }, config.signal);
322
323
  if (!response.ok) {
323
324
  const json = await response.json();
324
325
  const error = new Error(`RemoteRunnable call failed with status code ${response.status}: ${json.message}`);
@@ -375,11 +376,11 @@ export class RemoteRunnable extends Runnable {
375
376
  try {
376
377
  const response = await this.post("/stream_log", {
377
378
  input,
378
- config: removeCallbacks(config),
379
+ config: removeCallbacksAndSignal(config),
379
380
  kwargs,
380
381
  ...camelCaseStreamOptions,
381
382
  diff: false,
382
- });
383
+ }, config.signal);
383
384
  const { body, ok } = response;
384
385
  if (!ok) {
385
386
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -427,11 +428,11 @@ export class RemoteRunnable extends Runnable {
427
428
  try {
428
429
  const response = await outerThis.post("/stream_events", {
429
430
  input,
430
- config: removeCallbacks(config),
431
+ config: removeCallbacksAndSignal(config),
431
432
  kwargs,
432
433
  ...camelCaseStreamOptions,
433
434
  diff: false,
434
- });
435
+ }, config.signal);
435
436
  const { body, ok } = response;
436
437
  if (!ok) {
437
438
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -53,4 +53,14 @@ export interface RunnableConfig extends BaseCallbackConfig {
53
53
  recursionLimit?: number;
54
54
  /** Maximum number of parallel calls to make. */
55
55
  maxConcurrency?: number;
56
+ /**
57
+ * Timeout for this call in milliseconds.
58
+ */
59
+ timeout?: number;
60
+ /**
61
+ * Abort signal for this call.
62
+ * If provided, the call will be aborted when the signal is aborted.
63
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
64
+ */
65
+ signal?: AbortSignal;
56
66
  }
@@ -26,8 +26,17 @@ export interface ToolParams extends BaseLangChainParams {
26
26
  */
27
27
  responseFormat?: ResponseFormat;
28
28
  }
29
+ export interface StructuredToolParams extends Pick<StructuredToolInterface, "name" | "schema"> {
30
+ /**
31
+ * An optional description of the tool to pass to the model.
32
+ */
33
+ description?: string;
34
+ }
29
35
  export interface StructuredToolInterface<T extends ZodObjectAny = ZodObjectAny> extends RunnableInterface<(z.output<T> extends string ? string : never) | z.input<T> | ToolCall, ToolReturnType> {
30
36
  lc_namespace: string[];
37
+ /**
38
+ * A Zod schema representing the parameters of the tool.
39
+ */
31
40
  schema: T | z.ZodEffects<T>;
32
41
  /**
33
42
  * @deprecated Use .invoke() instead. Will be removed in 0.3.0.
@@ -43,7 +52,13 @@ export interface StructuredToolInterface<T extends ZodObjectAny = ZodObjectAny>
43
52
  call(arg: (z.output<T> extends string ? string : never) | z.input<T> | ToolCall, configArg?: Callbacks | RunnableConfig,
44
53
  /** @deprecated */
45
54
  tags?: string[]): Promise<ToolReturnType>;
55
+ /**
56
+ * The name of the tool.
57
+ */
46
58
  name: string;
59
+ /**
60
+ * A description of the tool.
61
+ */
47
62
  description: string;
48
63
  returnDirect: boolean;
49
64
  }
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isRunnableToolLike = exports.isStructuredTool = exports.convertToOpenAITool = exports.convertToOpenAIFunction = void 0;
3
+ exports.isLangChainTool = exports.isStructuredToolParams = exports.isRunnableToolLike = exports.isStructuredTool = exports.convertToOpenAITool = exports.convertToOpenAIFunction = void 0;
4
4
  const zod_to_json_schema_1 = require("zod-to-json-schema");
5
5
  const base_js_1 = require("../runnables/base.cjs");
6
+ const is_zod_schema_js_1 = require("./types/is_zod_schema.cjs");
6
7
  /**
7
8
  * Formats a `StructuredTool` or `RunnableToolLike` instance into a format
8
9
  * that is compatible with OpenAI function calling. It uses the `zodToJsonSchema`
@@ -12,11 +13,15 @@ const base_js_1 = require("../runnables/base.cjs");
12
13
  * @param {StructuredToolInterface | RunnableToolLike} tool The tool to convert to an OpenAI function.
13
14
  * @returns {FunctionDefinition} The inputted tool in OpenAI function format.
14
15
  */
15
- function convertToOpenAIFunction(tool) {
16
+ function convertToOpenAIFunction(tool, fields) {
17
+ // @TODO 0.3.0 Remove the `number` typing
18
+ const fieldsCopy = typeof fields === "number" ? undefined : fields;
16
19
  return {
17
20
  name: tool.name,
18
21
  description: tool.description,
19
22
  parameters: (0, zod_to_json_schema_1.zodToJsonSchema)(tool.schema),
23
+ // Do not include the `strict` field if it is `undefined`.
24
+ ...(fieldsCopy?.strict !== undefined ? { strict: fieldsCopy.strict } : {}),
20
25
  };
21
26
  }
22
27
  exports.convertToOpenAIFunction = convertToOpenAIFunction;
@@ -32,14 +37,23 @@ exports.convertToOpenAIFunction = convertToOpenAIFunction;
32
37
  */
33
38
  function convertToOpenAITool(
34
39
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- tool) {
36
- if (isStructuredTool(tool) || isRunnableToolLike(tool)) {
37
- return {
40
+ tool, fields) {
41
+ // @TODO 0.3.0 Remove the `number` typing
42
+ const fieldsCopy = typeof fields === "number" ? undefined : fields;
43
+ let toolDef;
44
+ if (isLangChainTool(tool)) {
45
+ toolDef = {
38
46
  type: "function",
39
47
  function: convertToOpenAIFunction(tool),
40
48
  };
41
49
  }
42
- return tool;
50
+ else {
51
+ toolDef = tool;
52
+ }
53
+ if (fieldsCopy?.strict !== undefined) {
54
+ toolDef.function.strict = fieldsCopy.strict;
55
+ }
56
+ return toolDef;
43
57
  }
44
58
  exports.convertToOpenAITool = convertToOpenAITool;
45
59
  /**
@@ -69,3 +83,33 @@ function isRunnableToolLike(tool) {
69
83
  tool.constructor.lc_name() === "RunnableToolLike");
70
84
  }
71
85
  exports.isRunnableToolLike = isRunnableToolLike;
86
+ /**
87
+ * Confirm whether or not the tool contains the necessary properties to be considered a `StructuredToolParams`.
88
+ *
89
+ * @param {unknown | undefined} tool The object to check if it is a `StructuredToolParams`.
90
+ * @returns {tool is StructuredToolParams} Whether the inputted object is a `StructuredToolParams`.
91
+ */
92
+ function isStructuredToolParams(tool) {
93
+ return (!!tool &&
94
+ typeof tool === "object" &&
95
+ "name" in tool &&
96
+ "schema" in tool &&
97
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
98
+ (0, is_zod_schema_js_1.isZodSchema)(tool.schema));
99
+ }
100
+ exports.isStructuredToolParams = isStructuredToolParams;
101
+ /**
102
+ * Whether or not the tool is one of StructuredTool, RunnableTool or StructuredToolParams.
103
+ * It returns `is StructuredToolParams` since that is the most minimal interface of the three,
104
+ * while still containing the necessary properties to be passed to a LLM for tool calling.
105
+ *
106
+ * @param {unknown | undefined} tool The tool to check if it is a LangChain tool.
107
+ * @returns {tool is StructuredToolParams} Whether the inputted tool is a LangChain tool.
108
+ */
109
+ function isLangChainTool(tool) {
110
+ return (isStructuredToolParams(tool) ||
111
+ isRunnableToolLike(tool) ||
112
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
+ isStructuredTool(tool));
114
+ }
115
+ exports.isLangChainTool = isLangChainTool;
@@ -1,4 +1,4 @@
1
- import { StructuredToolInterface } from "../tools/index.js";
1
+ import { StructuredToolInterface, StructuredToolParams } from "../tools/index.js";
2
2
  import { FunctionDefinition, ToolDefinition } from "../language_models/base.js";
3
3
  import { RunnableToolLike } from "../runnables/base.js";
4
4
  /**
@@ -10,7 +10,13 @@ import { RunnableToolLike } from "../runnables/base.js";
10
10
  * @param {StructuredToolInterface | RunnableToolLike} tool The tool to convert to an OpenAI function.
11
11
  * @returns {FunctionDefinition} The inputted tool in OpenAI function format.
12
12
  */
13
- export declare function convertToOpenAIFunction(tool: StructuredToolInterface | RunnableToolLike): FunctionDefinition;
13
+ export declare function convertToOpenAIFunction(tool: StructuredToolInterface | RunnableToolLike | StructuredToolParams, fields?: {
14
+ /**
15
+ * If `true`, model output is guaranteed to exactly match the JSON Schema
16
+ * provided in the function definition.
17
+ */
18
+ strict?: boolean;
19
+ } | number): FunctionDefinition;
14
20
  /**
15
21
  * Formats a `StructuredTool` or `RunnableToolLike` instance into a
16
22
  * format that is compatible with OpenAI tool calling. It uses the
@@ -21,7 +27,13 @@ export declare function convertToOpenAIFunction(tool: StructuredToolInterface |
21
27
  * @param {StructuredToolInterface | Record<string, any> | RunnableToolLike} tool The tool to convert to an OpenAI tool.
22
28
  * @returns {ToolDefinition} The inputted tool in OpenAI tool format.
23
29
  */
24
- export declare function convertToOpenAITool(tool: StructuredToolInterface | Record<string, any> | RunnableToolLike): ToolDefinition;
30
+ export declare function convertToOpenAITool(tool: StructuredToolInterface | Record<string, any> | RunnableToolLike, fields?: {
31
+ /**
32
+ * If `true`, model output is guaranteed to exactly match the JSON Schema
33
+ * provided in the function definition.
34
+ */
35
+ strict?: boolean;
36
+ } | number): ToolDefinition;
25
37
  /**
26
38
  * Confirm whether the inputted tool is an instance of `StructuredToolInterface`.
27
39
  *
@@ -36,3 +48,19 @@ export declare function isStructuredTool(tool?: StructuredToolInterface | Record
36
48
  * @returns {tool is RunnableToolLike} Whether the inputted tool is an instance of `RunnableToolLike`.
37
49
  */
38
50
  export declare function isRunnableToolLike(tool?: unknown): tool is RunnableToolLike;
51
+ /**
52
+ * Confirm whether or not the tool contains the necessary properties to be considered a `StructuredToolParams`.
53
+ *
54
+ * @param {unknown | undefined} tool The object to check if it is a `StructuredToolParams`.
55
+ * @returns {tool is StructuredToolParams} Whether the inputted object is a `StructuredToolParams`.
56
+ */
57
+ export declare function isStructuredToolParams(tool?: unknown): tool is StructuredToolParams;
58
+ /**
59
+ * Whether or not the tool is one of StructuredTool, RunnableTool or StructuredToolParams.
60
+ * It returns `is StructuredToolParams` since that is the most minimal interface of the three,
61
+ * while still containing the necessary properties to be passed to a LLM for tool calling.
62
+ *
63
+ * @param {unknown | undefined} tool The tool to check if it is a LangChain tool.
64
+ * @returns {tool is StructuredToolParams} Whether the inputted tool is a LangChain tool.
65
+ */
66
+ export declare function isLangChainTool(tool?: unknown): tool is StructuredToolParams;
@@ -1,5 +1,6 @@
1
1
  import { zodToJsonSchema } from "zod-to-json-schema";
2
2
  import { Runnable } from "../runnables/base.js";
3
+ import { isZodSchema } from "./types/is_zod_schema.js";
3
4
  /**
4
5
  * Formats a `StructuredTool` or `RunnableToolLike` instance into a format
5
6
  * that is compatible with OpenAI function calling. It uses the `zodToJsonSchema`
@@ -9,11 +10,15 @@ import { Runnable } from "../runnables/base.js";
9
10
  * @param {StructuredToolInterface | RunnableToolLike} tool The tool to convert to an OpenAI function.
10
11
  * @returns {FunctionDefinition} The inputted tool in OpenAI function format.
11
12
  */
12
- export function convertToOpenAIFunction(tool) {
13
+ export function convertToOpenAIFunction(tool, fields) {
14
+ // @TODO 0.3.0 Remove the `number` typing
15
+ const fieldsCopy = typeof fields === "number" ? undefined : fields;
13
16
  return {
14
17
  name: tool.name,
15
18
  description: tool.description,
16
19
  parameters: zodToJsonSchema(tool.schema),
20
+ // Do not include the `strict` field if it is `undefined`.
21
+ ...(fieldsCopy?.strict !== undefined ? { strict: fieldsCopy.strict } : {}),
17
22
  };
18
23
  }
19
24
  /**
@@ -28,14 +33,23 @@ export function convertToOpenAIFunction(tool) {
28
33
  */
29
34
  export function convertToOpenAITool(
30
35
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
- tool) {
32
- if (isStructuredTool(tool) || isRunnableToolLike(tool)) {
33
- return {
36
+ tool, fields) {
37
+ // @TODO 0.3.0 Remove the `number` typing
38
+ const fieldsCopy = typeof fields === "number" ? undefined : fields;
39
+ let toolDef;
40
+ if (isLangChainTool(tool)) {
41
+ toolDef = {
34
42
  type: "function",
35
43
  function: convertToOpenAIFunction(tool),
36
44
  };
37
45
  }
38
- return tool;
46
+ else {
47
+ toolDef = tool;
48
+ }
49
+ if (fieldsCopy?.strict !== undefined) {
50
+ toolDef.function.strict = fieldsCopy.strict;
51
+ }
52
+ return toolDef;
39
53
  }
40
54
  /**
41
55
  * Confirm whether the inputted tool is an instance of `StructuredToolInterface`.
@@ -62,3 +76,31 @@ export function isRunnableToolLike(tool) {
62
76
  typeof tool.constructor.lc_name === "function" &&
63
77
  tool.constructor.lc_name() === "RunnableToolLike");
64
78
  }
79
+ /**
80
+ * Confirm whether or not the tool contains the necessary properties to be considered a `StructuredToolParams`.
81
+ *
82
+ * @param {unknown | undefined} tool The object to check if it is a `StructuredToolParams`.
83
+ * @returns {tool is StructuredToolParams} Whether the inputted object is a `StructuredToolParams`.
84
+ */
85
+ export function isStructuredToolParams(tool) {
86
+ return (!!tool &&
87
+ typeof tool === "object" &&
88
+ "name" in tool &&
89
+ "schema" in tool &&
90
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
+ isZodSchema(tool.schema));
92
+ }
93
+ /**
94
+ * Whether or not the tool is one of StructuredTool, RunnableTool or StructuredToolParams.
95
+ * It returns `is StructuredToolParams` since that is the most minimal interface of the three,
96
+ * while still containing the necessary properties to be passed to a LLM for tool calling.
97
+ *
98
+ * @param {unknown | undefined} tool The tool to check if it is a LangChain tool.
99
+ * @returns {tool is StructuredToolParams} Whether the inputted tool is a LangChain tool.
100
+ */
101
+ export function isLangChainTool(tool) {
102
+ return (isStructuredToolParams(tool) ||
103
+ isRunnableToolLike(tool) ||
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ isStructuredTool(tool));
106
+ }
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.maximalMarginalRelevance = exports.euclideanDistance = exports.innerProduct = exports.cosineSimilarity = exports.normalize = exports.matrixFunc = void 0;
4
- const ml_distance_1 = require("ml-distance");
4
+ const similarities_js_1 = require("./ml-distance/similarities.cjs");
5
+ const distances_js_1 = require("./ml-distance/distances.cjs");
6
+ const euclidean_js_1 = require("./ml-distance-euclidean/euclidean.cjs");
5
7
  /**
6
8
  * Apply a row-wise function between two matrices with the same number of columns.
7
9
  *
@@ -45,15 +47,15 @@ exports.normalize = normalize;
45
47
  * @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.
46
48
  */
47
49
  function cosineSimilarity(X, Y) {
48
- return matrixFunc(X, Y, ml_distance_1.similarity.cosine);
50
+ return matrixFunc(X, Y, similarities_js_1.cosine);
49
51
  }
50
52
  exports.cosineSimilarity = cosineSimilarity;
51
53
  function innerProduct(X, Y) {
52
- return matrixFunc(X, Y, ml_distance_1.distance.innerProduct);
54
+ return matrixFunc(X, Y, distances_js_1.innerProduct);
53
55
  }
54
56
  exports.innerProduct = innerProduct;
55
57
  function euclideanDistance(X, Y) {
56
- return matrixFunc(X, Y, ml_distance_1.distance.euclidean);
58
+ return matrixFunc(X, Y, euclidean_js_1.euclidean);
57
59
  }
58
60
  exports.euclideanDistance = euclideanDistance;
59
61
  /**
@@ -1,4 +1,6 @@
1
- import { similarity as ml_distance_similarity, distance as ml_distance, } from "ml-distance";
1
+ import { cosine } from "./ml-distance/similarities.js";
2
+ import { innerProduct as innerProductDistance } from "./ml-distance/distances.js";
3
+ import { euclidean } from "./ml-distance-euclidean/euclidean.js";
2
4
  /**
3
5
  * Apply a row-wise function between two matrices with the same number of columns.
4
6
  *
@@ -40,13 +42,13 @@ export function normalize(M, similarity = false) {
40
42
  * @returns {number[][] | [[]]} A matrix where each row represents the cosine similarity values between the corresponding rows of X and Y.
41
43
  */
42
44
  export function cosineSimilarity(X, Y) {
43
- return matrixFunc(X, Y, ml_distance_similarity.cosine);
45
+ return matrixFunc(X, Y, cosine);
44
46
  }
45
47
  export function innerProduct(X, Y) {
46
- return matrixFunc(X, Y, ml_distance.innerProduct);
48
+ return matrixFunc(X, Y, innerProductDistance);
47
49
  }
48
50
  export function euclideanDistance(X, Y) {
49
- return matrixFunc(X, Y, ml_distance.euclidean);
51
+ return matrixFunc(X, Y, euclidean);
50
52
  }
51
53
  /**
52
54
  * This function implements the Maximal Marginal Relevance algorithm
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.innerProduct = void 0;
4
+ /**
5
+ *Returns the Inner Product similarity between vectors a and b
6
+ * @link [Inner Product Similarity algorithm](https://www.naun.org/main/NAUN/ijmmas/mmmas-49.pdf)
7
+ * @param a - first vector
8
+ * @param b - second vector
9
+ *
10
+ */
11
+ function innerProduct(a, b) {
12
+ let ans = 0;
13
+ for (let i = 0; i < a.length; i++) {
14
+ ans += a[i] * b[i];
15
+ }
16
+ return ans;
17
+ }
18
+ exports.innerProduct = innerProduct;
@@ -0,0 +1,8 @@
1
+ /**
2
+ *Returns the Inner Product similarity between vectors a and b
3
+ * @link [Inner Product Similarity algorithm](https://www.naun.org/main/NAUN/ijmmas/mmmas-49.pdf)
4
+ * @param a - first vector
5
+ * @param b - second vector
6
+ *
7
+ */
8
+ export declare function innerProduct(a: number[], b: number[]): number;
@@ -0,0 +1,14 @@
1
+ /**
2
+ *Returns the Inner Product similarity between vectors a and b
3
+ * @link [Inner Product Similarity algorithm](https://www.naun.org/main/NAUN/ijmmas/mmmas-49.pdf)
4
+ * @param a - first vector
5
+ * @param b - second vector
6
+ *
7
+ */
8
+ export function innerProduct(a, b) {
9
+ let ans = 0;
10
+ for (let i = 0; i < a.length; i++) {
11
+ ans += a[i] * b[i];
12
+ }
13
+ return ans;
14
+ }