Бөлісу құралы:


Конечные точки, совместимые с OpenAI

Agent Framework поддерживает протоколы, совместимые с OpenAI, как для размещения агентов через стандартные API, так и для подключения к любой конечной точке, совместимой с OpenAI.

Что такое протоколы OpenAI?

Поддерживаются два протокола OpenAI:

  • API завершения чата — стандартный формат запроса и ответа без отслеживания состояния для взаимодействия чата
  • API ответов — расширенный формат, поддерживающий беседы, потоковое вещание и долговременные процессы агентов

API ответов теперь является стандартным и рекомендуемым подходом в соответствии с документацией OpenAI. Он предоставляет более комплексный и функциональный интерфейс для создания приложений ИИ со встроенным управлением беседами, возможностями потоковой передачи и поддержкой длительных процессов.

Используйте API ответов , когда:

  • Создание новых приложений (рекомендуется по умолчанию)
  • Вам потребуется управление беседами на стороне сервера. Однако это не обязательно: вы можете использовать API для ответов в режиме без сохранения состояния.
  • Вы хотите постоянную историю бесед
  • Вы создаете долговременные процессы агента
  • Вам нужны расширенные возможности потоковой передачи с подробными типами событий
  • Вы хотите отслеживать отдельные ответы и управлять ими (например, получать определенный ответ по идентификатору, проверять его состояние или отменять выполняемый ответ).

Используйте API завершения чата , когда:

  • Перенос существующих приложений, использующих формат завершения чата
  • Вам нужны простые, без отслеживания состояния взаимодействия запросов и ответа
  • Управление состоянием полностью осуществляется вашим клиентом
  • Вы интегрируете с существующими инструментами, поддерживающими только завершение чата
  • Вам нужна максимальная совместимость с устаревшими системами

Агенты хостинга в качестве конечных точек OpenAI (.NET)

Библиотека Microsoft.Agents.AI.Hosting.OpenAI позволяет предоставлять агентов ИИ через интерфейсы HTTP, совместимые с OpenAI, поддерживая API завершения чат-диалогов и ответов. Это позволяет интегрировать агентов с любым клиентом или инструментом, совместимым с OpenAI.

Пакет NuGet:

API завершения чата

API завершения чата предоставляет простой интерфейс без отслеживания состояния для взаимодействия с агентами с помощью стандартного формата чата OpenAI.

Настройка агента в ASP.NET Core с интеграцией ChatCompletions

Вот полный пример демонстрации агента через API завершения чата:

Предпосылки

1. Создание проекта веб-API ASP.NET Core

Создайте проект веб-API ASP.NET Core или используйте существующий.

2. Установка необходимых зависимостей

Установите следующие пакеты:

Выполните следующие команды в каталоге проекта, чтобы установить необходимые пакеты NuGet:

# Hosting.A2A.AspNetCore for OpenAI ChatCompletions/Responses protocol(s) integration
dotnet add package Microsoft.Agents.AI.Hosting.OpenAI --prerelease

# Libraries to connect to Azure OpenAI
dotnet add package Azure.AI.OpenAI --prerelease
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease

# Swagger to test app
dotnet add package Microsoft.AspNetCore.OpenApi
dotnet add package Swashbuckle.AspNetCore

3. Настройка подключения Azure OpenAI

Приложению требуется подключение Azure OpenAI. Настройте конечную точку и имя развертывания, используя dotnet user-secrets или переменные окружения. Вы также можете просто изменить appsettings.jsonфайл, но это не рекомендуется для приложений, развернутых в рабочей среде, так как некоторые данные могут считаться секретами.

dotnet user-secrets set "AZURE_OPENAI_ENDPOINT" "https://<your-openai-resource>.openai.azure.com/"
dotnet user-secrets set "AZURE_OPENAI_DEPLOYMENT_NAME" "gpt-4o-mini"

4. Добавление кода в Program.cs

Замените все содержимое Program.cs следующим кодом:

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();

string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");

// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
    .GetChatClient(deploymentName)
    .AsIChatClient();
builder.Services.AddSingleton(chatClient);

builder.AddOpenAIChatCompletions();

// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");

var app = builder.Build();

app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

// Expose the agent via OpenAI ChatCompletions protocol
app.MapOpenAIChatCompletions(pirateAgent);

app.Run();

Тестирование конечной точки завершения чата

