Dela via


OpenAI-kompatibla gränssnitt

Agent Framework stöder OpenAI-kompatibla protokoll för både värdagenter bakom standard-API:er och anslutning till alla OpenAI-kompatibla slutpunkter.

Vad är OpenAI-protokoll?

Två OpenAI-protokoll stöds:

  • API för slutförande av chatt – Standardtillståndslöst format för begäran/svar för chattinteraktioner
  • Svars-API – Avancerat format som stöder konversationer, strömning och långvariga agentprocesser

Svars-API:et är nu standardmetoden och rekommenderas enligt OpenAI:s dokumentation. Det ger ett mer omfattande och funktionsrikt gränssnitt för att skapa AI-program med inbyggd konversationshantering, strömningsfunktioner och stöd för långvariga processer.

Använd svars-API :et när:

  • Skapa nya program (rekommenderas som standard)
  • Du behöver konversationshantering på serversidan. Det är dock inte ett krav: du kan fortfarande använda svars-API i tillståndslöst läge.
  • Du vill ha beständig konversationshistorik
  • Du skapar bestående agentprocesser
  • Du behöver avancerade strömningsfunktioner med detaljerade händelsetyper
  • Du vill spåra och hantera enskilda svar (t.ex. hämta ett specifikt svar efter ID, kontrollera dess status eller avbryta ett svar som körs)

Använd API:et för chattens slutförande när:

  • Migrering av befintliga applikationer som förlitar sig på chattkompletteringsformatet
  • Du behöver enkla, tillståndslösa begäran/svar-interaktioner
  • Tillståndshantering hanteras helt av din klientapplikation
  • Du integrerar med befintliga verktyg som endast stöder chattavslutningar
  • Du behöver maximal kompatibilitet med äldre system

Värdagenter som OpenAI-slutpunkter (.NET)

Med Microsoft.Agents.AI.Hosting.OpenAI biblioteket kan du exponera AI-agenter via OpenAI-kompatibla HTTP-slutpunkter, med stöd för både API:er för chatt och svar. På så sätt kan du integrera dina agenter med alla OpenAI-kompatibla klienter eller verktyg.

NuGet-paket:

API för chattens slutförande

API:et för chattslutföranden tillhandahåller ett enkelt, tillståndslöst gränssnitt för att interagera med agenter med OpenAIs standardchattformat.

Konfigurera en agent i ASP.NET Core med ChatCompletions-integrering

Här är ett fullständigt exempel som exponerar en agent via API:et för chattavslut:

Förutsättningar

1. Skapa ett ASP.NET Core Web API-projekt

Skapa ett nytt ASP.NET Core Web API-projekt eller använd ett befintligt.

2. Installera nödvändiga beroenden

Installera följande paket:

Kör följande kommandon i projektkatalogen för att installera nödvändiga NuGet-paket:

# 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. Konfigurera Azure OpenAI-anslutning

Programmet kräver en Azure OpenAI-anslutning. Konfigurera slutpunkten och distributionsnamnet med hjälp av dotnet user-secrets eller miljövariabler. Du kan också redigera appsettings.json, men det rekommenderas inte för de appar som distribueras i produktion eftersom vissa data kan anses vara hemliga.

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. Lägg till koden i Program.cs

Ersätt innehållet i Program.cs med följande kod:

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

Testa slutpunkten för chattens slutförande

När programmet körs kan du testa agenten med hjälp av OpenAI SDK- eller HTTP-begäranden:

Använda HTTP-begäran

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

Obs! Ersätt {{baseAddress}} med serverslutpunkten.

Här är ett exempelsvar:

{
	"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"
}

Svaret innehåller meddelande-ID, innehåll och användningsstatistik.

Chattavslut stöder också strömning, där utdata returneras i segment så snart innehåll är tillgängligt. Med den här funktionen kan du visa utdata progressivt. Du kan aktivera direktuppspelning genom att ange "stream": true. Utdataformatet består av segment för Server-Sent händelser (SSE) enligt definitionen i specifikationen för OpenAI Chat Completions.

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

Och de utdata vi får är en uppsättning ChatCompletions-segment:

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

Strömningssvaret innehåller liknande information, men levereras som Server-Sent Händelser.

API för svar

Svars-API:et innehåller avancerade funktioner som konversationshantering, strömning och stöd för långvariga agentprocesser.

Konfigurera en agent i ASP.NET Core med API-integrering för svar

Här är ett fullständigt exempel med svars-API:et:

