Поделиться через


Клиентская библиотека Проектов ИИ Azure для JavaScript версии 1.0.0-beta.2

Использование клиентской библиотеки проектов ИИ (в предварительной версии) для:

  • Перечисление подключений в проекте Azure AI Foundry и получение свойств подключения. Например, получите URL-адрес конечной точки вывода и учетные данные, связанные с подключением Azure OpenAI.
  • Разработка агентов с помощью службы агента ИИ Azure, используя обширную экосистему моделей, инструментов и возможностей openAI, Майкрософт и других поставщиков LLM. Служба агента ИИ Azure позволяет создавать агенты для широкого спектра вариантов использования сгенерируемым ИИ. Пакет в настоящее время находится в закрытой предварительной версии.
  • Включить трассировку OpenTelemetry.

документации по продукту

Оглавление

Начало работы

Предпосылка

  • версии LTS Node.js
  • подписка Azure.
  • Проект в Azure AI Foundry.
  • Строка подключения проекта. Его можно найти на странице обзора проекта Azure AI Foundry в разделе "Сведения о проекте". Ниже предполагается, что переменная среды AZURE_AI_PROJECTS_CONNECTION_STRING определена для хранения этого значения.
  • Идентификатор записи необходим для проверки подлинности клиента. Приложению требуется объект, реализующий интерфейс TokenCredential. Примеры кода здесь используют DefaultAzureCredential. Чтобы получить эту работу, вам потребуется:
    • Роль Contributor. На портале Azure можно назначить роль с помощью вкладки "Управление доступом (IAM)" ресурса проекта Azure AI.
    • установленной Azure CLI.
    • Вы вошли в учетную запись Azure, выполнив az login.
    • Обратите внимание, что если у вас несколько подписок Azure, подписка, содержащая ресурс Проекта Azure AI, должна быть вашей подпиской по умолчанию. Запустите az account list --output table, чтобы вывести список всех подписок и увидеть, какой из них используется по умолчанию. Запустите az account set --subscription "Your Subscription ID or Name", чтобы изменить подписку по умолчанию.

Установка пакета

npm install @azure/ai-projects

Основные понятия

Создание и проверка подлинности клиента

Метод фабрики классов fromConnectionString используется для создания клиента. Чтобы создать клиент, выполните приведенные действия.

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(),
);

Примеры

Перечисление подключений

Проект Azure AI Foundry имеет центр управления. При вводе в проект появится вкладка с именем "Подключенные ресурсы". Операции .connections на клиенте позволяют перечислять подключения и получать свойства подключения. Свойства подключения включают URL-адрес ресурса и учетные данные проверки подлинности, помимо прочего.

Ниже приведены примеры кода операций подключения. Полные примеры можно найти в папке "подключения" в [примерах пакетов][примеры].

Получение свойств всех подключений

Чтобы получить список свойств всех подключений в проекте Azure AI Foundry:

const connections = await client.connections.listConnections();
for (const connection of connections) {
  console.log(connection);
}

Получение свойств всех подключений определенного типа

Список свойств подключений определенного типа (здесь Azure OpenAI):

const connections = await client.connections.listConnections({ category: "AzureOpenAI" });
for (const connection of connections) {
  console.log(connection);
}

Получение свойств подключения по имени подключения

Чтобы получить свойства подключения с именем connectionName:

const connection = await client.connections.getConnection("connectionName");
console.log(connection);

Чтобы получить свойства подключения с учетными данными проверки подлинности, выполните следующие действия.

const connection = await client.connections.getConnectionWithSecrets("connectionName");
console.log(connection);

Агенты (предварительная версия)

Агенты в клиентской библиотеке проектов ИИ Azure предназначены для упрощения различных взаимодействий и операций в проектах ИИ. Они служат основными компонентами, которые управляют и выполняют задачи, используя различные средства и ресурсы для достижения конкретных целей. Ниже описана типичная последовательность взаимодействия с агентами. Дополнительные примеры агента см. в папке "Агенты" в [примерах пакетов][примеры].

Агенты активно разрабатываются. В ближайшее время появится форма регистрации для частной предварительной версии.

Создание агента

Ниже приведен пример создания агента:

const agent = await client.agents.createAgent("gpt-4o", {
  name: "my-agent",
  instructions: "You are a helpful assistant",
});

Чтобы разрешить агентам доступ к ресурсам или пользовательским функциям, вам потребуются средства. Средства можно передать в createAgent через аргументы tools и toolResources.

Для этого можно использовать 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}`);

Чтобы выполнить поиск по файлам агентом, сначала необходимо отправить файл, создать векторное хранилище и связать файл с векторным хранилищем. Ниже приведен пример:

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}`);

Создание агента с интерпретатором кода

Ниже приведен пример отправки файла и его использования для интерпретатора кода агентом:

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}`);

Создание агента с помощью Bing Grounding

Чтобы разрешить агенту выполнять поиск через API поиска Bing, вы используете ToolUtility.createConnectionTool() вместе с подключением.

Ниже приведен пример:

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}`);

Поиск ИИ Azure — это корпоративная система поиска для высокопроизводительных приложений. Он интегрируется со службой Azure OpenAI и Машинным обучением Azure, предлагая расширенные технологии поиска, такие как векторный поиск и полнотекстовый поиск. Идеально подходит для аналитики базы знаний, обнаружения информации и автоматизации

Ниже приведен пример интеграции службы "Поиск ИИ 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}`);

