From 0c2a583df89164b5ffa7e1d80ca3df81e3e06d0d Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Tue, 5 Nov 2024 11:24:26 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20refactor:=20Optimize=20Agent=20T?= =?UTF-8?q?ool=20Loading=20and=20Fix=20Bedrock=20Tool=20Handling=20(#4641)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: bedrock tool name regex * fix: pass args as single input, attempt json first. * refactor: remove toolMap from agent tool load as is not used * fix: update formatAgentMessages test to use strictEqual for args comparison, testing new behavior --- api/app/clients/prompts/formatAgentMessages.spec.js | 2 +- api/app/clients/prompts/formatMessages.js | 7 +++++-- api/server/controllers/agents/client.js | 1 - api/server/controllers/agents/run.js | 3 --- api/server/services/ActionService.js | 5 ++--- api/server/services/Endpoints/agents/initialize.js | 3 +-- api/server/services/Endpoints/bedrock/initialize.js | 1 - api/server/services/ToolService.js | 6 ++---- api/typedefs.js | 1 - 9 files changed, 11 insertions(+), 18 deletions(-) diff --git a/api/app/clients/prompts/formatAgentMessages.spec.js b/api/app/clients/prompts/formatAgentMessages.spec.js index fe0f1e0228..17b8fda7e0 100644 --- a/api/app/clients/prompts/formatAgentMessages.spec.js +++ b/api/app/clients/prompts/formatAgentMessages.spec.js @@ -120,7 +120,7 @@ describe('formatAgentMessages', () => { ]; const result = formatAgentMessages(payload); expect(result).toHaveLength(2); - expect(result[0].tool_calls[0].args).toBe('non-json-string'); + expect(result[0].tool_calls[0].args).toStrictEqual({ input: 'non-json-string' }); }); it('should handle complex tool calls with multiple steps', () => { diff --git a/api/app/clients/prompts/formatMessages.js b/api/app/clients/prompts/formatMessages.js index c9839102d3..8a0dc97ea9 100644 --- a/api/app/clients/prompts/formatMessages.js +++ b/api/app/clients/prompts/formatMessages.js @@ -189,10 +189,13 @@ const formatAgentMessages = (payload) => { // TODO: investigate; args as dictionary may need to be provider-or-tool-specific let args = _args; try { - args = JSON.parse(args); + args = JSON.parse(_args); } catch (e) { - // failed to parse, leave as is + if (typeof _args === 'string') { + args = { input: _args }; + } } + tool_call.args = args; lastAIMessage.tool_calls.push(tool_call); diff --git a/api/server/controllers/agents/client.js b/api/server/controllers/agents/client.js index c7f832db1e..277d545baa 100644 --- a/api/server/controllers/agents/client.js +++ b/api/server/controllers/agents/client.js @@ -461,7 +461,6 @@ class AgentClient extends BaseClient { req: this.options.req, agent: this.options.agent, tools: this.options.tools, - toolMap: this.options.toolMap, runId: this.responseMessageId, modelOptions: this.modelOptions, customHandlers: this.options.eventHandlers, diff --git a/api/server/controllers/agents/run.js b/api/server/controllers/agents/run.js index 241d224730..56cc46d5b3 100644 --- a/api/server/controllers/agents/run.js +++ b/api/server/controllers/agents/run.js @@ -18,7 +18,6 @@ const { providerEndpointMap } = require('librechat-data-provider'); * @param {string | undefined} [options.runId] - Optional run ID; otherwise, a new run ID will be generated. * @param {Agent} options.agent - The agent for this run. * @param {StructuredTool[] | undefined} [options.tools] - The tools to use in the run. - * @param {Record | undefined} [options.toolMap] - The tool map for the run. * @param {Record | undefined} [options.customHandlers] - Custom event handlers. * @param {ClientOptions} [options.modelOptions] - Optional model to use; if not provided, it will use the default from modelMap. * @param {boolean} [options.streaming=true] - Whether to use streaming. @@ -29,7 +28,6 @@ async function createRun({ runId, tools, agent, - toolMap, modelOptions, customHandlers, streaming = true, @@ -47,7 +45,6 @@ async function createRun({ const graphConfig = { tools, - toolMap, llmConfig, instructions: agent.instructions, additional_instructions: agent.additional_instructions, diff --git a/api/server/services/ActionService.js b/api/server/services/ActionService.js index 6bca75b989..ea1bcc4d23 100644 --- a/api/server/services/ActionService.js +++ b/api/server/services/ActionService.js @@ -14,6 +14,7 @@ const { getLogStores } = require('~/cache'); const { logger } = require('~/config'); const toolNameRegex = /^[a-zA-Z0-9_-]+$/; +const replaceSeparatorRegex = new RegExp(actionDomainSeparator, 'g'); /** * Validates tool name against regex pattern and updates if necessary. @@ -83,8 +84,6 @@ async function domainParser(req, domain, inverse = false) { return key; } - const replaceSeparatorRegex = new RegExp(actionDomainSeparator, 'g'); - if (!cachedDomain) { return domain.replace(replaceSeparatorRegex, '.'); } @@ -156,7 +155,7 @@ async function createActionTool({ action, requestBuilder, zodSchema, name, descr if (name) { return tool(_call, { - name, + name: name.replace(replaceSeparatorRegex, '_'), description: description || '', schema: zodSchema, }); diff --git a/api/server/services/Endpoints/agents/initialize.js b/api/server/services/Endpoints/agents/initialize.js index 93bb837695..796f69e4ac 100644 --- a/api/server/services/Endpoints/agents/initialize.js +++ b/api/server/services/Endpoints/agents/initialize.js @@ -54,7 +54,7 @@ const initializeClient = async ({ req, res, endpointOption }) => { throw new Error('Agent not found'); } - const { tools, toolMap } = await loadAgentTools({ + const { tools } = await loadAgentTools({ req, tools: agent.tools, agent_id: agent.id, @@ -100,7 +100,6 @@ const initializeClient = async ({ req, res, endpointOption }) => { agent, tools, sender, - toolMap, contentParts, modelOptions, eventHandlers, diff --git a/api/server/services/Endpoints/bedrock/initialize.js b/api/server/services/Endpoints/bedrock/initialize.js index 4a7e98a4ad..00630c41e6 100644 --- a/api/server/services/Endpoints/bedrock/initialize.js +++ b/api/server/services/Endpoints/bedrock/initialize.js @@ -60,7 +60,6 @@ const initializeClient = async ({ req, res, endpointOption }) => { agent, sender, // tools, - // toolMap, modelOptions, contentParts, eventHandlers, diff --git a/api/server/services/ToolService.js b/api/server/services/ToolService.js index 778b29ff06..9fa012191b 100644 --- a/api/server/services/ToolService.js +++ b/api/server/services/ToolService.js @@ -373,14 +373,14 @@ async function processRequiredActions(client, requiredActions) { } /** - * Processes the runtime tool calls and returns a combined toolMap. + * Processes the runtime tool calls and returns the tool classes. * @param {Object} params - Run params containing user and request information. * @param {ServerRequest} params.req - The request object. * @param {string} params.agent_id - The agent ID. * @param {Agent['tools']} params.tools - The agent's available tools. * @param {Agent['tool_resources']} params.tool_resources - The agent's available tool resources. * @param {string | undefined} [params.openAIApiKey] - The OpenAI API key. - * @returns {Promise<{ tools?: StructuredTool[]; toolMap?: Record}>} The combined toolMap. + * @returns {Promise<{ tools?: StructuredTool[] }>} The agent tools. */ async function loadAgentTools({ req, agent_id, tools, tool_resources, openAIApiKey }) { if (!tools || tools.length === 0) { @@ -482,10 +482,8 @@ async function loadAgentTools({ req, agent_id, tools, tool_resources, openAIApiK throw new Error('No tools found for the specified tool calls.'); } - const toolMap = { ...ToolMap, ...ActionToolMap }; return { tools: agentTools, - toolMap, }; } diff --git a/api/typedefs.js b/api/typedefs.js index 371fe94447..8c1af11a69 100644 --- a/api/typedefs.js +++ b/api/typedefs.js @@ -958,7 +958,6 @@ * @property {Object} [headers] - Additional headers for requests * @property {string} [proxy] - Proxy configuration * @property {Object} [tools] - Available tools for the agent - * @property {Object} [toolMap] - Mapping of tool configurations * @property {Object} [eventHandlers] - Custom event handlers * @property {Object} [addParams] - Additional parameters to add to requests * @property {string[]} [dropParams] - Parameters to remove from requests