После запуска приложения можно протестировать агент с помощью пакета SDK OpenAI или HTTP-запросов:

Использование HTTP-запроса

POST {{baseAddress}}/pirate/v1/chat/completions
Content-Type: application/json
{
  "model": "pirate",
  "stream": false,
  "messages": [
    {
      "role": "user",
      "content": "Hey mate!"
    }
  ]
}

Примечание. Замените {{baseAddress}} конечной точкой сервера.

Ниже приведен пример ответа:

{
	"id": "chatcmpl-nxAZsM6SNI2BRPMbzgjFyvWWULTFr",
	"object": "chat.completion",
	"created": 1762280028,
	"model": "gpt-5",
	"choices": [
		{
			"index": 0,
			"finish_reason": "stop",
			"message": {
				"role": "assistant",
				"content": "Ahoy there, matey! How be ye farin' on this fine day?"
			}
		}
	],
	"usage": {
		"completion_tokens": 18,
		"prompt_tokens": 22,
		"total_tokens": 40,
		"completion_tokens_details": {
			"accepted_prediction_tokens": 0,
			"audio_tokens": 0,
			"reasoning_tokens": 0,
			"rejected_prediction_tokens": 0
		},
		"prompt_tokens_details": {
			"audio_tokens": 0,
			"cached_tokens": 0
		}
	},
	"service_tier": "default"
}

Ответ содержит идентификатор сообщения, содержимое и статистику использования.

Завершение чата также поддерживает потоковую передачу, где выходные данные возвращаются в блоках, как только содержимое доступно. Эта возможность позволяет постепенно отображать выходные данные. Вы можете включить потоковую передачу, указав "stream": true. Формат выходных данных состоит из блоков Server-Sent Events (SSE), как определено в спецификации завершений чатов OpenAI.

POST {{baseAddress}}/pirate/v1/chat/completions
Content-Type: application/json
{
  "model": "pirate",
  "stream": true,
  "messages": [
    {
      "role": "user",
      "content": "Hey mate!"
    }
  ]
}

А выходные данные, которые мы получаем, — это набор блоков ChatCompletions:

data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[],"object":"chat.completion.chunk","created":0,"model":"gpt-5"}

data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[{"index":0,"finish_reason":"stop","delta":{"content":"","role":"assistant"}}],"object":"chat.completion.chunk","created":0,"model":"gpt-5"}

...

data: {"id":"chatcmpl-xwKgBbFtSEQ3OtMf21ctMS2Q8lo93","choices":[],"object":"chat.completion.chunk","created":0,"model":"gpt-5","usage":{"completion_tokens":34,"prompt_tokens":23,"total_tokens":57,"completion_tokens_details":{"accepted_prediction_tokens":0,"audio_tokens":0,"reasoning_tokens":0,"rejected_prediction_tokens":0},"prompt_tokens_details":{"audio_tokens":0,"cached_tokens":0}}}

Ответ стриминга содержит аналогичную информацию, но в виде событий Server-Sent.

API ответов на запросы

API Ответов предоставляет расширенные возможности, включая управление диалогами, потоковую передачу данных и поддержку длительных агентских процессов.

Настройка агента в ASP.NET Core с интеграцией API ответов

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

Предпосылки

Выполните те же предварительные требования, что и пример завершения чата (шаги 1–3).

4. Добавление кода в Program.cs

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddSwaggerGen();

string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
    ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");

// Register the chat client
IChatClient chatClient = new AzureOpenAIClient(
        new Uri(endpoint),
        new DefaultAzureCredential())
    .GetChatClient(deploymentName)
    .AsIChatClient();
builder.Services.AddSingleton(chatClient);

builder.AddOpenAIResponses();
builder.AddOpenAIConversations();

// Register an agent
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");

var app = builder.Build();

app.MapOpenApi();
app.UseSwagger();
app.UseSwaggerUI();

// Expose the agent via OpenAI Responses protocol
app.MapOpenAIResponses(pirateAgent);
app.MapOpenAIConversations();

app.Run();

Тестирование API ответов

API ответов аналогичен завершениям чатов, но обладает сохранением состояния, что позволяет передавать conversation параметр. Как и завершение чата, он поддерживает параметр stream, который контролирует формат выходных данных: это может быть либо единичный ответ в формате JSON, либо поток событий. API ответов определяет собственные типы событий потоковой передачи, включая response.created, , response.output_item.addedresponse.output_item.doneи response.completedдругие.