Создание агента с вызовом функции

Вы можете улучшить агенты, определив функции обратного вызова в качестве инструментов функции. Их можно предоставить для createAgent с помощью сочетания tools и toolResources. Только определения и описания функций предоставляются для createAgentбез реализации. Run или event handler of stream вызовет состояние requires_action на основе определений функций. Код должен обрабатывать это состояние и вызывать соответствующие функции.

Ниже приведен пример:

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}`);

Создание потока

Для каждого сеанса или беседы требуется поток. Ниже приведен пример:

const thread = await client.agents.createThread();

Создание потока с помощью ресурса средства

В некоторых сценариях может потребоваться назначить определенные ресурсы отдельным потокам. Для этого укажите аргумент toolResources для createThread. В следующем примере вы создадите векторное хранилище и отправьте файл, включите агент для поиска файлов с помощью аргумента tools, а затем свяжите файл с потоком с помощью аргумента 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 });

Создание сообщения

Чтобы создать сообщение для помощника по обработке, передайте user как role и вопрос в виде content:

const message = await client.agents.createMessage(thread.id, {
  role: "user",
  content: "hello, world!",
});

Создание сообщения с вложением поиска файлов

Чтобы вложить файл в сообщение для поиска содержимого, используйте ToolUtility.createFileSearchTool() и аргумент 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],
  },
});

Создание сообщения с вложением интерпретатора кода

Чтобы подключить файл к сообщению для анализа данных, используйте ToolUtility.createCodeInterpreterTool() и аргумент attachment.

Ниже приведен пример:

// 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}`);

Создание запуска, Run_and_Process или stream

Ниже приведен пример createRun и опроса до завершения выполнения:

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);
}

Чтобы провести опрос пакета SDK от вашего имени, используйте метод createThreadAndRun.

Ниже приведен пример:

const run = await client.agents.createThreadAndRun(thread.id, agent.id);

При потоковой передаче опросы также не должны рассматриваться.

Ниже приведен пример:

const streamEventMessages = await client.agents.createRun(thread.id, agent.id).stream();

Обработку событий можно выполнить следующим образом:

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;
  }
}

Получение сообщения

Чтобы получить сообщения от агентов, используйте следующий пример:

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}`);
    }
  }

Получение файла

Файлы, отправленные агентами, не могут быть извлечены обратно. Если ваш вариант использования должен получить доступ к содержимому файла, отправленного агентами, рекомендуется сохранить дополнительную копию, доступную приложению. Однако файлы, созданные агентами, извлекаются getFileContent.

Ниже приведен пример получения идентификаторов файлов из сообщений:

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}`);

Слеза

Чтобы удалить ресурсы после выполнения задач, используйте следующие функции:

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}`);

Калька

Вы можете добавить ресурс Application Insights Azure в проект Azure AI Foundry. Перейдите на вкладку "Трассировка" в студии. Если он включен, вы можете получить строку подключения Application Insights, настроить агенты и просмотреть полный путь выполнения с помощью Azure Monitor. Как правило, перед созданием агента может потребоваться начать трассировку.

Установка

Обязательно установите OpenTelemetry и подключаемый модуль трассировки пакета SDK Azure с помощью

npm install @opentelemetry/api \
  @opentelemetry/instrumentation \
  @opentelemetry/sdk-trace-node \
  @azure/opentelemetry-instrumentation-azure-sdk \
  @azure/monitor-opentelemetry-exporter

Вам также потребуется экспортер для отправки телеметрии в серверную часть наблюдаемости. Трассировки можно распечатать в консоли или использовать локальное средство просмотра, например панели мониторинга Aspire.

Чтобы подключиться к панели мониторинга Aspire или другой серверной части, совместимой с OpenTelemetry, установите экспортер OTLP:

npm install @opentelemetry/exporter-trace-otlp-proto \
  @opentelemetry/exporter-metrics-otlp-proto

Пример трассировки

Ниже приведен пример кода для включения выше 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})
// ...

Устранение неполадок

Исключения

Клиентские методы, которые вызывают службы, вызывают RestError для ответа кода состояния HTTP без успешного выполнения из службы. code исключения будет содержать код состояния HTTP-ответа. error.message исключения содержит подробное сообщение, которое может оказаться полезным при диагностике проблемы:

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);
}

Например, если указать неправильные учетные данные:

Status code: 401 (Unauthorized)
Operation returned an invalid status 'Unauthorized'

Проблемы с отчетами

Чтобы сообщить о проблемах с клиентской библиотекой или запросить дополнительные функции, откройте проблему GitHub здесь

Способствует

Этот проект приветствует взносы и предложения. Большинство вкладов требуют, чтобы вы согласились с соглашением о лицензии участника (CLA), заявив, что у вас есть право, и на самом деле, предоставьте нам права на использование вашего вклада. Дополнительные сведения см. в https://cla.microsoft.com.

При отправке запроса на вытягивание бот CLA автоматически определяет, нужно ли предоставить соглашение об уровне обслуживания и украсить pr соответствующим образом (например, метка, комментарий). Просто следуйте инструкциям, предоставленным ботом. Это необходимо сделать только один раз во всех репозиториях с помощью нашего CLA.

Этот проект принял Microsoft Open Source Code of Conduct. Дополнительные сведения см. в разделе "Часто задаваемые вопросы о поведении" или opencode@microsoft.com с дополнительными вопросами или комментариями.