你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
使用本文查找有关使用基于 OpenAPI 的工具的分步说明和代码示例。
转到 Microsoft Foundry 门户。 在 “代理人” 屏幕或 代理沙箱中,选择您的代理人。
向下滚动 “设置” 窗格到 动作。 然后选择“添加”。
选择 OpenAPI 3.0 指定的工具。
为工具提供名称(必需)和说明(可选)。 模型将使用说明来确定何时以及如何使用该工具。
选择 “下一步 ”并选择身份验证方法。
- 如果选择
connection,则需要选择使用 API 密钥的 自定义连接 。 - 如果选择
managed identity,则需要输入受众以获取令牌(即身份验证范围)。 请确保已按照 OpenAPI 工具概述中所述设置身份验证和角色分配。 执行正确的设置后,受众的一个例子可以是https://cognitiveservices.azure.com/连接到 Foundry Tools。
- 如果选择
将 OpenAPI 规范复制并粘贴到文本框中。
查看该工具并将其添加到代理。
初始化
代码首先设置必要的导入并初始化 AI 项目客户端:
# Import necessary libraries
import os
import jsonref
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
# import the folloing
from azure.ai.agents.models import OpenApiTool, OpenApiAnonymousAuthDetails
# use the following for connection auth
# from azure.ai.agents.models import OpenApiTool, OpenApiConnectionAuthDetails, OpenApiConnectionSecurityScheme
# use the following for managed identity auth
# from azure.ai.agents.models import OpenApiTool, OpenApiManagedAuthDetails, OpenApiManagedSecurityScheme
endpoint = os.environ["PROJECT_ENDPOINT"]
model_deployment_name = os.environ["MODEL_DEPLOYMENT_NAME"]
# Initialize the project client using the endpoint and default credentials
with AIProjectClient(
endpoint=endpoint,
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
) as project_client:
工具设置
同样,OpenAPI 规范是从 weather.json中加载的。 创建匿名身份验证对象(OpenApiAnonymousAuthDetails),因为此特定 API 在此示例中不需要身份验证。 可以在 GitHub 上找到一个 OpenAPI 规范示例。
# Load the OpenAPI specification for the weather service from a local JSON file
with open(os.path.join(os.path.dirname(__file__), "weather.json"), "r") as f:
openapi_weather = jsonref.loads(f.read())
# Create Auth object for the OpenApiTool (note: using anonymous auth here; connection or managed identity requires additional setup)
auth = OpenApiAnonymousAuthDetails()
# for connection setup
# auth = OpenApiConnectionAuthDetails(security_scheme=OpenApiConnectionSecurityScheme(connection_id=os.environ["CONNECTION_ID"]))
# for managed identity set up
# auth = OpenApiManagedAuthDetails(security_scheme=OpenApiManagedSecurityScheme(audience="https://your_identity_scope.com"))
# Initialize the main OpenAPI tool definition for weather
openapi_tool = OpenApiTool(
name="get_weather", spec=openapi_weather, description="Retrieve weather information for a location", auth=auth
)
代理创建
使用 project_client.agents.create_agent 该方法创建代理。
# Create an agent configured with the combined OpenAPI tool definitions
agent = project_client.agents.create_agent(
model=os.environ["MODEL_DEPLOYMENT_NAME"],
name="my-agent",
instructions="You are a helpful agent",
tools=openapi_tool.definitions,
)
print(f"Created agent, ID: {agent.id}")
线程管理
创建线程并添加初始用户消息。
# Create a new conversation thread for the interaction
thread = project_client.agents.threads.create()
print(f"Created thread, ID: {thread.id}")
# Create the initial user message in the thread
message = project_client.agents.messages.create(
thread_id=thread.id,
role="user",
content="What's the weather in Seattle?",
)
print(f"Created message, ID: {message.id}")
创建运行并检查输出
创建运行,检查输出,并检查运行期间调用的工具。
# Create and automatically process the run, handling tool calls internally
run = project_client.agents.runs.create_and_process(thread_id=thread.id, agent_id=agent.id)
print(f"Run finished with status: {run.status}")
if run.status == "failed":
print(f"Run failed: {run.last_error}")
# Retrieve the steps taken during the run for analysis
run_steps = project_client.agents.run_steps.list(thread_id=thread.id, run_id=run.id)
# Loop through each step to display information
for step in run_steps:
print(f"Step {step['id']} status: {step['status']}")
tool_calls = step.get("step_details", {}).get("tool_calls", [])
for call in tool_calls:
print(f" Tool Call ID: {call.get('id')}")
print(f" Type: {call.get('type')}")
function_details = call.get("function", {})
if function_details:
print(f" Function name: {function_details.get('name')}")
print(f" function output: {function_details.get('output')}")
print()
清理行动
交互完成后,脚本会通过删除创建的代理资源 agents_client.delete_agent() 来执行清理,以避免留下未使用的资源。 它还从 agents_client.messages.list() 线程中提取和打印用于查看或日志记录的整个消息历史记录。
# Delete the agent resource to clean up
project_client.agents.delete_agent(agent.id)
print("Deleted agent")
# Fetch and log all messages exchanged during the conversation thread
messages = project_client.agents.messages.list(thread_id=thread.id)
for msg in messages:
print(f"Message ID: {msg.id}, Role: {msg.role}, Content: {msg.content}")
创建项目客户端
创建包含用于连接到 AI 项目和其他资源的终结点的客户端对象。
const { AgentsClient, isOutputOfType, ToolUtility } = require("@azure/ai-agents");
const { delay } = require("@azure/core-util");
const { DefaultAzureCredential } = require("@azure/identity");
const fs = require("fs");
require("dotenv/config");
const projectEndpoint = process.env["PROJECT_ENDPOINT"];
// Create an Azure AI Client
const client = new AgentsClient(projectEndpoint, new DefaultAzureCredential());
读入 OpenAPI 规范
可以在 GitHub 上找到一个 OpenAPI 规范示例。
// Read in OpenApi spec
const filePath = "./data/weatherOpenApi.json";
const openApiSpec = JSON.parse(fs.readFileSync(filePath, "utf-8"));
// Define OpenApi function
const openApiFunction = {
name: "getWeather",
spec: openApiSpec,
description: "Retrieve weather information for a location",
auth: {
type: "anonymous",
},
default_params: ["format"], // optional
};
创建代理并启用 OpenAPI 工具
// Create OpenApi tool
const openApiTool = ToolUtility.createOpenApiTool(openApiFunction);
// Create agent with OpenApi tool
const agent = await client.createAgent(modelDeploymentName, {
name: "myAgent",
instructions: "You are a helpful agent",
tools: [openApiTool.definition],
});
console.log(`Created agent, agent ID: ${agent.id}`);
创建线程
// Create a thread
const thread = await client.threads.create();
console.log(`Created thread, thread ID: ${thread.id}`);
// Create a message
const message = await client.messages.create(thread.id, "user", "What's the weather in Seattle?");
console.log(`Created message, message ID: ${message.id}`);
创建运行并检查输出
// Create and execute a run
let run = await client.runs.create(thread.id, agent.id);
while (run.status === "queued" || run.status === "in_progress") {
await delay(1000);
run = await client.runs.get(thread.id, run.id);
}
if (run.status === "failed") {
// Check if you got "Rate limit is exceeded.", then you want to get more quota
console.log(`Run failed: ${run.lastError}`);
}
console.log(`Run finished with status: ${run.status}`);
// Get most recent message from the assistant
const messagesIterator = client.messages.list(thread.id);
const messages = [];
for await (const m of messagesIterator) {
messages.push(m);
}
const assistantMessage = messages.find((msg) => msg.role === "assistant");
if (assistantMessage) {
const textContent = assistantMessage.content.find((content) => isOutputOfType(content, "text"));
if (textContent) {
console.log(`Last message: ${textContent.text.value}`);
}
}
// Delete the agent once done
await client.deleteAgent(agent.id);
console.log(`Deleted agent, agent ID: ${agent.id}`);
配置客户端和 OpenAPI 工具
首先,检索配置详细信息并创建一个 PersistentAgentsClient,然后使用 OpenAPI 规范定义 OpenApiToolDefinition 。 可以在 GitHub 上找到一个 OpenAPI 规范示例。
using Azure;
using Azure.AI.Agents.Persistent;
using Azure.Identity;
using Microsoft.Extensions.Configuration;
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
var projectEndpoint = configuration["ProjectEndpoint"];
var modelDeploymentName = configuration["ModelDeploymentName"];
var openApiSpec = configuration["OpenApiSpec"];
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
BinaryData spec = BinaryData.FromBytes(File.ReadAllBytes(openApiSpec));
// Using anonymous auth for this example
OpenApiAnonymousAuthDetails openApiAnonAuth = new();
// Define the OpenAPI tool
OpenApiToolDefinition openApiToolDef = new(
name: "get_weather",
description: "Retrieve weather information for a location",
spec: spec,
openApiAuthentication: openApiAnonAuth,
defaultParams: ["format"]
);
创建代理
接下来,使用必要的模型部署、名称、说明和以前定义的 OpenAPI 工具创建一个 PersistentAgent 。
PersistentAgent agent = client.Administration.CreateAgent(
model: modelDeploymentName,
name: "Open API Tool Calling Agent",
instructions: "You are a helpful agent.",
tools: [openApiToolDef]
);
创建线程、消息和运行
为对话创建一个 PersistentAgentThread 会话,向其添加用户消息,然后创建一个 ThreadRun 处理消息,等待消息完成。
PersistentAgentThread thread = client.Threads.CreateThread();
client.Messages.CreateMessage(
thread.Id,
MessageRole.User,
"What's the weather in Seattle?");
ThreadRun run = client.Runs.CreateRun(
thread.Id,
agent.Id);
// Poll for the run's completion status
do
{
Thread.Sleep(TimeSpan.FromMilliseconds(500));
run = client.Runs.GetRun(thread.Id, run.Id);
}
while (run.Status == RunStatus.Queued
|| run.Status == RunStatus.InProgress
|| run.Status == RunStatus.RequiresAction);
显示对话消息
在控制台中按时间顺序检索并输出会话中的所有消息以显示对话流。
Pageable<PersistentThreadMessage> messages = client.Messages.GetMessages(
threadId: thread.Id,
order: ListSortOrder.Ascending);
foreach (PersistentThreadMessage threadMessage in messages)
{
foreach (MessageContent content in threadMessage.ContentItems)
{
switch (content)
{
case MessageTextContent textItem:
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
break;
}
}
清理资源
最后,删除创建的 PersistentAgentThread 和 PersistentAgent,以清理本示例中使用的资源。
client.Threads.DeleteThread(thread.Id);
client.Administration.DeleteAgent(agent.Id);
请按照 REST API 快速入门 为环境变量 AGENT_TOKEN、AZURE_AI_FOUNDRY_PROJECT_ENDPOINT 和 API_VERSION 设置正确的值。
创建 OpenAPI 规范工具定义、代理和线程
建议将 OpenAPI 规范存储在另一个文件中,并导入内容以初始化该工具。 此示例用作 anonymous 身份验证类型。 可以在 GitHub 上找到一个 OpenAPI 规范示例。
curl --request POST \
--url $AZURE_AI_FOUNDRY_PROJECT_ENDPOINT/assistants?api-version=$API_VERSION \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"instructions": "You are a weather bot. Use the provided functions to answer questions about the weather.",
"model": "gpt-4o",
"tools": [{
"type": "openapi",
"openapi": {
"name": "weatherapp",
"description": "Tool to get weather data",
"auth": {
"type": "anonymous"
},
"spec": {
"openapi": "3.1.0",
"info": {
"title": "get weather data",
"description": "Retrieves current weather data for a location.",
"version": "v1.0.0"
},
"servers": [{
"url": "https://wttr.in"
}],
"auth": [],
"paths": {
"/{location}": {
"get": {
"description": "Get weather information for a specific location",
"operationId": "GetCurrentWeather",
"parameters": [
{
"name": "location",
"in": "path",
"description": "City or location to retrieve the weather for",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "format",
"in": "query",
"description": "Format in which to return data. Always use 3.",
"required": true,
"schema": {
"type": "integer",
"default": 3
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
},
"404": {
"description": "Location not found"
}
},
"deprecated": false
}
}
},
"components": {
"schemes": { }
}
}
}
}]
}'
创建运行并检查输出
创建运行并观察模型是否使用 OpenAPI 规范工具来响应用户的问题。
创建线程
curl --request POST \
--url $AZURE_AI_FOUNDRY_PROJECT_ENDPOINT/threads?api-version=$API_VERSION \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d ''
将用户问题添加到线程
curl curl --request POST \
--url $AZURE_AI_FOUNDRY_PROJECT_ENDPOINT/threads/thread_abc123/messages?api-version=$API_VERSION \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"role": "user",
"content": "What is the weather in Seattle?"
}'
运行线程
curl --request POST \
--url $AZURE_AI_FOUNDRY_PROJECT_ENDPOINT/threads/thread_abc123/runs?api-version=$API_VERSION \
-H "Authorization: Bearer $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "asst_abc123",
}'
获取运行状态
curl --request GET \
--url $AZURE_AI_FOUNDRY_PROJECT_ENDPOINT/threads/thread_abc123/runs/run_abc123?api-version=$API_VERSION \
-H "Authorization: Bearer $AGENT_TOKEN"
检索代理响应
curl --request GET \
--url $AZURE_AI_FOUNDRY_PROJECT_ENDPOINT/threads/thread_abc123/messages?api-version=$API_VERSION \
-H "Authorization: Bearer $AGENT_TOKEN"
示例代码
以下示例代码在名为
package com.example.agents;
import com.azure.ai.agents.persistent.MessagesClient;
import com.azure.ai.agents.persistent.PersistentAgentsAdministrationClient;
import com.azure.ai.agents.persistent.PersistentAgentsClient;
import com.azure.ai.agents.persistent.PersistentAgentsClientBuilder;
import com.azure.ai.agents.persistent.RunsClient;
import com.azure.ai.agents.persistent.ThreadsClient;
import com.azure.ai.agents.persistent.models.CreateAgentOptions;
import com.azure.ai.agents.persistent.models.CreateRunOptions;
import com.azure.ai.agents.persistent.models.MessageImageFileContent;
import com.azure.ai.agents.persistent.models.MessageRole;
import com.azure.ai.agents.persistent.models.MessageTextContent;
import com.azure.ai.agents.persistent.models.OpenApiAnonymousAuthDetails;
import com.azure.ai.agents.persistent.models.OpenApiFunctionDefinition;
import com.azure.ai.agents.persistent.models.OpenApiToolDefinition;
import com.azure.ai.agents.persistent.models.PersistentAgent;
import com.azure.ai.agents.persistent.models.PersistentAgentThread;
import com.azure.ai.agents.persistent.models.RunStatus;
import com.azure.ai.agents.persistent.models.ThreadMessage;
import com.azure.ai.agents.persistent.models.ThreadRun;
import com.azure.ai.agents.persistent.models.MessageContent;
import com.azure.core.http.rest.PagedIterable;
import com.azure.core.util.BinaryData;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.json.JsonProviders;
import com.azure.json.JsonReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
public class AgentExample {
public static void main(String[] args) throws IOException, URISyntaxException {
// variables for authenticating requests to the agent service
String projectEndpoint = System.getenv("PROJECT_ENDPOINT");
String modelName = System.getenv("MODEL_DEPLOYMENT_NAME");
PersistentAgentsClientBuilder clientBuilder = new PersistentAgentsClientBuilder().endpoint(projectEndpoint)
.credential(new DefaultAzureCredentialBuilder().build());
PersistentAgentsClient agentsClient = clientBuilder.buildClient();
PersistentAgentsAdministrationClient administrationClient = agentsClient.getPersistentAgentsAdministrationClient();
ThreadsClient threadsClient = agentsClient.getThreadsClient();
MessagesClient messagesClient = agentsClient.getMessagesClient();
RunsClient runsClient = agentsClient.getRunsClient();
Path filePath = getFile("weather_openapi.json");
JsonReader reader = JsonProviders.createReader(Files.readAllBytes(filePath));
OpenApiAnonymousAuthDetails oaiAuth = new OpenApiAnonymousAuthDetails();
OpenApiToolDefinition openApiTool = new OpenApiToolDefinition(new OpenApiFunctionDefinition(
"openapitool",
reader.getNullable(nonNullReader -> BinaryData.fromObject(nonNullReader.readUntyped())),
oaiAuth
));
String agentName = "openAPI_example";
CreateAgentOptions createAgentOptions = new CreateAgentOptions(modelName)
.setName(agentName)
.setInstructions("You are a helpful agent")
.setTools(Arrays.asList(openApiTool));
PersistentAgent agent = administrationClient.createAgent(createAgentOptions);
PersistentAgentThread thread = threadsClient.createThread();
ThreadMessage createdMessage = messagesClient.createMessage(
thread.getId(),
MessageRole.USER,
"What's the weather in seattle?");
try {
//run agent
CreateRunOptions createRunOptions = new CreateRunOptions(thread.getId(), agent.getId())
.setAdditionalInstructions("");
ThreadRun threadRun = runsClient.createRun(createRunOptions);
waitForRunCompletion(thread.getId(), threadRun, runsClient);
printRunMessages(messagesClient, thread.getId());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
//cleanup
threadsClient.deleteThread(thread.getId());
administrationClient.deleteAgent(agent.getId());
}
}
private static Path getFile(String fileName) throws FileNotFoundException, URISyntaxException {
URL resource = AgentExample.class.getClassLoader().getResource(fileName);
if (resource == null) {
throw new FileNotFoundException("File not found");
}
File file = new File(resource.toURI());
return file.toPath();
}
// A helper function to print messages from the agent
public static void printRunMessages(MessagesClient messagesClient, String threadId) {
PagedIterable<ThreadMessage> runMessages = messagesClient.listMessages(threadId);
for (ThreadMessage message : runMessages) {
System.out.print(String.format("%1$s - %2$s : ", message.getCreatedAt(), message.getRole()));
for (MessageContent contentItem : message.getContent()) {
if (contentItem instanceof MessageTextContent) {
System.out.print((((MessageTextContent) contentItem).getText().getValue()));
} else if (contentItem instanceof MessageImageFileContent) {
String imageFileId = (((MessageImageFileContent) contentItem).getImageFile().getFileId());
System.out.print("Image from ID: " + imageFileId);
}
System.out.println();
}
}
}
// a helper function to wait until a run has completed running
public static void waitForRunCompletion(String threadId, ThreadRun threadRun, RunsClient runsClient)
throws InterruptedException {
do {
Thread.sleep(500);
threadRun = runsClient.getRun(threadId, threadRun.getId());
}
while (
threadRun.getStatus() == RunStatus.QUEUED
|| threadRun.getStatus() == RunStatus.IN_PROGRESS
|| threadRun.getStatus() == RunStatus.REQUIRES_ACTION);
if (threadRun.getStatus() == RunStatus.FAILED) {
System.out.println(threadRun.getLastError().getMessage());
}
}
}