Bibliothèque de client Azure AI Projects pour JavaScript - version 1.0.0-beta.2
Utilisez la bibliothèque cliente AI Projects (en préversion) pour :
- Énumérer les connexions dans votre projet Azure AI Foundry et obtenir les propriétés de connexion. Par exemple, obtenez l’URL du point de terminaison d’inférence et les informations d’identification associées à votre connexion Azure OpenAI.
- Développer des agents à l’aide du service Azure AI Agent, en tirant parti d’un vaste écosystème de modèles, d’outils et de fonctionnalités d’OpenAI, de Microsoft et d’autres fournisseurs LLM. Le service d’agent Azure AI permet de créer des agents pour un large éventail de cas d’utilisation de l’IA générative. Le package est actuellement en préversion privée.
- Activer le suivi OpenTelemetry.
Table des matières
- prise en main
- concepts clés
- exemples de
- Énumérer les connexions
-
Agents (préversion)
-
créer un agent avec :
- de recherche de fichiers
- interpréteur de code
- de mise au sol Bing
- Recherche Azure AI
- d’appel de fonction
- Créer un de thread avec
- Créer un message avec :
- exécuter, créer un thread et une exécution ou stream
- Récupérer le message
- Récupérer le de fichier
- Démontez en supprimant les de ressources
- suivi
-
créer un agent avec :
- suivi
- résolution des problèmes
- contribution
Commencer
Prérequis
- versions LTS de Node.js
- Un abonnement Azure .
- Un projet dans Azure AI Foundry.
- Chaîne de connexion du projet. Il se trouve dans la page de présentation de votre projet Azure AI Foundry, sous « Détails du projet ». Ci-dessous, nous partons du principe que la variable d’environnement
AZURE_AI_PROJECTS_CONNECTION_STRING
a été définie pour contenir cette valeur. - L’ID Entra est nécessaire pour authentifier le client. Votre application a besoin d’un objet qui implémente l’interface TokenCredential. Les exemples de code ici utilisent DefaultAzureCredential. Pour travailler, vous aurez besoin des éléments suivants :
- Rôle
Contributor
. Le rôle attribué peut être effectué via l’onglet « Contrôle d’accès (IAM) » de votre ressource Azure AI Project dans le portail Azure. - azure CLI installé.
- Vous êtes connecté à votre compte Azure en exécutant
az login
. - Notez que si vous avez plusieurs abonnements Azure, l’abonnement qui contient votre ressource Azure AI Project doit être votre abonnement par défaut. Exécutez
az account list --output table
pour répertorier l’ensemble de votre abonnement et voir lequel est la valeur par défaut. Exécutezaz account set --subscription "Your Subscription ID or Name"
pour modifier votre abonnement par défaut.
- Rôle
Installer le package
npm install @azure/ai-projects
Concepts clés
Créer et authentifier le client
La méthode de fabrique de classes fromConnectionString
est utilisée pour construire le client. Pour construire un client :
import { AIProjectsClient } from "@azure/ai-projects";
import { DefaultAzureCredential } from "@azure/identity";
import "dotenv/config";
const connectionString = process.env["AZURE_AI_PROJECTS_CONNECTION_STRING"] || "<connectionString>";
const client = AIProjectsClient.fromConnectionString(
connectionString,
new DefaultAzureCredential(),
);
Exemples
Énumérer les connexions
Votre projet Azure AI Foundry dispose d’un « Centre de gestion ». Lorsque vous y entrez, vous verrez un onglet nommé « Ressources connectées » sous votre projet. Les opérations .connections
sur le client vous permettent d’énumérer les connexions et d’obtenir les propriétés de connexion. Les propriétés de connexion incluent l’URL de ressource et les informations d’identification d’authentification, entre autres.
Vous trouverez ci-dessous des exemples de code des opérations de connexion. Vous trouverez des exemples complets sous le dossier « connexions » dans les [exemples de package][samples].
Obtenir les propriétés de toutes les connexions
Pour répertorier les propriétés de toutes les connexions dans le projet Azure AI Foundry :
const connections = await client.connections.listConnections();
for (const connection of connections) {
console.log(connection);
}
Obtenir les propriétés de toutes les connexions d’un type particulier
Pour répertorier les propriétés des connexions d’un certain type (ici Azure OpenAI) :
const connections = await client.connections.listConnections({ category: "AzureOpenAI" });
for (const connection of connections) {
console.log(connection);
}
Obtenir les propriétés d’une connexion par son nom de connexion
Pour obtenir les propriétés de connexion d’une connexion nommée connectionName
:
const connection = await client.connections.getConnection("connectionName");
console.log(connection);
Pour obtenir les propriétés de connexion avec ses informations d’identification d’authentification :
const connection = await client.connections.getConnectionWithSecrets("connectionName");
console.log(connection);
Agents (préversion)
Les agents de la bibliothèque cliente Azure AI Projects sont conçus pour faciliter diverses interactions et opérations au sein de vos projets IA. Ils servent de composants principaux qui gèrent et exécutent des tâches, en tirant parti de différents outils et ressources pour atteindre des objectifs spécifiques. Les étapes suivantes décrivent la séquence classique d’interaction avec les agents. Consultez le dossier « agents » dans les [exemples de package][exemples] pour obtenir d’autres exemples d’agent.
Les agents sont activement développés. Un formulaire d’inscription pour la préversion privée sera bientôt disponible.
Créer un agent
Voici un exemple de création d’un agent :
const agent = await client.agents.createAgent("gpt-4o", {
name: "my-agent",
instructions: "You are a helpful assistant",
});
Pour autoriser les agents à accéder à vos ressources ou fonctions personnalisées, vous avez besoin d’outils. Vous pouvez transmettre des outils pour createAgent
par le biais des arguments tools
et toolResources
.
Vous pouvez utiliser ToolSet
pour ce faire :
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,
toolResources: toolSet.toolResources,
});
console.log(`Created agent, agent ID: ${agent.id}`);
Créer un agent avec la recherche de fichiers
Pour effectuer une recherche de fichiers par un agent, nous devons d’abord charger un fichier, créer un magasin de vecteurs et associer le fichier au magasin vectoriel. Voici un exemple :
const localFileStream = fs.createReadStream("sample_file_for_upload.txt");
const file = await client.agents.uploadFile(localFileStream, "assistants", {
fileName: "sample_file_for_upload.txt",
});
console.log(`Uploaded file, ID: ${file.id}`);
const vectorStore = await client.agents.createVectorStore({
fileIds: [file.id],
name: "my_vector_store",
});
console.log(`Created vector store, ID: ${vectorStore.id}`);
const fileSearchTool = ToolUtility.createFileSearchTool([vectorStore.id]);
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: [fileSearchTool.definition],
toolResources: fileSearchTool.resources,
});
console.log(`Created agent, agent ID : ${agent.id}`);
Créer un agent avec l’interpréteur de code
Voici un exemple pour charger un fichier et l’utiliser pour l’interpréteur de code par un agent :
const fileStream = fs.createReadStream("nifty_500_quarterly_results.csv");
const fFile = await client.agents.uploadFile(fileStream, "assistants", {
fileName: "nifty_500_quarterly_results.csv",
});
console.log(`Uploaded local file, file ID : ${file.id}`);
const codeInterpreterTool = ToolUtility.createCodeInterpreterTool([file.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: [codeInterpreterTool.definition],
toolResources: codeInterpreterTool.resources,
});
console.log(`Created agent, agent ID: ${agent.id}`);
Créer un agent avec Bing Grounding
Pour permettre à votre agent d’effectuer une recherche via l’API recherche Bing, vous utilisez ToolUtility.createConnectionTool()
avec une connexion.
Voici un exemple :
const bingGroundingConnectionId = "<bingGroundingConnectionId>";
const bingTool = ToolUtility.createConnectionTool(connectionToolType.BingGrounding, [
bingGroundingConnectionId,
]);
const agent = await client.agents.createAgent("gpt-4-0125-preview", {
name: "my-agent",
instructions: "You are a helpful agent",
tools: [bingTool.definition],
});
console.log(`Created agent, agent ID : ${agent.id}`);
Créer un agent à l’aide d’Azure AI Search
Azure AI Search est un système de recherche d’entreprise pour les applications hautes performances. Il s’intègre à Azure OpenAI Service et Azure Machine Learning, offrant des technologies de recherche avancées telles que la recherche vectorielle et la recherche en texte intégral. Idéal pour les insights de base de connaissances, la découverte des informations et l’automatisation
Voici un exemple d’intégration d’Azure AI Search :
const cognitiveServicesConnectionName = "<cognitiveServicesConnectionName>";
const cognitiveServicesConnection = await client.connections.getConnection(
cognitiveServicesConnectionName,
);
const azureAISearchTool = ToolUtility.createAzureAISearchTool(
cognitiveServicesConnection.id,
cognitiveServicesConnection.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],
toolResources: azureAISearchTool.resources,
});
console.log(`Created agent, agent ID : ${agent.id}`);
Créer un agent avec l’appel de fonction
Vous pouvez améliorer vos agents en définissant des fonctions de rappel en tant qu’outils de fonction. Ceux-ci peuvent être fournis à createAgent
via la combinaison de tools
et de toolResources
. Seules les définitions et descriptions des fonctions sont fournies à createAgent
, sans les implémentations. Le Run
ou event handler of stream
déclenche un état de requires_action
en fonction des définitions de fonction. Votre code doit gérer cet état et appeler les fonctions appropriées.
Voici un exemple :
class FunctionToolExecutor {
private functionTools: { func: Function, definition: FunctionToolDefinition }[];
constructor() {
this.functionTools = [{
func: this.getUserFavoriteCity,
...ToolUtility.createFunctionTool({
name: "getUserFavoriteCity",
description: "Gets the user's favorite city.",
parameters: {}
})
}, {
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'] } } }
})
}];
}
private getUserFavoriteCity(): {} {
return { "location": "Seattle, WA" };
}
private getCityNickname(location: string): {} {
return { "nickname": "The Emerald City" };
}
private getWeather(location: string, unit: string): {} {
return { "weather": unit === "f" ? "72f" : "22c" };
}
public invokeTool(toolCall: RequiredToolCallOutput & FunctionToolDefinitionOutput): ToolOutput | undefined {
console.log(`Function tool call - ${toolCall.function.name}`);
const args = [];
if (toolCall.function.parameters) {
try {
const params = JSON.parse(toolCall.function.parameters);
for (const key in params) {
if (Object.prototype.hasOwnProperty.call(params, key)) {
args.push(params[key]);
}
}
} catch (error) {
console.error(`Failed to parse parameters: ${toolCall.function.parameters}`, error);
return undefined;
}
}
const result = this.functionTools.find((tool) => tool.definition.function.name === toolCall.function.name)?.func(...args);
return result ? {
toolCallId: toolCall.id,
output: JSON.stringify(result)
} : undefined;
}
public getFunctionDefinitions(): FunctionToolDefinition[] {
return this.functionTools.map(tool => {return tool.definition});
}
}
const functionToolExecutor = new FunctionToolExecutor();
const functionTools = functionToolExecutor.getFunctionDefinitions();
const agent = await client.agents.createAgent("gpt-4o",
{
name: "my-agent",
instructions: "You are a weather bot. Use the provided functions to help answer questions. Customize your responses to the user's preferences as much as possible and use friendly nicknames for cities whenever possible.",
tools: functionTools
});
console.log(`Created agent, agent ID: ${agent.id}`);
Créer un thread
Pour chaque session ou conversation, un thread est requis. Voici un exemple :
const thread = await client.agents.createThread();
Créer un thread avec une ressource d’outil
Dans certains scénarios, vous devrez peut-être affecter des ressources spécifiques à des threads individuels. Pour ce faire, vous fournissez l’argument toolResources
à createThread
. Dans l’exemple suivant, vous créez un magasin de vecteurs et chargez un fichier, activez un agent pour la recherche de fichiers à l’aide de l’argument tools
, puis associez le fichier au thread à l’aide de l’argument toolResources
.
const localFileStream = fs.createReadStream("sample_file_for_upload.txt");
const file = await client.agents.uploadFile(localFileStream, "assistants", {
fileName: "sample_file_for_upload.txt",
});
console.log(`Uploaded file, ID: ${file.id}`);
const vectorStore = await client.agents.createVectorStore({
fileIds: [file.id],
name: "my_vector_store",
});
console.log(`Created vector store, ID: ${vectorStore.id}`);
const fileSearchTool = ToolUtility.createFileSearchTool([vectorStore.id]);
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: [fileSearchTool.definition],
});
console.log(`Created agent, agent ID : ${agent.id}`);
// Create thread with file resources.
// If the agent has multiple threads, only this thread can search this file.
const thread = await client.agents.createThread({ toolResources: fileSearchTool.resources });
Créer un message
Pour créer un message permettant à l’Assistant de traiter, vous transmettez user
en tant que role
et une question en tant que content
:
const message = await client.agents.createMessage(thread.id, {
role: "user",
content: "hello, world!",
});
Créer un message avec une pièce jointe de recherche de fichiers
Pour joindre un fichier à un message pour la recherche de contenu, vous utilisez ToolUtility.createFileSearchTool()
et l’argument attachments
:
const fileSearchTool = ToolUtility.createFileSearchTool();
const message = await client.agents.createMessage(thread.id, {
role: "user",
content: "What feature does Smart Eyewear offer?",
attachments: {
fileId: file.id,
tools: [fileSearchTool.definition],
},
});
Créer un message avec une pièce jointe de l’interpréteur de code
Pour joindre un fichier à un message pour l’analyse des données, vous utilisez ToolUtility.createCodeInterpreterTool()
et l’argument attachment
.
Voici un exemple :
// notice that CodeInterpreter must be enabled in the agent creation,
// otherwise the agent will not be able to see the file attachment for code interpretation
const codeInterpreterTool = ToolUtility.createCodeInterpreterTool();
const agent = await client.agents.createAgent("gpt-4-1106-preview", {
name: "my-assistant",
instructions: "You are helpful assistant",
tools: [codeInterpreterTool.definition],
});
console.log(`Created agent, agent ID: ${agent.id}`);
const thread = client.agents.createThread();
console.log(`Created thread, thread ID: ${thread.id}`);
const message = await client.agents.createMessage(thread.id, {
role: "user",
content:
"Could you please create bar chart in TRANSPORTATION sector for the operating profit from the uploaded csv file and provide file to me?",
attachments: {
fileId: file.id,
tools: [codeInterpreterTool.definition],
},
});
console.log(`Created message, message ID: ${message.id}`);
Créer une exécution, un Run_and_Process ou un flux
Voici un exemple de createRun
et d’interrogation jusqu’à ce que l’exécution soit terminée :
let run = await client.agents.createRun(thread.id, agent.id);
// Poll the run as long as run status is queued or in progress
while (
run.status === "queued" ||
run.status === "in_progress" ||
run.status === "requires_action"
) {
// Wait for a second
await new Promise((resolve) => setTimeout(resolve, 1000));
run = await client.agents.getRun(thread.id, run.id);
}
Pour que le SDK interroge votre nom, utilisez la méthode createThreadAndRun
.
Voici un exemple :
const run = await client.agents.createThreadAndRun(thread.id, agent.id);
Avec la diffusion en continu, l’interrogation n’a pas besoin d’être prise en compte.
Voici un exemple :
const streamEventMessages = await client.agents.createRun(thread.id, agent.id).stream();
La gestion des événements peut être effectuée comme suit :
for await (const eventMessage of streamEventMessages) {
switch (eventMessage.event) {
case RunStreamEvent.ThreadRunCreated:
console.log(`ThreadRun status: ${(eventMessage.data as ThreadRunOutput).status}`)
break;
case MessageStreamEvent.ThreadMessageDelta:
{
const messageDelta = eventMessage.data as MessageDeltaChunk;
messageDelta.delta.content.forEach((contentPart) => {
if (contentPart.type === "text") {
const textContent = contentPart as MessageDeltaTextContent
const textValue = textContent.text?.value || "No text"
console.log(`Text delta received:: ${textValue}`)
}
});
}
break;
case RunStreamEvent.ThreadRunCompleted:
console.log("Thread Run Completed");
break;
case ErrorEvent.Error:
console.log(`An error occurred. Data ${eventMessage.data}`);
break;
case DoneEvent.Done:
console.log("Stream completed.");
break;
}
}
Récupérer le message
Pour récupérer des messages à partir d’agents, utilisez l’exemple suivant :
const messages = await client.agents.listMessages(thread.id);
// The messages are following in the reverse order,
// we will iterate them and output only text contents.
for (const dataPoint of messages.data.reverse()) {
const lastMessageContent: MessageContentOutput = dataPoint.content[dataPoint.content.length - 1];
console.log( lastMessageContent);
if (isOutputOfType<MessageTextContentOutput>(lastMessageContent, "text")) {
console.log(`${dataPoint.role}: ${(lastMessageContent as MessageTextContentOutput).text.value}`);
}
}
Récupérer un fichier
Les fichiers chargés par les agents ne peuvent pas être récupérés. Si votre cas d’usage doit accéder au contenu du fichier chargé par les agents, il est conseillé de conserver une copie supplémentaire accessible par votre application. Toutefois, les fichiers générés par les agents sont récupérables par getFileContent
.
Voici un exemple de récupération d’ID de fichier à partir de messages :
const messages = await client.agents.listMessages(thread.id);
const imageFile = (messages.data[0].content[0] as MessageImageFileContentOutput).imageFile;
const imageFileName = (await client.agents.getFile(imageFile.fileId)).filename;
const fileContent = await (await client.agents.getFileContent(imageFile.fileId).asNodeStream()).body;
if (fileContent) {
const chunks: Buffer[] = [];
for await (const chunk of fileContent) {
chunks.push(Buffer.from(chunk));
}
const buffer = Buffer.concat(chunks);
fs.writeFileSync(imageFileName, buffer);
} else {
console.error("Failed to retrieve file content: fileContent is undefined");
}
console.log(`Saved image file to: ${imageFileName}`);
Démontage
Pour supprimer des ressources après avoir effectué des tâches, utilisez les fonctions suivantes :
await client.agents.deleteVectorStore(vectorStore.id);
console.log(`Deleted vector store, vector store ID: ${vectorStore.id}`);
await client.agents.deleteFile(file.id);
console.log(`Deleted file, file ID: ${file.id}`);
client.agents.deleteAgent(agent.id);
console.log(`Deleted agent, agent ID: ${agent.id}`);
Traçage
Vous pouvez ajouter une ressource Azure Application Insights à votre projet Azure AI Foundry. Consultez l’onglet Suivi dans votre studio. Si l’un d’eux a été activé, vous pouvez obtenir la chaîne de connexion Application Insights, configurer vos agents et observer le chemin d’exécution complet via Azure Monitor. En règle générale, vous pouvez commencer le suivi avant de créer un agent.
Installation
Veillez à installer OpenTelemetry et le plug-in de suivi du Kit de développement logiciel (SDK) Azure via
npm install @opentelemetry/api \
@opentelemetry/instrumentation \
@opentelemetry/sdk-trace-node \
@azure/opentelemetry-instrumentation-azure-sdk \
@azure/monitor-opentelemetry-exporter
Vous aurez également besoin d’un exportateur pour envoyer des données de télémétrie à votre back-end d’observabilité. Vous pouvez imprimer des traces dans la console ou utiliser une visionneuse locale telle que Tableau de bord Aspire.
Pour vous connecter au tableau de bord Aspire ou à un autre back-end compatible OpenTelemetry, installez l’exportateur OTLP :
npm install @opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/exporter-metrics-otlp-proto
Exemple de suivi
Voici un exemple de code à inclure ci-dessus createAgent
:
import { trace } from "@opentelemetry/api";
import { AzureMonitorTraceExporter } from "@azure/monitor-opentelemetry-exporter"
import {
ConsoleSpanExporter,
NodeTracerProvider,
SimpleSpanProcessor,
} from "@opentelemetry/sdk-trace-node";
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();
const tracer = trace.getTracer("Agents Sample", "1.0.0");
const client = AIProjectsClient.fromConnectionString(
connectionString || "", new DefaultAzureCredential()
);
if (!appInsightsConnectionString) {
appInsightsConnectionString = await client.telemetry.getConnectionString();
}
if (appInsightsConnectionString) {
const exporter = new AzureMonitorTraceExporter({
connectionString: appInsightsConnectionString
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
}
await tracer.startActiveSpan("main", async (span) => {
client.telemetry.updateSettings({enableContentRecording: true})
// ...
Dépannage
Exceptions
Les méthodes clientes qui effectuent des appels de service déclenchent une RestError pour une réponse de code d’état HTTP non réussie du service. La code
de l’exception contiendra le code d’état de la réponse HTTP. Le error.message
de l’exception contient un message détaillé qui peut être utile pour diagnostiquer le problème :
import { RestError } from "@azure/core-rest-pipeline"
// ...
try {
const result = await client.connections.listConnections();
} catch (e as RestError) {
console.log(`Status code: ${e.code}`);
console.log(e.message);
}
Par exemple, lorsque vous fournissez des informations d’identification incorrectes :
Status code: 401 (Unauthorized)
Operation returned an invalid status 'Unauthorized'
Signaler des problèmes
Pour signaler des problèmes avec la bibliothèque cliente ou demander des fonctionnalités supplémentaires, ouvrez un problème GitHub ici
Contribuant
Ce projet accueille les contributions et suggestions. La plupart des contributions vous obligent à accepter un contrat de licence contributeur (CLA) déclarant que vous avez le droit, et en fait, de nous accorder les droits d’utilisation de votre contribution. Pour plus d’informations, visitez https://cla.microsoft.com.
Lorsque vous envoyez une demande de tirage( pull request), un bot CLA détermine automatiquement si vous devez fournir un CLA et décorer correctement la demande de tirage (par exemple, étiquette, commentaire). Suivez simplement les instructions fournies par le bot. Vous n’aurez besoin de le faire qu’une seule fois sur tous les dépôts à l’aide de notre CLA.
Ce projet a adopté le code de conduite Microsoft Open Source. Pour plus d’informations, consultez la FAQ sur le code de conduite ou contactez opencode@microsoft.com avec toutes les questions ou commentaires supplémentaires.
Azure SDK for JavaScript