Создание беседы и ответа

Вы можете отправить запрос на ответы напрямую или создать беседу с помощью API бесед, а затем связать последующие запросы с этой беседой.

Чтобы начать, создайте новую беседу:

POST http://localhost:5209/v1/conversations
Content-Type: application/json
{
  "items": [
    {
        "type": "message",
        "role": "user",
        "content": "Hello!"
      }
  ]
}

Ответ содержит идентификатор беседы:

{
  "id": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
  "object": "conversation",
  "created_at": 1762881679,
  "metadata": {}
}

Затем отправьте запрос и укажите параметр беседы. (Чтобы получить ответ в виде событий потоковой передачи, задайте "stream": true в запросе.)

POST http://localhost:5209/pirate/v1/responses
Content-Type: application/json
{
  "stream": false,
  "conversation": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
  "input": [
    {
      "type": "message",
      "role": "user",
      "content": [
        {
            "type": "input_text",
            "text": "are you a feminist?"
        }
      ]
    }
  ]
}

Агент возвращает ответ и сохраняет элементы беседы в хранилище для последующего получения:

{
  "id": "resp_FP01K4bnMsyQydQhUpovK6ysJJroZMs1pnYCUvEqCZqGCkac",
  "conversation": "conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y",
  "object": "response",
  "created_at": 1762881518,
  "status": "completed",
  "incomplete_details": null,
  "output": [
    {
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "Arrr, matey! As a pirate, I be all about respect for the crew, no matter their gender! We sail these seas together, and every hand on deck be valuable. A true buccaneer knows that fairness and equality be what keeps the ship afloat. So, in me own way, I’d say I be supportin’ all hearty souls who seek what be right! What say ye?"
        }
      ],
      "type": "message",
      "status": "completed",
      "id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y"
    }
  ],
  "usage": {
    "input_tokens": 26,
    "input_tokens_details": {
      "cached_tokens": 0
    },
    "output_tokens": 85,
    "output_tokens_details": {
      "reasoning_tokens": 0
    },
    "total_tokens": 111
  },
  "tool_choice": null,
  "temperature": 1,
  "top_p": 1  
}

Ответ содержит идентификаторы бесед и сообщений, содержимое и статистику использования.

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

GET http://localhost:5209/v1/conversations/conv_E9Ma6nQpRzYxRHxRRqoOWWsDjZVyZfKxlHhfCf02Yxyy9N2y/items?include=string

Возвращается ответ JSON, содержащий как входные, так и выходные сообщения:

{
  "object": "list",
  "data": [
    {
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "Arrr, matey! As a pirate, I be all about respect for the crew, no matter their gender! We sail these seas together, and every hand on deck be valuable. A true buccaneer knows that fairness and equality be what keeps the ship afloat. So, in me own way, I’d say I be supportin’ all hearty souls who seek what be right! What say ye?",
          "annotations": [],
          "logprobs": []
        }
      ],
      "type": "message",
      "status": "completed",
      "id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y"
    },
    {
      "role": "user",
      "content": [
        {
          "type": "input_text",
          "text": "are you a feminist?"
        }
      ],
      "type": "message",
      "status": "completed",
      "id": "msg_iLVtSEJL0Nd2b3ayr9sJWeV9VyEASMlilHhfCf02Yxyy9N2y"
    }
  ],
  "first_id": "msg_1FAQyZcWgsBdmgJgiXmDyavWimUs8irClHhfCf02Yxyy9N2y",
  "last_id": "msg_lUpquo0Hisvo6cLdFXMKdYACqFRWcFDrlHhfCf02Yxyy9N2y",
  "has_more": false
}

Выявление нескольких агентов

Вы можете задействовать нескольких агентов одновременно, используя оба протокола.

var mathAgent = builder.AddAIAgent("math", instructions: "You are a math expert.");
var scienceAgent = builder.AddAIAgent("science", instructions: "You are a science expert.");

// Add both protocols
builder.AddOpenAIChatCompletions();
builder.AddOpenAIResponses();

var app = builder.Build();

// Expose both agents via Chat Completions
app.MapOpenAIChatCompletions(mathAgent);
app.MapOpenAIChatCompletions(scienceAgent);

