diff --git a/docs/core_docs/docs/how_to/chatbots_tools.ipynb b/docs/core_docs/docs/how_to/chatbots_tools.ipynb index 0568d79112f3..27cb36437b7a 100644 --- a/docs/core_docs/docs/how_to/chatbots_tools.ipynb +++ b/docs/core_docs/docs/how_to/chatbots_tools.ipynb @@ -87,7 +87,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Great! Now let’s assemble our agent:\n" + "Great! Now let’s assemble our agent:\n", + "\n", + "```{=mdx}\n", + ":::tip\n", + "As of `langchain` version `0.2.8`, the `createOpenAIToolsAgent` function now supports [OpenAI-formatted tools](https://api.js.langchain.com/interfaces/langchain_core_language_models_base.ToolDefinition.html).\n", + ":::\n", + "```\n" ] }, { diff --git a/docs/core_docs/docs/how_to/generative_ui.mdx b/docs/core_docs/docs/how_to/generative_ui.mdx index e4cb26d44527..d0d091ef8508 100644 --- a/docs/core_docs/docs/how_to/generative_ui.mdx +++ b/docs/core_docs/docs/how_to/generative_ui.mdx @@ -47,6 +47,10 @@ export const agentExecutor = new AgentExecutor({ }); ``` +:::tip +As of `langchain` version `0.2.8`, the `createToolCallingAgent` function now supports [OpenAI-formatted tools](https://api.js.langchain.com/interfaces/langchain_core_language_models_base.ToolDefinition.html). +::: + ```tsx agent.tsx async function agent(inputs: { input: string }) { "use server"; diff --git a/docs/core_docs/docs/how_to/stream_agent_client.mdx b/docs/core_docs/docs/how_to/stream_agent_client.mdx index e531929978ca..d954a9c8a1c7 100644 --- a/docs/core_docs/docs/how_to/stream_agent_client.mdx +++ b/docs/core_docs/docs/how_to/stream_agent_client.mdx @@ -94,6 +94,10 @@ Next, lets define our async function inside which contains the agent logic: }); ``` +:::tip +As of `langchain` version `0.2.8`, the `createToolCallingAgent` function now supports [OpenAI-formatted tools](https://api.js.langchain.com/interfaces/langchain_core_language_models_base.ToolDefinition.html). +::: + Here you can see we're doing a few things: The first is we're defining our list of tools (in this case we're only using a single tool) and pulling in our prompt from the LangChain prompt hub. diff --git a/docs/core_docs/docs/how_to/tools_prompting.ipynb b/docs/core_docs/docs/how_to/tools_prompting.ipynb index 1f975d74aef7..a5ac5aa739d8 100644 --- a/docs/core_docs/docs/how_to/tools_prompting.ipynb +++ b/docs/core_docs/docs/how_to/tools_prompting.ipynb @@ -139,7 +139,13 @@ "source": [ "## Creating our prompt\n", "\n", - "We'll want to write a prompt that specifies the tools the model has access to, the arguments to those tools, and the desired output format of the model. In this case we'll instruct it to output a JSON blob of the form `{\"name\": \"...\", \"arguments\": {...}}`." + "We'll want to write a prompt that specifies the tools the model has access to, the arguments to those tools, and the desired output format of the model. In this case we'll instruct it to output a JSON blob of the form `{\"name\": \"...\", \"arguments\": {...}}`.\n", + "\n", + "```{=mdx}\n", + ":::tip\n", + "As of `langchain` version `0.2.8`, the `renderTextDescription` function now supports [OpenAI-formatted tools](https://api.js.langchain.com/interfaces/langchain_core_language_models_base.ToolDefinition.html).\n", + ":::\n", + "```" ] }, { diff --git a/langchain/package.json b/langchain/package.json index 9bd804d77d0c..f119b2b92fa0 100644 --- a/langchain/package.json +++ b/langchain/package.json @@ -888,7 +888,7 @@ } }, "dependencies": { - "@langchain/core": "~0.2.0", + "@langchain/core": ">=0.2.9 <0.3.0", "@langchain/openai": ">=0.1.0 <0.3.0", "@langchain/textsplitters": "~0.0.0", "binary-extensions": "^2.2.0", diff --git a/langchain/src/agents/openai_tools/index.ts b/langchain/src/agents/openai_tools/index.ts index 4e744d2930b5..ae071993224e 100644 --- a/langchain/src/agents/openai_tools/index.ts +++ b/langchain/src/agents/openai_tools/index.ts @@ -7,6 +7,7 @@ import { ChatPromptTemplate } from "@langchain/core/prompts"; import { RunnablePassthrough } from "@langchain/core/runnables"; import { OpenAIClient } from "@langchain/openai"; import { convertToOpenAITool } from "@langchain/core/utils/function_calling"; +import { ToolDefinition } from "@langchain/core/language_models/base"; import { formatToOpenAIToolMessages } from "../format_scratchpad/openai_tools.js"; import { OpenAIToolsAgentOutputParser, @@ -35,7 +36,7 @@ export type CreateOpenAIToolsAgentParams = { } >; /** Tools this agent has access to. */ - tools: StructuredToolInterface[]; + tools: StructuredToolInterface[] | ToolDefinition[]; /** The prompt to use, must have an input key of `agent_scratchpad`. */ prompt: ChatPromptTemplate; /** diff --git a/langchain/src/agents/structured_chat/index.ts b/langchain/src/agents/structured_chat/index.ts index e4a725d7b023..27b8972b7567 100644 --- a/langchain/src/agents/structured_chat/index.ts +++ b/langchain/src/agents/structured_chat/index.ts @@ -1,8 +1,10 @@ import { zodToJsonSchema, JsonSchema7ObjectType } from "zod-to-json-schema"; import type { StructuredToolInterface } from "@langchain/core/tools"; -import type { - BaseLanguageModel, - BaseLanguageModelInterface, +import { + isOpenAITool, + type BaseLanguageModel, + type BaseLanguageModelInterface, + type ToolDefinition, } from "@langchain/core/language_models/base"; import { RunnablePassthrough } from "@langchain/core/runnables"; import type { BasePromptTemplate } from "@langchain/core/prompts"; @@ -14,6 +16,7 @@ import { PromptTemplate, } from "@langchain/core/prompts"; import { AgentStep } from "@langchain/core/agents"; +import { isStructuredTool } from "@langchain/core/utils/function_calling"; import { LLMChain } from "../../chains/llm_chain.js"; import { Optional } from "../../types/type-utils.js"; import { @@ -239,7 +242,7 @@ export type CreateStructuredChatAgentParams = { /** LLM to use as the agent. */ llm: BaseLanguageModelInterface; /** Tools this agent has access to. */ - tools: StructuredToolInterface[]; + tools: (StructuredToolInterface | ToolDefinition)[]; /** * The prompt to use. Must have input keys for * `tools`, `tool_names`, and `agent_scratchpad`. @@ -324,7 +327,16 @@ export async function createStructuredChatAgent({ )}` ); } - const toolNames = tools.map((tool) => tool.name); + let toolNames: string[] = []; + if (tools.every(isOpenAITool)) { + toolNames = tools.map((tool) => tool.function.name); + } else if (tools.every(isStructuredTool)) { + toolNames = tools.map((tool) => tool.name); + } else { + throw new Error( + "All tools must be either OpenAI or Structured tools, not a mix." + ); + } const partialedPrompt = await prompt.partial({ tools: renderTextDescriptionAndArgs(tools), tool_names: toolNames.join(", "), diff --git a/langchain/src/agents/tool_calling/index.ts b/langchain/src/agents/tool_calling/index.ts index f0fe4b3f43aa..4d548d0cf536 100644 --- a/langchain/src/agents/tool_calling/index.ts +++ b/langchain/src/agents/tool_calling/index.ts @@ -2,6 +2,7 @@ import { BaseChatModel } from "@langchain/core/language_models/chat_models"; import { ChatPromptTemplate } from "@langchain/core/prompts"; import { StructuredToolInterface } from "@langchain/core/tools"; import { RunnablePassthrough } from "@langchain/core/runnables"; +import { ToolDefinition } from "@langchain/core/language_models/base"; import { AgentRunnableSequence } from "../agent.js"; import { ToolCallingAgentOutputParser, @@ -20,7 +21,7 @@ export type CreateToolCallingAgentParams = { */ llm: BaseChatModel; /** Tools this agent has access to. */ - tools: StructuredToolInterface[]; + tools: StructuredToolInterface[] | ToolDefinition[]; /** The prompt to use, must have an input key of `agent_scratchpad`. */ prompt: ChatPromptTemplate; /** diff --git a/langchain/src/tools/render.ts b/langchain/src/tools/render.ts index a668af1986a0..821c5b2208bd 100644 --- a/langchain/src/tools/render.ts +++ b/langchain/src/tools/render.ts @@ -1,5 +1,9 @@ import { zodToJsonSchema, JsonSchema7ObjectType } from "zod-to-json-schema"; import { StructuredToolInterface } from "@langchain/core/tools"; +import { + ToolDefinition, + isOpenAITool, +} from "@langchain/core/language_models/base"; /** * Render the tool name and description in plain text. @@ -13,9 +17,21 @@ import { StructuredToolInterface } from "@langchain/core/tools"; * @returns a string of all tools and their descriptions */ export function renderTextDescription( - tools: StructuredToolInterface[] + tools: StructuredToolInterface[] | ToolDefinition[] ): string { - return tools.map((tool) => `${tool.name}: ${tool.description}`).join("\n"); + if ((tools as unknown[]).every(isOpenAITool)) { + return (tools as ToolDefinition[]) + .map( + (tool) => + `${tool.function.name}${ + tool.function.description ? `: ${tool.function.description}` : "" + }` + ) + .join("\n"); + } + return (tools as StructuredToolInterface[]) + .map((tool) => `${tool.name}: ${tool.description}`) + .join("\n"); } /** @@ -30,9 +46,19 @@ export function renderTextDescription( * @returns a string of all tools, their descriptions and a stringified version of their schemas */ export function renderTextDescriptionAndArgs( - tools: StructuredToolInterface[] + tools: StructuredToolInterface[] | ToolDefinition[] ): string { - return tools + if ((tools as unknown[]).every(isOpenAITool)) { + return (tools as ToolDefinition[]) + .map( + (tool) => + `${tool.function.name}${ + tool.function.description ? `: ${tool.function.description}` : "" + }, args: ${JSON.stringify(tool.function.parameters)}` + ) + .join("\n"); + } + return (tools as StructuredToolInterface[]) .map( (tool) => `${tool.name}: ${tool.description}, args: ${JSON.stringify( diff --git a/yarn.lock b/yarn.lock index 3cb5ed84b03e..0d4c6f6d6594 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29532,7 +29532,7 @@ __metadata: "@gomomento/sdk-core": ^1.51.1 "@jest/globals": ^29.5.0 "@langchain/cohere": ^0.0.8 - "@langchain/core": ~0.2.0 + "@langchain/core": ">=0.2.9 <0.3.0" "@langchain/openai": ">=0.1.0 <0.3.0" "@langchain/scripts": ~0.0.14 "@langchain/textsplitters": ~0.0.0