diff --git a/sdk/ai/ai-projects/review/ai-projects.api.md b/sdk/ai/ai-projects/review/ai-projects.api.md index d926154bc015..6cadf2bc0bf1 100644 --- a/sdk/ai/ai-projects/review/ai-projects.api.md +++ b/sdk/ai/ai-projects/review/ai-projects.api.md @@ -540,9 +540,6 @@ export type Frequency = string; // @public export type FrequencyOutput = string; -// @public -export function fromConnectionId(toolType: connectionToolType, connectionIds: string[]): ToolDefinitionParent; - // @public export function fromFunctionDefinition(functionDefintion: FunctionDefinition): FunctionToolDefinition; @@ -1614,6 +1611,49 @@ export interface ToolResourcesOutput { file_search?: FileSearchToolResourceOutput; } +// @public +export class ToolSet { + addAzureAISearchTool(indexConnectionId: string, indexName: string): { + definition: AzureAISearchToolDefinition; + resources: ToolResources; + }; + addCodeInterpreterTool(fileIds?: string[], dataSources?: Array): { + definition: CodeInterpreterToolDefinition; + resources: ToolResources; + }; + addConnectionTool(toolType: connectionToolType, connectionIds: string[]): { + definition: ToolDefinition; + }; + addFileSearchTool(vectorStoreIds?: string[], vectorStores?: Array, definitionDetails?: FileSearchToolDefinitionDetails): { + definition: FileSearchToolDefinition; + resources: ToolResources; + }; + toolDefinitions: ToolDefinition[]; + toolResources: ToolResources; +} + +// @public +export class ToolUtility { + static createAzureAISearchTool(indexConnectionId: string, indexName: string): { + definition: AzureAISearchToolDefinition; + resources: ToolResources; + }; + static createCodeInterpreterTool(fileIds?: string[], dataSources?: Array): { + definition: CodeInterpreterToolDefinition; + resources: ToolResources; + }; + static createConnectionTool(toolType: connectionToolType, connectionIds: string[]): { + definition: ToolDefinition; + }; + static createFileSearchTool(vectorStoreIds?: string[], vectorStores?: Array, definitionDetails?: FileSearchToolDefinitionDetails): { + definition: FileSearchToolDefinition; + resources: ToolResources; + }; + static createFunctionTool(functionDefinition: FunctionDefinition): { + definition: FunctionToolDefinition; + }; +} + // @public export type Trigger = TriggerParent | RecurrenceTrigger | CronTrigger; diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_azure_ai_search.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_azure_ai_search.ts new file mode 100644 index 000000000000..eaaba05f45ab --- /dev/null +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_azure_ai_search.ts @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * + * FILE: agents_azure_ai_search.ts + * + * DESCRIPTION: + * This sample demonstrates how to use agent operations with the + * Azure AI Search tool from the Azure Agents service using a synchronous client. + * + * USAGE: + * npx ts-node agents_azure_ai_search.ts + * + * Before running the sample: + * + * npm install @azure/ai-projects @azure/identity @azure/core-util dotenv + * + * Set this environment variables with your own values: + * AZURE_AI_PROJECTS_CONNECTION_STRING - the Azure AI Project connection string, as found in your AI Studio Project + * AZURE_AI_SEARCH_CONNECTION_NAME - the name of the connection with Azure AI search, must be a CognitiveSearch connection + */ + +import { AIProjectsClient, MessageContentOutput, isOutputOfType, MessageTextContentOutput, ToolUtility } from "@azure/ai-projects" +import { delay } from "@azure/core-util"; +import { DefaultAzureCredential } from "@azure/identity"; + +import * as dotenv from "dotenv"; +dotenv.config(); + +const connectionString = process.env["AZURE_AI_PROJECTS_CONNECTION_STRING"] || ">;;;"; + +export async function main(): Promise { + // Create an Azure AI Client from a connection string, copied from your AI Studio project. + // At the moment, it should be in the format ";;;" + // Customer needs to login to Azure subscription via Azure CLI and set the environment variables + const client = AIProjectsClient.fromConnectionString(connectionString || "", new DefaultAzureCredential()); + const connectionName = process.env["AZURE_AI_SEARCH_CONNECTION_NAME"] || ""; + const connection = await client.connections.getConnection(connectionName); + + // Initialize Azure AI Search tool + const azureAISearchTool = ToolUtility.createAzureAISearchTool(connection.id, connection.name) + + // Create agent with the Azure AI search tool + const agent = await client.agents.createAgent( + "gpt-4-0125-preview", { + name: "my-agent", + instructions: "You are a helpful agent", + tools: [azureAISearchTool.definition], + tool_resources: azureAISearchTool.resources + }, { + headers: {"x-ms-enable-preview": "true"} + }); + console.log(`Created agent, agent ID : ${agent.id}`); + + // Create thread for communication + const thread = await client.agents.createThread() + console.log(`Created thread, thread ID: ${thread.id}`); + + // Create message to thread + const message = await client.agents.createMessage(thread.id, {role: "user", content: "Hello, send an email with the datetime and weather information in New York"}); + console.log(`Created message, message ID: ${message.id}`); + + // Create and process agent run in thread with tools + let run = await client.agents.createRun(thread.id, agent.id); + while (run.status === "queued" || run.status === "in_progress") { + await delay(1000); + run = await client.agents.getRun(thread.id, run.id); + } + if (run.status === "failed") { + console.log(`Run failed: ${run.last_error}`); + } + console.log(`Run finished with status: ${run.status}`); + + // Delete the assistant when done + client.agents.deleteAgent(agent.id) + console.log(`Deleted agent, agent ID: ${agent.id}`); + + // Fetch and log all messages + const messages = await client.agents.listMessages(thread.id) + console.log(`Messages:`); + const agentMessage: MessageContentOutput = messages.data[0].content[0]; + if (isOutputOfType(agentMessage, "text")) { + const textContent = agentMessage as MessageTextContentOutput; + console.log(`Text Message Content - ${textContent.text.value}`); + } +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding.ts index a50d6002996b..2b5578f8ec81 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding.ts @@ -7,7 +7,7 @@ * * DESCRIPTION: * This sample demonstrates how to use agent operations with the Grounding with Bing Search tool from - * the Azure Agents service using a asynchronous client. + * the Azure Agents service using a client. * * USAGE: * npx ts-node agents_bing_grounding.ts @@ -21,7 +21,7 @@ * BING_CONNECTION_NAME - the name of the connection with Bing search grounding */ -import { AIProjectsClient, fromConnectionId, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects" +import { AIProjectsClient, ToolUtility, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects" import { delay } from "@azure/core-util"; import { DefaultAzureCredential } from "@azure/identity"; @@ -39,18 +39,17 @@ export async function main(): Promise { const connectionId = bingConnection.id; // Initialize agent bing tool with the connection id - const bingTool = fromConnectionId(connectionToolType.BingGrounding, [connectionId]); + const bingTool = ToolUtility.createConnectionTool(connectionToolType.BingGrounding, [connectionId]); // Create agent with the bing tool and process assistant run const agent = await client.agents.createAgent( "gpt-4-0125-preview", { name: "my-agent", instructions: "You are a helpful agent", - tools: [bingTool] + tools: [bingTool.definition] }, { headers: {"x-ms-enable-preview": "true"} }); - console.log(connectionId) console.log(`Created agent, agent ID : ${agent.id}`); // Create thread for communication diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding_streaming.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding_streaming.ts index 29e445a57f46..74b545ad8051 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding_streaming.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_bing_grounding_streaming.ts @@ -8,7 +8,7 @@ * * DESCRIPTION: * This sample demonstrates how to use agent operations with the Grounding with Bing Search tool from - * the Azure Agents service using a asynchronous client and streaming. + * the Azure Agents service using a client and streaming. * * USAGE: * npx ts-node agents_bing_grounding_streaming.ts @@ -22,7 +22,7 @@ * BING_CONNECTION_NAME - the name of the connection with Bing search grounding */ -import { AIProjectsClient, DoneEvent, ErrorEvent, MessageDeltaChunk, MessageDeltaTextContent, MessageStreamEvent, RunStreamEvent, ThreadRunOutput, fromConnectionId, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects" +import { AIProjectsClient, DoneEvent, ErrorEvent, MessageDeltaChunk, MessageDeltaTextContent, MessageStreamEvent, RunStreamEvent, ThreadRunOutput, ToolUtility, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects" import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; @@ -35,17 +35,16 @@ export async function main(): Promise { const bingConnection = await client.connections.getConnection(process.env["BING_CONNECTION_NAME"] || ""); const connectionId = bingConnection.id; - const bingTool = fromConnectionId(connectionToolType.BingGrounding, [connectionId]); + const bingTool = ToolUtility.createConnectionTool(connectionToolType.BingGrounding, [connectionId]); const agent = await client.agents.createAgent( "gpt-4-0125-preview", { name: "my-agent", instructions: "You are a helpful agent", - tools: [bingTool] + tools: [bingTool.definition] }, { headers: {"x-ms-enable-preview": "true"} }); - console.log(connectionId) console.log(`Created agent, agent ID : ${agent.id}`); const thread = await client.agents.createThread() diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_fabric.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_fabric.ts index 7a578f5279ec..192852b5e687 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/agents_fabric.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_fabric.ts @@ -7,7 +7,7 @@ * * DESCRIPTION: * This sample demonstrates how to use agent operations with the Microsoft Fabric tool from - * the Azure Agents service using a asynchronous client. + * the Azure Agents service using a client. * * USAGE: * npx ts-node agents_fabric.ts @@ -21,7 +21,7 @@ * FABRIC_CONNECTION_NAME */ -import { AIProjectsClient, fromConnectionId, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects"; +import { AIProjectsClient, ToolUtility, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects"; import { delay } from "@azure/core-util"; import { DefaultAzureCredential } from "@azure/identity"; @@ -39,14 +39,14 @@ export async function main(): Promise { const connectionId = fabricConnection.id; // Initialize agent Microsoft Fabric tool with the connection id - const fabricTool = fromConnectionId(connectionToolType.MicrosoftFabric, [connectionId]); + const fabricTool = ToolUtility.createConnectionTool(connectionToolType.MicrosoftFabric, [connectionId]); // Create agent with the Microsoft Fabric tool and process assistant run const agent = await client.agents.createAgent( "gpt-4-0125-preview", { name: "my-agent", instructions: "You are a helpful agent", - tools: [fabricTool] + tools: [fabricTool.definition] }, { headers: {"x-ms-enable-preview": "true"} }); diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_function.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_function.ts index 272120e6e3dc..a37723b00e96 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/agents_function.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_function.ts @@ -5,7 +5,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unsafe-function-type */ -import { AIProjectsClient, FunctionDefinition, FunctionToolDefinition, FunctionToolDefinitionOutput, MessageContentOutput, MessageImageFileContentOutput, MessageTextContentOutput, RequiredToolCallOutput, SubmitToolOutputsActionOutput, ToolDefinition, ToolOutput, isOutputOfType } from "@azure/ai-projects" +import { AIProjectsClient, FunctionToolDefinition, FunctionToolDefinitionOutput, MessageContentOutput, MessageImageFileContentOutput, MessageTextContentOutput, RequiredToolCallOutput, SubmitToolOutputsActionOutput, ToolOutput, ToolUtility, isOutputOfType } from "@azure/ai-projects" import { delay } from "@azure/core-util"; import { DefaultAzureCredential } from "@azure/identity"; @@ -20,28 +20,30 @@ export async function main(): Promise { const agents = client.agents; class FunctionToolExecutor { - private functionTools: { func: Function, definition: FunctionDefinition }[]; + private functionTools: { func: Function, definition: FunctionToolDefinition }[]; constructor() { this.functionTools = [{ - func: this.getUserFavoriteCity, definition: { + func: this.getUserFavoriteCity, + ...ToolUtility.createFunctionTool({ name: "getUserFavoriteCity", description: "Gets the user's favorite city.", parameters: {} - } + }) }, { - func: this.getCityNickname, definition: { - name: "getCityNickname", - description: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.", - parameters: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g. Seattle, Wa" } } } - } - }, - { - func: this.getWeather, definition: { + func: this.getCityNickname, + ...ToolUtility.createFunctionTool({ + name: "getCityNickname", + description: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.", + parameters: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g. Seattle, Wa" } } } + }) + }, { + func: this.getWeather, + ...ToolUtility.createFunctionTool({ name: "getWeather", description: "Gets the weather for a location.", parameters: { type: "object", properties: { location: { type: "string", description: "The city and state, e.g. Seattle, Wa" }, unit: { type: "string", enum: ['c', 'f'] } } } - } + }) }]; } @@ -73,7 +75,7 @@ export async function main(): Promise { return undefined; } } - const result = this.functionTools.find((tool) => tool.definition.name === toolCall.function.name)?.func(...args); + const result = this.functionTools.find((tool) => tool.definition.function.name === toolCall.function.name)?.func(...args); return result ? { tool_call_id: toolCall.id, output: JSON.stringify(result) @@ -81,7 +83,7 @@ export async function main(): Promise { } public getFunctionDefinitions(): FunctionToolDefinition[] { - return this.functionTools.map(tool => {return { type: "function", function: tool.definition}}); + return this.functionTools.map(tool => {return tool.definition}); } } diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_sharepoint.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_sharepoint.ts index 264245fa4595..0d7f517cf2c7 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/agents_sharepoint.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_sharepoint.ts @@ -7,7 +7,7 @@ * * DESCRIPTION: * This sample demonstrates how to use agent operations with the Sharepoint tool from - * the Azure Agents service using a asynchronous client. + * the Azure Agents service using a client. * * USAGE: * npx ts-node agents_sharepoint.ts @@ -21,7 +21,7 @@ * SHAREPOINT_CONNECTION_NAME */ -import { AIProjectsClient, fromConnectionId, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects"; +import { AIProjectsClient, ToolUtility, connectionToolType, MessageContentOutput, isOutputOfType, MessageTextContentOutput } from "@azure/ai-projects"; import { delay } from "@azure/core-util"; import { DefaultAzureCredential } from "@azure/identity"; @@ -39,14 +39,14 @@ export async function main(): Promise { const connectionId = sharepointConnection.id; // Initialize agent Sharepoint tool with the connection id - const sharepointTool = fromConnectionId(connectionToolType.SharepointGrounding, [connectionId]); + const sharepointTool = ToolUtility.createConnectionTool(connectionToolType.SharepointGrounding, [connectionId]); // Create agent with the Sharepoint tool and process assistant run const agent = await client.agents.createAgent( "gpt-4-0125-preview", { name: "my-agent", instructions: "You are a helpful agent", - tools: [sharepointTool] + tools: [sharepointTool.definition] }, { headers: {"x-ms-enable-preview": "true"} }); diff --git a/sdk/ai/ai-projects/samples-dev/agents/agents_toolset.ts b/sdk/ai/ai-projects/samples-dev/agents/agents_toolset.ts new file mode 100644 index 000000000000..1c3457763f08 --- /dev/null +++ b/sdk/ai/ai-projects/samples-dev/agents/agents_toolset.ts @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { AIProjectsClient, ToolSet } from "@azure/ai-projects"; +import { DefaultAzureCredential } from "@azure/identity"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; + +dotenv.config(); + +const connectionString = process.env["AZURE_AI_PROJECTS_CONNECTION_STRING"] || ">;;;"; + +export async function main(): Promise { + const client = AIProjectsClient.fromConnectionString(connectionString || "", new DefaultAzureCredential()); + + // Upload file for code interpreter tool + const fileStream1 = fs.createReadStream("samples-dev/agents/nifty_500_quarterly_results.csv"); + const codeInterpreterFile = await client.agents.uploadFile(fileStream1, "assistants", "my-local-file"); + + console.log(`Uploaded local file, file ID : ${codeInterpreterFile.id}`); + + // Upload file for file search tool + const fileStream2 = fs.createReadStream("./samples-dev/agents/sample_file_for_upload.txt"); + const fileSearchFile = await client.agents.uploadFile(fileStream2, "assistants", "sample_file_for_upload.txt"); + console.log(`Uploaded file, ID: ${fileSearchFile.id}`); + + // Create vector store for file search tool + const vectorStore = await client.agents.createVectorStoreAndPoll({file_ids: [fileSearchFile.id]}); + + // Create tool set + const toolSet = new ToolSet(); + toolSet.addFileSearchTool([vectorStore.id]); + toolSet.addCodeInterpreterTool([codeInterpreterFile.id]); + + // Create agent with tool set + const agent = await client.agents.createAgent("gpt-4o", { + name: "my-agent", + instructions: "You are a helpful agent", + tools: toolSet.toolDefinitions, + tool_resources: toolSet.toolResources + }); + console.log(`Created agent, agent ID: ${agent.id}`); + + // Create threads, messages, and runs to interact with agent as desired + + // Delete agent + await client.agents.deleteAgent(agent.id); + console.log(`Deleted agent, agent ID: ${agent.id}`); +} + +main().catch((err) => { + console.error("The sample encountered an error:", err); +}); diff --git a/sdk/ai/ai-projects/samples-dev/agents/code_interpreter.ts b/sdk/ai/ai-projects/samples-dev/agents/code_interpreter.ts index 15337d84cb5b..6a26c3761d2a 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/code_interpreter.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/code_interpreter.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import {AIProjectsClient, isOutputOfType, CodeInterpreterToolDefinition, MessageTextContentOutput, ToolResources, MessageImageFileContentOutput, MessageContentOutput } from "@azure/ai-projects" +import {AIProjectsClient, isOutputOfType, MessageTextContentOutput, MessageImageFileContentOutput, ToolUtility } from "@azure/ai-projects" import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; @@ -19,12 +19,15 @@ const localFile = await client.agents.uploadFile(localFileStream, "assistants", console.log(`Uploaded local file, file ID : ${localFile.id}`); +// Create code interpreter tool +const codeInterpreterTool = ToolUtility.createCodeInterpreterTool([localFile.id]); + // Notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment const agent = await client.agents.createAgent("gpt-4o-mini", { name: "my-agent", instructions: "You are a helpful agent", - tools: [{type: "code_interpreter"} as CodeInterpreterToolDefinition], - tool_resources: { code_interpreter: {file_ids: [localFile.id]} } as ToolResources + tools: [codeInterpreterTool.definition], + tool_resources: codeInterpreterTool.resources, }); console.log(`Created agent, agent ID: ${agent.id}`); diff --git a/sdk/ai/ai-projects/samples-dev/agents/code_interpreter_streaming.ts b/sdk/ai/ai-projects/samples-dev/agents/code_interpreter_streaming.ts index 597afac77b10..2149f7272440 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/code_interpreter_streaming.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/code_interpreter_streaming.ts @@ -1,13 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import {AIProjectsClient, isOutputOfType, CodeInterpreterToolDefinition, MessageTextContentOutput, ToolResources, MessageImageFileContentOutput, MessageContentOutput, RunStreamEvent, MessageStreamEvent, ThreadRunOutput, MessageDeltaChunk, MessageDeltaTextContent, ErrorEvent, DoneEvent } from "@azure/ai-projects" +import {AIProjectsClient, isOutputOfType, ToolUtility, MessageTextContentOutput, MessageImageFileContentOutput, RunStreamEvent, MessageStreamEvent, ThreadRunOutput, MessageDeltaChunk, MessageDeltaTextContent, ErrorEvent, DoneEvent } from "@azure/ai-projects" import { DefaultAzureCredential } from "@azure/identity"; import * as dotenv from "dotenv"; dotenv.config(); import * as fs from "fs"; -import { Readable } from "stream"; const connectionString = process.env["AZURE_AI_PROJECTS_CONNECTION_STRING"] || ">;;;"; @@ -20,12 +19,15 @@ export async function main(): Promise { console.log(`Uploaded local file, file ID : ${localFile.id}`); + // Create code interpreter tool + const codeInterpreterTool = ToolUtility.createCodeInterpreterTool([localFile.id]); + // Notice that CodeInterpreter must be enabled in the agent creation, otherwise the agent will not be able to see the file attachment const agent = await client.agents.createAgent("gpt-4o-mini", { name: "my-agent", instructions: "You are a helpful agent", - tools: [{type: "code_interpreter"} as CodeInterpreterToolDefinition], - tool_resources: { code_interpreter: {file_ids: [localFile.id]} } as ToolResources + tools: [codeInterpreterTool.definition], + tool_resources: codeInterpreterTool.resources, }); console.log(`Created agent, agent ID: ${agent.id}`); diff --git a/sdk/ai/ai-projects/samples-dev/agents/file_search.ts b/sdk/ai/ai-projects/samples-dev/agents/file_search.ts index 6a2a79c9dede..f0f08e32c6ba 100644 --- a/sdk/ai/ai-projects/samples-dev/agents/file_search.ts +++ b/sdk/ai/ai-projects/samples-dev/agents/file_search.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { AIProjectsClient, isOutputOfType, MessageContentOutput, MessageImageFileContentOutput, MessageTextContentOutput } from "@azure/ai-projects"; +import { AIProjectsClient, ToolUtility, isOutputOfType, MessageContentOutput, MessageImageFileContentOutput, MessageTextContentOutput } from "@azure/ai-projects"; import { delay } from "@azure/core-util"; import { DefaultAzureCredential } from "@azure/identity"; @@ -23,14 +23,17 @@ export async function main(): Promise { const vectorStore = await client.agents.createVectorStore({ file_ids: [file.id], name: "my_vector_store" }); console.log(`Created vector store, ID: ${vectorStore.id}`); - // Create agent with files + // Create file search tool + const fileSearchTool = ToolUtility.createFileSearchTool([vectorStore.id]); + + // Create agent with tool const agent = await client.agents.createAgent( "gpt-4o", { name:"SDK Test Agent - Retrieval", instructions:"You are helpful agent that can help fetch data from files you know about.", - tools: [{type: "file_search" }], - tool_resources: {file_search: {vector_store_ids: [vectorStore.id]} } + tools: [fileSearchTool.definition], + tool_resources: fileSearchTool.resources } ); console.log(`Created agent, agent ID : ${agent.id}`); diff --git a/sdk/ai/ai-projects/src/agents/utils.ts b/sdk/ai/ai-projects/src/agents/utils.ts index d9105a9c1553..241539a8c8c7 100644 --- a/sdk/ai/ai-projects/src/agents/utils.ts +++ b/sdk/ai/ai-projects/src/agents/utils.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { FunctionDefinition, FunctionToolDefinition, RequiredActionOutput, RequiredToolCallOutput, ToolDefinitionOutputParent, ToolDefinitionParent } from "./inputOutputs.js"; +import { AzureAISearchToolDefinition, CodeInterpreterToolDefinition, FileSearchToolDefinition, FileSearchToolDefinitionDetails, FunctionDefinition, FunctionToolDefinition, RequiredActionOutput, RequiredToolCallOutput, ToolDefinition, ToolDefinitionOutputParent, ToolResources, VectorStoreConfigurations, VectorStoreDataSource } from "./inputOutputs.js"; /** @@ -40,17 +40,189 @@ export enum connectionToolType { } /** - * Creates a tool definition for a connection tool with the given connection ids. - * - * @param toolType - The type of the connection tool. - * @param connectionIds - A list of the IDs of the connections to use. - * @returns The function tool definition. + * Utility class for creating various tools. */ -export function fromConnectionId(toolType : connectionToolType, connectionIds: string[]) : ToolDefinitionParent { - return { - type: toolType, - [toolType]: { - connections: connectionIds.map(connectionId => ({connection_id: connectionId})) +export class ToolUtility { + /** + * Creates a connection tool + * + * @param toolType - The type of the connection tool. + * @param connectionIds - A list of the IDs of the connections to use. + * @returns An object containing the definition for the connection tool + */ + static createConnectionTool( + toolType: connectionToolType, + connectionIds: string[] + ): { definition: ToolDefinition } { + return { + definition: { + type: toolType, + [toolType]: { + connections: connectionIds.map(connectionId => ({ connection_id: connectionId })) + } + } + }; + } + + /** + * Creates a file search tool + * + * @param vectorStoreIds - The ID of the vector store attached to this agent. There can be a maximum of 1 vector store attached to the agent. + * @param vectorStores - The list of vector store configuration objects from Azure. This list is limited to one element. The only element of this list contains the list of azure asset IDs used by the search tool. + * @param definitionDetails - The input definition information for a file search tool as used to configure an agent. + * + * @returns An object containing the definition and resources for the file search tool + */ + static createFileSearchTool( + vectorStoreIds?: string[], + vectorStores?: Array, + definitionDetails?: FileSearchToolDefinitionDetails + ): { definition: FileSearchToolDefinition, resources: ToolResources } { + return { + definition: { type: "file_search", file_search: definitionDetails }, + resources: { file_search: { vector_store_ids: vectorStoreIds, vector_stores: vectorStores } } + }; + } + + /** + * Creates a code interpreter tool + * + * @param fileIds - A list of file IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. + * @param dataSources - The data sources to be used. This option is mutually exclusive with fileIds. + * + * @returns An object containing the definition and resources for the code interpreter tool. + */ + static createCodeInterpreterTool( + fileIds?: string[], + dataSources?: Array + ): { definition: CodeInterpreterToolDefinition, resources: ToolResources } { + if (fileIds && dataSources) { + throw new Error("Cannot specify both fileIds and dataSources"); } + + return { + definition: { type: "code_interpreter" }, + resources: { code_interpreter: { file_ids: fileIds, data_sources: dataSources } } + }; + } + + /** + * Creates an Azure AI search tool + * + * @param indexConnectionId - The connection ID of the Azure AI search index. + * @param indexName - The name of the Azure AI search index. + * + * @returns An object containing the definition and resources for the Azure AI search tool. + */ + static createAzureAISearchTool( + indexConnectionId: string, + indexName: string + ): { definition: AzureAISearchToolDefinition, resources: ToolResources } { + return { + definition: { type: "azure_ai_search" }, + resources: { azure_ai_search: { indexes: [{ index_connection_id: indexConnectionId, index_name: indexName }] } } + }; + } + + /** + * Creates a function tool + * + * @param functionDefinition - The function definition to use. + * + * @returns An object containing the definition for the function tool. + */ + static createFunctionTool( + functionDefinition: FunctionDefinition + ): { definition: FunctionToolDefinition } { + return { + definition: { + type: "function", + function: functionDefinition + } + }; + } +} + +/** + * Represents a set of tools with their definitions and resources. + */ +export class ToolSet { + /** A list of tool definitions that have been added to the tool set. */ + toolDefinitions: ToolDefinition[] = []; + + /** A collection of resources associated with the tools in the tool set. */ + toolResources: ToolResources = {}; + + /** + * Adds a connection tool to the tool set. + * + * @param toolType - The type of the connection tool. + * @param connectionIds - A list of the IDs of the connections to use. + * + * @returns An object containing the definition for the connection tool + */ + addConnectionTool( + toolType: connectionToolType, + connectionIds: string[] + ) : { definition: ToolDefinition } { + const tool = ToolUtility.createConnectionTool(toolType, connectionIds); + this.toolDefinitions.push(tool.definition); + return tool; + } + + /** + * Adds a file search tool to the tool set. + * + * @param vectorStoreIds - The ID of the vector store attached to this agent. There can be a maximum of 1 vector store attached to the agent. + * @param vectorStores - The list of vector store configuration objects from Azure. This list is limited to one element. The only element of this list contains the list of azure asset IDs used by the search tool. + * @param definitionDetails - The input definition information for a file search tool as used to configure an agent. + * + * @returns An object containing the definition and resources for the file search tool + */ + addFileSearchTool( + vectorStoreIds?: string[], + vectorStores?: Array, + definitionDetails?: FileSearchToolDefinitionDetails + ) : { definition: FileSearchToolDefinition, resources: ToolResources } { + const tool = ToolUtility.createFileSearchTool(vectorStoreIds, vectorStores, definitionDetails); + this.toolDefinitions.push(tool.definition); + this.toolResources = { ...this.toolResources, ...tool.resources }; + return tool; + } + + /** + * Adds a code interpreter tool to the tool set. + * + * @param fileIds - A list of file IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files associated with the tool. + * @param dataSources - The data sources to be used. This option is mutually exclusive with fileIds. + * + * @returns An object containing the definition and resources for the code interpreter tool + */ + addCodeInterpreterTool( + fileIds?: string[], + dataSources?: Array + ) : { definition: CodeInterpreterToolDefinition, resources: ToolResources } { + const tool = ToolUtility.createCodeInterpreterTool(fileIds, dataSources); + this.toolDefinitions.push(tool.definition); + this.toolResources = { ...this.toolResources, ...tool.resources }; + return tool; + } + + /** + * Adds an Azure AI search tool to the tool set. + * + * @param indexConnectionId - The connection ID of the Azure AI search index. + * @param indexName - The name of the Azure AI search index. + * + * @returns An object containing the definition and resources for the Azure AI search tool + */ + addAzureAISearchTool( + indexConnectionId: string, + indexName: string + ) : { definition: AzureAISearchToolDefinition, resources: ToolResources } { + const tool = ToolUtility.createAzureAISearchTool(indexConnectionId, indexName); + this.toolDefinitions.push(tool.definition); + this.toolResources = { ...this.toolResources, ...tool.resources }; + return tool; } }