Libreria client di Azure AI Projects per JavaScript - versione 1.0.0-beta.2
Usare la libreria client dei progetti di intelligenza artificiale (in anteprima) per:
- Enumerare le connessioni nel progetto Azure AI Foundry e ottenere le proprietà di connessione. Ad esempio, ottenere l'URL dell'endpoint di inferenza e le credenziali associate alla connessione OpenAI di Azure.
- Sviluppare agenti usando il servizio Azure AI Agent, sfruttando un ampio ecosistema di modelli, strumenti e funzionalità di OpenAI, Microsoft e altri provider LLM. Il servizio Agente di intelligenza artificiale di Azure consente la creazione di agenti per un'ampia gamma di casi d'uso generativi di intelligenza artificiale. Il pacchetto è attualmente in anteprima privata.
- Abilitare la traccia OpenTelemetry.
Sommario
- Introduzione
- concetti chiave
-
esempi
- enumerare le connessioni
- agenti
(anteprima) -
Creare un agente con:
- ricerca file
- 'interprete del codice
- di base bing
- ricerca di intelligenza artificiale di Azure
- chiamata di funzione
-
Creare thread con
- risorsa strumento di
- risorsa strumento di
- Creare messaggi con:
- esegui esecuzione, creazione di thread ed esecuzione o di flusso
- Recuperare messaggio
- Recuperare file
- Eliminare l'eliminazione di di risorse
- traccia
-
Creare un agente con:
- traccia
- risoluzione dei problemi
- contributi
Introduttiva
Prerequisito
- versioni LTS di Node.js
- Una sottoscrizione di Azure .
- Un progetto di in Azure AI Foundry.
- Stringa di connessione del progetto. È disponibile nella pagina di panoramica del progetto Azure AI Foundry, in "Dettagli progetto". Di seguito si presuppone che la variabile di ambiente
AZURE_AI_PROJECTS_CONNECTION_STRING
sia stata definita per contenere questo valore. - L'ID Entra è necessario per autenticare il client. L'applicazione necessita di un oggetto che implementa l'interfaccia token
. Gli esempi di codice qui usano DefaultAzureCredential. Per ottenere questo lavoro, è necessario: - Ruolo
Contributor
. Il ruolo assegnato può essere eseguito tramite la scheda "Controllo di accesso (IAM)" della risorsa progetto di Intelligenza artificiale di Azure nel portale di Azure. - installato dell'interfaccia della riga di comando di Azure.
- Si è connessi all'account Azure eseguendo
az login
. - Si noti che se si dispone di più sottoscrizioni di Azure, la sottoscrizione che contiene la risorsa del progetto di intelligenza artificiale di Azure deve essere la sottoscrizione predefinita. Eseguire
az account list --output table
per elencare tutte le sottoscrizioni e vedere quale è l'impostazione predefinita. Eseguireaz account set --subscription "Your Subscription ID or Name"
per modificare la sottoscrizione predefinita.
- Ruolo
Installare il pacchetto
npm install @azure/ai-projects
Concetti chiave
Creare ed autenticare il client
Il metodo class factory fromConnectionString
viene usato per costruire il client. Per costruire 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(),
);
Esempi
Enumerare le connessioni
Il progetto Azure AI Foundry ha un "Centro di gestione". Quando lo si immette, verrà visualizzata una scheda denominata "Risorse connesse" nel progetto. Le operazioni di .connections
sul client consentono di enumerare le connessioni e ottenere le proprietà di connessione. Le proprietà di connessione includono l'URL della risorsa e le credenziali di autenticazione, tra le altre cose.
Di seguito sono riportati esempi di codice delle operazioni di connessione. Gli esempi completi sono disponibili nella cartella "connections" nella [pacchetti samples][samples].
Ottenere le proprietà di tutte le connessioni
Per elencare le proprietà di tutte le connessioni nel progetto Azure AI Foundry:
const connections = await client.connections.listConnections();
for (const connection of connections) {
console.log(connection);
}
Ottenere le proprietà di tutte le connessioni di un particolare tipo
Per elencare le proprietà delle connessioni di un determinato tipo (qui Azure OpenAI):
const connections = await client.connections.listConnections({ category: "AzureOpenAI" });
for (const connection of connections) {
console.log(connection);
}
Ottenere le proprietà di una connessione in base al nome della connessione
Per ottenere le proprietà di connessione di una connessione denominata connectionName
:
const connection = await client.connections.getConnection("connectionName");
console.log(connection);
Per ottenere le proprietà di connessione con le credenziali di autenticazione:
const connection = await client.connections.getConnectionWithSecrets("connectionName");
console.log(connection);
Agenti (anteprima)
Gli agenti nella libreria client di Azure AI Projects sono progettati per facilitare varie interazioni e operazioni all'interno dei progetti di intelligenza artificiale. Fungono da componenti di base che gestiscono ed eseguono attività, sfruttando diversi strumenti e risorse per raggiungere obiettivi specifici. I passaggi seguenti descrivono la sequenza tipica per l'interazione con gli agenti. Per altri esempi di Agent, vedere la cartella "agents" nel [pacchetto samples][samples].
Gli agenti vengono sviluppati attivamente. Presto sarà disponibile un modulo di iscrizione per l'anteprima privata.
Creare un agente
Ecco un esempio di come creare un agente:
const agent = await client.agents.createAgent("gpt-4o", {
name: "my-agent",
instructions: "You are a helpful assistant",
});
Per consentire agli agenti di accedere alle risorse o alle funzioni personalizzate, sono necessari strumenti. È possibile passare strumenti a createAgent
tramite gli argomenti tools
e toolResources
.
A tale scopo, è possibile usare ToolSet
:
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}`);
Creare un agente con Ricerca file
Per eseguire la ricerca di file da un agente, è prima necessario caricare un file, creare un archivio vettoriale e associare il file all'archivio vettoriale. Ecco un esempio:
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}`);
Creare un agente con interprete del codice
Di seguito è riportato un esempio per caricare un file e usarlo per l'interprete di codice da un agente:
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}`);
Creare un agente con Bing Grounding
Per consentire all'agente di eseguire la ricerca tramite l'API di ricerca Bing, usare ToolUtility.createConnectionTool()
insieme a una connessione.
Ecco un esempio:
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}`);
Creare un agente con Ricerca intelligenza artificiale di Azure
Ricerca di intelligenza artificiale di Azure è un sistema di ricerca aziendale per applicazioni ad alte prestazioni. Si integra con il servizio Azure OpenAI e Azure Machine Learning, offrendo tecnologie di ricerca avanzate come la ricerca vettoriale e la ricerca full-text. Ideale per informazioni dettagliate, individuazione delle informazioni e automazione delle informazioni
Di seguito è riportato un esempio per integrare Ricerca intelligenza artificiale di Azure:
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}`);
Creare un agente con chiamata di funzione
È possibile migliorare gli agenti definendo le funzioni di callback come strumenti per le funzioni. Questi elementi possono essere forniti per createAgent
tramite la combinazione di tools
e toolResources
. Solo le definizioni e le descrizioni delle funzioni vengono fornite per createAgent
, senza le implementazioni. Il Run
o event handler of stream
genererà uno stato requires_action
in base alle definizioni di funzione. Il codice deve gestire questo stato e chiamare le funzioni appropriate.
Ecco un esempio:
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}`);
Crea thread
Per ogni sessione o conversazione, è necessario un thread. Ecco un esempio:
const thread = await client.agents.createThread();
Creare un thread con una risorsa strumento
In alcuni scenari potrebbe essere necessario assegnare risorse specifiche a singoli thread. A tale scopo, specificare l'argomento toolResources
per createThread
. Nell'esempio seguente si crea un archivio vettoriale e si carica un file, si abilita un agente per la ricerca di file usando l'argomento tools
e quindi si associa il file al thread usando l'argomento 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 });
Crea messaggio
Per creare un messaggio per l'assistente da elaborare, passare user
come role
e una domanda come content
:
const message = await client.agents.createMessage(thread.id, {
role: "user",
content: "hello, world!",
});
Creare un messaggio con l'allegato di ricerca file
Per allegare un file a un messaggio per la ricerca di contenuto, usare ToolUtility.createFileSearchTool()
e l'argomento 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],
},
});
Creare un messaggio con allegato dell'interprete del codice
Per allegare un file a un messaggio per l'analisi dei dati, usare ToolUtility.createCodeInterpreterTool()
e l'argomento attachment
.
Ecco un esempio:
// 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}`);
Creare run, Run_and_Process o stream
Di seguito è riportato un esempio di createRun
e polling fino al completamento dell'esecuzione:
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);
}
Per fare in modo che l'SDK esegua il polling per conto dell'SDK, usare il metodo createThreadAndRun
.
Ecco un esempio:
const run = await client.agents.createThreadAndRun(thread.id, agent.id);
Con lo streaming, non è necessario considerare anche il polling.
Ecco un esempio:
const streamEventMessages = await client.agents.createRun(thread.id, agent.id).stream();
La gestione degli eventi può essere eseguita nel modo seguente:
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;
}
}
Recupera messaggio
Per recuperare i messaggi dagli agenti, usare l'esempio seguente:
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}`);
}
}
Recupera file
Impossibile recuperare i file caricati dagli agenti. Se il caso d'uso deve accedere al contenuto del file caricato dagli agenti, è consigliabile mantenere una copia aggiuntiva accessibile dall'applicazione. Tuttavia, i file generati dagli agenti sono recuperabili da getFileContent
.
Di seguito è riportato un esempio di recupero di ID file dai messaggi:
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}`);
Teardown
Per rimuovere le risorse dopo il completamento delle attività, usare le funzioni seguenti:
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}`);
Tracciatura
È possibile aggiungere una risorsa di Azure Application Insights al progetto Azure AI Foundry. Vedere la scheda Traccia nello studio. Se è stato abilitato, è possibile ottenere la stringa di connessione di Application Insights, configurare gli agenti e osservare il percorso di esecuzione completo tramite Monitoraggio di Azure. In genere, è consigliabile iniziare la traccia prima di creare un agente.
Installazione
Assicurarsi di installare OpenTelemetry e il plug-in di traccia di Azure SDK tramite
npm install @opentelemetry/api \
@opentelemetry/instrumentation \
@opentelemetry/sdk-trace-node \
@azure/opentelemetry-instrumentation-azure-sdk \
@azure/monitor-opentelemetry-exporter
È anche necessario un utilità di esportazione per inviare dati di telemetria al back-end di osservabilità. È possibile stampare tracce nella console o usare un visualizzatore locale, ad esempio aspira dashboard.
Per connettersi a Aspire Dashboard o a un altro back-end compatibile con OpenTelemetry, installare l'utilità di esportazione OTLP:
npm install @opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/exporter-metrics-otlp-proto
Esempio di traccia
Ecco un esempio di codice da includere sopra 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})
// ...
Risoluzione dei problemi
Eccezioni
I metodi client che effettuano chiamate al servizio generano un RestError per una risposta di codice di stato HTTP non riuscita dal servizio. Il code
dell'eccezione conterrà il codice di stato della risposta HTTP. L'error.message
dell'eccezione contiene un messaggio dettagliato che può essere utile per diagnosticare il problema:
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);
}
Ad esempio, quando si specificano credenziali errate:
Status code: 401 (Unauthorized)
Operation returned an invalid status 'Unauthorized'
Segnalazione di problemi
Per segnalare problemi con la libreria client o richiedere funzionalità aggiuntive, aprire un problema di GitHub qui
Contribuire
Questo progetto accoglie contributi e suggerimenti. La maggior parte dei contributi richiede l'accettazione di un Contratto di licenza collaboratore (CLA) che dichiara di avere il diritto e, in realtà, concedere a Microsoft i diritti per l'uso del contributo. Per informazioni dettagliate, visitare https://cla.microsoft.com.
Quando si invia una richiesta pull, un bot CLA determinerà automaticamente se è necessario fornire un cla e decorare la richiesta pull in modo appropriato (ad esempio, etichetta, commento). Seguire semplicemente le istruzioni fornite dal bot. Dovrai eseguire questa operazione una sola volta in tutti i repository usando la nostra cla.
Questo progetto ha adottato la codice di comportamento Microsoft Open Source. Per altre informazioni, vedere domande frequenti sul codice di condotta o contattare opencode@microsoft.com con eventuali domande o commenti aggiuntivi.
Azure SDK for JavaScript