@langchain/core
Version:
Core LangChain.js abstractions and schemas
108 lines (107 loc) • 4.66 kB
JavaScript
import { zodToJsonSchema } from "zod-to-json-schema";
import { Runnable } from "../runnables/base.js";
import { isZodSchema } from "./types/is_zod_schema.js";
/**
* Formats a `StructuredTool` or `RunnableToolLike` instance into a format
* that is compatible with OpenAI function calling. It uses the `zodToJsonSchema`
* function to convert the schema of the `StructuredTool` or `RunnableToolLike`
* into a JSON schema, which is then used as the parameters for the OpenAI function.
*
* @param {StructuredToolInterface | RunnableToolLike} tool The tool to convert to an OpenAI function.
* @returns {FunctionDefinition} The inputted tool in OpenAI function format.
*/
export function convertToOpenAIFunction(tool, fields) {
// @TODO 0.3.0 Remove the `number` typing
const fieldsCopy = typeof fields === "number" ? undefined : fields;
return {
name: tool.name,
description: tool.description,
parameters: zodToJsonSchema(tool.schema),
// Do not include the `strict` field if it is `undefined`.
...(fieldsCopy?.strict !== undefined ? { strict: fieldsCopy.strict } : {}),
};
}
/**
* Formats a `StructuredTool` or `RunnableToolLike` instance into a
* format that is compatible with OpenAI tool calling. It uses the
* `zodToJsonSchema` function to convert the schema of the `StructuredTool`
* or `RunnableToolLike` into a JSON schema, which is then used as the
* parameters for the OpenAI tool.
*
* @param {StructuredToolInterface | Record<string, any> | RunnableToolLike} tool The tool to convert to an OpenAI tool.
* @returns {ToolDefinition} The inputted tool in OpenAI tool format.
*/
export function convertToOpenAITool(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tool, fields) {
// @TODO 0.3.0 Remove the `number` typing
const fieldsCopy = typeof fields === "number" ? undefined : fields;
let toolDef;
if (isLangChainTool(tool)) {
toolDef = {
type: "function",
function: convertToOpenAIFunction(tool),
};
}
else {
toolDef = tool;
}
if (fieldsCopy?.strict !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
toolDef.function.strict = fieldsCopy.strict;
}
return toolDef;
}
/**
* Confirm whether the inputted tool is an instance of `StructuredToolInterface`.
*
* @param {StructuredToolInterface | Record<string, any> | undefined} tool The tool to check if it is an instance of `StructuredToolInterface`.
* @returns {tool is StructuredToolInterface} Whether the inputted tool is an instance of `StructuredToolInterface`.
*/
export function isStructuredTool(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tool) {
return (tool !== undefined &&
Array.isArray(tool.lc_namespace));
}
/**
* Confirm whether the inputted tool is an instance of `RunnableToolLike`.
*
* @param {unknown | undefined} tool The tool to check if it is an instance of `RunnableToolLike`.
* @returns {tool is RunnableToolLike} Whether the inputted tool is an instance of `RunnableToolLike`.
*/
export function isRunnableToolLike(tool) {
return (tool !== undefined &&
Runnable.isRunnable(tool) &&
"lc_name" in tool.constructor &&
typeof tool.constructor.lc_name === "function" &&
tool.constructor.lc_name() === "RunnableToolLike");
}
/**
* Confirm whether or not the tool contains the necessary properties to be considered a `StructuredToolParams`.
*
* @param {unknown | undefined} tool The object to check if it is a `StructuredToolParams`.
* @returns {tool is StructuredToolParams} Whether the inputted object is a `StructuredToolParams`.
*/
export function isStructuredToolParams(tool) {
return (!!tool &&
typeof tool === "object" &&
"name" in tool &&
"schema" in tool &&
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isZodSchema(tool.schema));
}
/**
* Whether or not the tool is one of StructuredTool, RunnableTool or StructuredToolParams.
* It returns `is StructuredToolParams` since that is the most minimal interface of the three,
* while still containing the necessary properties to be passed to a LLM for tool calling.
*
* @param {unknown | undefined} tool The tool to check if it is a LangChain tool.
* @returns {tool is StructuredToolParams} Whether the inputted tool is a LangChain tool.
*/
export function isLangChainTool(tool) {
return (isStructuredToolParams(tool) ||
isRunnableToolLike(tool) ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
isStructuredTool(tool));
}