Förutsättningar

Följ samma krav som exemplet med chattavslut (steg 1–3).

4. Lägg till koden i 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();

Testa svars-API:et

Svars-API:et liknar Chattslutföranden men är tillståndskänsligt, vilket gör att du kan skicka en conversation-parameter. Precis som Chattsvar stöder den parametern stream, som styr utdataformatet: antingen ett enda JSON-svar eller en ström av händelser. Svars-API:et definierar sina egna typer av strömningshändelser, inklusive response.created, response.output_item.added, response.output_item.done, response.completedoch andra.

Skapa en konversation och ett svar

Du kan skicka en begäran om svar direkt, eller så kan du först skapa en konversation med hjälp av API:et Konversationer och sedan länka efterföljande begäranden till konversationen.

Börja med att skapa en ny konversation:

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

Svaret innehåller konversations-ID:

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

Skicka sedan en begäran och ange konversationsparametern. (Om du vill ta emot svaret som strömmande händelser anger du "stream": true i begäran.)

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?"
        }
      ]
    }
  ]
}

Agenten returnerar svaret och sparar konversationsobjekten till lagring för senare hämtning:

{
  "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  
}

Svaret innehåller konversations- och meddelandeidentifierare, innehåll och användningsstatistik.

Om du vill hämta konversationsobjekten skickar du den här begäran:

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

Detta returnerar ett JSON-svar som innehåller både indata- och utdatameddelanden:

{
  "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
}

Exponera flera agenter

Du kan exponera flera agenter samtidigt med båda protokollen:

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

Agenter kommer att vara tillgängliga på:

  • Chatten har slutförts: /math/v1/chat/completions och /science/v1/chat/completions
  • Svar: /math/v1/responses och /science/v1/responses

Anpassade ändpunkter

Du kan anpassa slutpunktssökvägarna:

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

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

Ansluta till OpenAI-kompatibla slutpunkter (Python)

Python OpenAIChatClient och OpenAIResponsesClient båda stöder en base_url parameter så att du kan ansluta till alla OpenAI-kompatibla slutpunkter – inklusive lokalt installerade agenter, lokala slutsatsdragningsservrar (Ollama, LM Studio, vLLM) eller OpenAI-kompatibla API:er från tredje part.

pip install agent-framework --pre

Klient för chattens slutförande

Använd OpenAIChatClient med base_url för att peka på valfri server som är kompatibel med chatten:

import asyncio
from agent_framework import tool
from agent_framework.openai import OpenAIChatClient

@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 = OpenAIChatClient(
        base_url="http://localhost:11434/v1/",  # e.g. Ollama
        api_key="not-needed",                   # placeholder for local servers
        model_id="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())

Svarsklient

Använd OpenAIResponsesClient med base_url för slutpunkter som stöder svars-API:et:

import asyncio
from agent_framework.openai import OpenAIResponsesClient

async def main():
    agent = OpenAIResponsesClient(
        base_url="https://your-hosted-agent.example.com/v1/",
        api_key="your-api-key",
        model_id="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())

Vanliga OpenAI-Compatible servrar

Metoden base_url fungerar med alla servrar som exponerar formatet OpenAI Chat Completions:

Server Bas-webbadress Noteringar
Ollama http://localhost:11434/v1/ Lokal slutsatsdragning, ingen API-nyckel behövs
LM Studio http://localhost:1234/v1/ Lokal slutsatsdragning med GUI
vLLM http://localhost:8000/v1/ Server för hög genomströmning
Microsoft Foundry Din implementeringsslutpunkt Använder Azure-autentiseringsuppgifter
Värdbaserade Agent Framework-agenter Din agentslutpunkt .NET-agenter som exponeras via MapOpenAIChatCompletions

Anmärkning

Du kan också ange OPENAI_BASE_URL miljövariabeln i stället för att skicka base_url direkt. Klienten använder den automatiskt.

Använda Azure OpenAI-klienter

Azure OpenAI-varianterna (AzureOpenAIChatClient, AzureOpenAIResponsesClient) ansluter till Azure OpenAI-slutpunkter med azure-autentiseringsuppgifter – behövs inte base_url :

from agent_framework.azure import AzureOpenAIResponsesClient

agent = AzureOpenAIResponsesClient().as_agent(
    name="Assistant",
    instructions="You are a helpful assistant.",
)

Konfigurera med miljövariabler:

export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"
export AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME="gpt-4o-mini"

Se även

Nästa steg