// Expose both agents via Responses
app.MapOpenAIResponses(mathAgent);
app.MapOpenAIResponses(scienceAgent);

Агенты будут доступны по адресу:

  • Завершение чата: /math/v1/chat/completions и /science/v1/chat/completions
  • Ответы: /math/v1/responses и /science/v1/responses

Пользовательские конечные точки

Пути конечных точек можно настроить:

// Custom path for Chat Completions
app.MapOpenAIChatCompletions(mathAgent, path: "/api/chat");

// Custom path for Responses
app.MapOpenAIResponses(scienceAgent, responsesPath: "/api/responses");

Подключение к конечным точкам, совместимым с OpenAI (Python)

Python OpenAIChatCompletionClient и OpenAIChatClient поддерживают параметр base_url, позволяя подключаться к любой конечной точке, совместимой с OpenAI, включая самостоятельно размещенные агенты, локальные серверы вывода (Ollama, LM Studio, vLLM) или сторонние интерфейсы API, совместимые с OpenAI.

pip install agent-framework

Клиент завершения чата

Используйте OpenAIChatCompletionClient и base_url для указания на любой сервер, совместимый с завершением чата.

import asyncio
from agent_framework import tool
from agent_framework.openai import OpenAIChatCompletionClient

@tool(approval_mode="never_require")
def get_weather(location: str) -> str:
    """Get the weather for a location."""
    return f"Weather in {location}: sunny, 22°C"

async def main():
    # Point to any OpenAI-compatible endpoint
    agent = OpenAIChatCompletionClient(
        base_url="http://localhost:11434/v1/",  # e.g. Ollama
        api_key="not-needed",                   # placeholder for local servers
        model="llama3.2",
    ).as_agent(
        name="WeatherAgent",
        instructions="You are a helpful weather assistant.",
        tools=get_weather,
    )

    response = await agent.run("What's the weather in Seattle?")
    print(response)

asyncio.run(main())

Клиент для ответов

Используйте OpenAIChatClient вместе с base_url для конечных точек, поддерживающих API ответов:

import asyncio
from agent_framework.openai import OpenAIChatClient

async def main():
    agent = OpenAIChatClient(
        base_url="https://your-hosted-agent.example.com/v1/",
        api_key="your-api-key",
        model="gpt-4o-mini",
    ).as_agent(
        name="Assistant",
        instructions="You are a helpful assistant.",
    )

    # Non-streaming
    response = await agent.run("Hello!")
    print(response)

    # Streaming
    async for chunk in agent.run("Tell me a joke", stream=True):
        if chunk.text:
            print(chunk.text, end="", flush=True)

asyncio.run(main())

Общие серверы, совместимые с OpenAI

Подход base_url работает с любым сервером, предоставляющим формат завершения чата OpenAI:

Сервер Базовый URL-адрес Примечания.
Ollama http://localhost:11434/v1/ Локальная инференция, ключ API не требуется
LM Studio http://localhost:1234/v1/ Локальный инференс с графическим интерфейсом
vLLM http://localhost:8000/v1/ Обслуживание с высокой пропускной способностью
Microsoft Foundry Конечная точка развертывания Использование учетных данных Azure
Агенты платформы Hosted Agent Framework Конечная точка агента Агенты .NET, доступные через MapOpenAIChatCompletions

Замечание

Можно также задать OPENAI_BASE_URL переменную среды вместо передачи base_url напрямую. Клиент будет использовать его автоматически.

Использование клиентов Azure OpenAI

Используйте те же универсальные клиенты OpenAI для Azure OpenAI, передав явные входные данные маршрутизации Azure вместо base_url.

import os
from agent_framework.openai import OpenAIChatClient
from azure.identity import AzureCliCredential

agent = OpenAIChatClient(
    model=os.environ["AZURE_OPENAI_CHAT_MODEL"],
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
    credential=AzureCliCredential(),
).as_agent(
    name="Assistant",
    instructions="You are a helpful assistant.",
)

Настройка с переменными среды:

export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_CHAT_MODEL="gpt-4o-mini"
export AZURE_OPENAI_API_VERSION="your-api-version"

OpenAIChatClient предпочитает AZURE_OPENAI_CHAT_MODEL; AZURE_OPENAI_MODEL остается общим резервным вариантом, если вам нужен один.

См. также

Дальнейшие шаги