使用 Azure OpenAI 回應 API 來產生有狀態、多回合的回應。 它將聊天完成功能與助理 API 整合於一個統一體驗中。 使用 多代理協調 將獨立工作委派給平行運作的子代理,或使用 工具搜尋,僅在模型需要時才載入工具定義。 回應 API 也支援驅動電腦使用的computer-use-preview模式。
欲了解完整的請求與回應參數描述,請參閱 回應 API 參數參考。
先決條件
- 一個已部署的 Azure OpenAI 模型。
- 一種認證方法:
- API 金鑰(例如,
AZURE_OPENAI_API_KEY),或
- Microsoft Entra ID(推薦)。
- 安裝你語言的客戶端函式庫:
-
Python:
pip install openai azure-identity
-
.NET:
dotnet add package OpenAI 和 dotnet add package Azure.Identity
-
JavaScript/TypeScript:
npm install openai @azure/identity
-
Java:在專案中加入
com.openai:openai-java和com.azure:azure-identity。
- 以 REST 為例,設定
AZURE_OPENAI_API_KEY(API 金鑰流程)或 AZURE_OPENAI_AUTH_TOKEN(Microsoft Entra ID 流程)。
支援的區域
在執行本文範例前,請確認你的資源區域是否支援 Responses API。 必須使用 v1 API 才能存取最新功能。 詳情請參閱 API 版本生命週期。 關於 Foundry Agent Service 的區域支援,請參閱 區域可用性表。 回應 API 目前可在以下地區使用:
- 澳洲東部
- 巴西南部
- 加拿大中央
- 加拿大東部
- centralus
- 伊斯特斯
- eastus2
- francecentral
- 德國-西中部
- 義大利北方
- 日本東部
- japanwest
- koreacentral
- northcentralus
- 挪威東部
- 波蘭中央
- southafricanorth
- 美國中南部
- 東南亞
- 南印度
- 西班牙中心
- swedencentral
- switzerlandnorth
- switzerlandwest
- uaenorth
- UKSOUTH
- ukwest
- westcentralus
- 西歐
- westus
- westus2
- westus3
支援的模型
回應 API 支援以下模型:
-
gpt-6.1-terra (版本: 2026-10-26)
-
gpt-6.1-sol (版本: 2026-09-29)
-
gpt-6-luna (版本: 2026-09-22)
-
gpt-6-sol (版本: 2026-09-22)
-
gpt-6-astra (版本: 2026-09-03)
-
gpt-5.6-sol (版本: 2026-07-09)
-
gpt-5.6-terra (版本: 2026-07-09)
-
gpt-5.6-luna (版本: 2026-07-09)
-
gpt-chat-latest(版本:2026-10-07, 2026-08-06, 2026-06-24, 2026-05-28, 2026-05-05)
-
gpt-5.5 (版本: 2026-04-24)
-
gpt-5.4-nano (版本: 2026-03-17)
-
gpt-5.4-mini (版本: 2026-03-17)
-
gpt-5.4-pro (版本:2026-03-05)
-
gpt-5.4 (版本:2026-03-05)
-
gpt-5.3-chat (版本: 2026-03-03)
-
gpt-5.3-codex (版本: 2026-02-24)
-
gpt-5.2-codex (版本: 2026-01-14)
-
gpt-5.2 (版本: 2025-12-11)
-
gpt-5.2-chat (版本: 2025-12-11)
-
gpt-5.2-chat (版本: 2026-02-10)
-
gpt-5.1-codex-max (版本: 2025-12-04)
-
gpt-5.1 (版本: 2025-11-13)
-
gpt-5.1-chat (版本: 2025-11-13)
-
gpt-5.1-codex (版本: 2025-11-13)
-
gpt-5.1-codex-mini (版本: 2025-11-13)
-
gpt-5-pro (版本: 2025-10-06)
-
gpt-5-codex (版本: 2025-09-11)
-
gpt-5 (版本: 2025-08-07)
-
gpt-5-mini (版本: 2025-08-07)
-
gpt-5-nano (版本: 2025-08-07)
-
gpt-5-chat (版本: 2025-08-07)
-
gpt-5-chat (版本: 2025-10-03)
-
gpt-5-codex (版本: 2025-09-15)
-
gpt-4o(版本:2024-11-20、、2024-08-062024-05-13)
-
gpt-4o-mini (版本: 2024-07-18)
computer-use-preview
-
gpt-4.1 (版本: 2025-04-14)
-
gpt-4.1-nano (版本: 2025-04-14)
-
gpt-4.1-mini (版本: 2025-04-14)
-
gpt-image-1 (版本: 2025-04-15)
-
gpt-image-1-mini (版本: 2025-10-06)
-
gpt-image-1.5 (版本: 2025-12-16)
-
gpt-image-2.5-flare (版本: 2026-09-09)
-
gpt-image-2.5-sunburst (版本: 2026-09-09)
-
o1 (版本: 2024-12-17)
-
o3-mini (版本: 2025-01-31)
-
o3 (版本: 2025-04-16)
-
o4-mini (版本: 2025-04-16)
並非所有型號都能在所有支援地區取得。 請查看 模型頁面 以了解模型區域的可用性。
註
目前不支援:
以下有一個已知的問題:
-
現在支援 PDF 作為輸入檔,但目前不支援將檔案上傳目的設定為 。
user_data
- 當背景模式搭配串流時,效能會有問題。 Microsoft 正在努力解決這個問題。
產生文字回應
使用 Responses API 產生一個簡單的文字回應。 用你的部署值替換 YOUR-RESOURCE-NAME 和 MODEL_NAME 。
import os
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
# API key authentication
client = OpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
)
response = client.responses.create(
model="MODEL_NAME",
input="This is a test."
)
print(response.model_dump_json(indent=2))
# Microsoft Entra ID authentication (recommended)
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=token_provider(),
)
response = client.responses.create(
model="MODEL_NAME",
input="This is a test."
)
print(response.model_dump_json(indent=2))
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("This is a test.") }
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import { OpenAI } from "openai";
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
const endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/";
// API key authentication
const openai = new OpenAI({
baseURL: endpoint,
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await openai.responses.create({
model: "MODEL_NAME",
input: "This is a test."
});
console.log(response.output_text);
// Microsoft Entra ID authentication (recommended)
const tokenProvider = getBearerTokenProvider(
new DefaultAzureCredential(),
"https://ai.azure.com/.default"
);
const openaiEntra = new OpenAI({
baseURL: endpoint,
apiKey: await tokenProvider(),
});
const responseEntra = await openaiEntra.responses.create({
model: "MODEL_NAME",
input: "This is a test."
});
console.log(responseEntra.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
// Microsoft Entra ID authentication (recommended)
OpenAIClient openAIClientEntra = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(BearerTokenCredential.create(
AuthenticationUtil.getBearerTokenSupplier(
new DefaultAzureCredentialBuilder().build(),
"https://ai.azure.com/.default")))
.build();
ResponseCreateParams params = ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("This is a test.")
.build();
Response response = openAIClient.responses().create(params);
System.out.println(response.outputText());
Microsoft Entra ID
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AZURE_OPENAI_AUTH_TOKEN" \
-d '{
"model": "MODEL_NAME",
"input": "This is a test."
}'
API 金鑰
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "This is a test."
}'
範例回應
{
"id": "resp_67cb32528d6881909eb2859a55e18a85",
"created_at": 1741369938.0,
"output_text": "Great! How can I help you today?",
...
}
檢索回應
從先前的回應 API 呼叫中,依其 ID 檢索回應。
import os
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
# API key authentication
client = OpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
)
response = client.responses.retrieve("<response_id>")
print(response.model_dump_json(indent=2))
# Microsoft Entra ID authentication
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=token_provider,
)
response = client.responses.retrieve("<response_id>")
print(response.model_dump_json(indent=2))
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
string responseId = "<response_id>";
ResponseResult response = await openAIClient.GetResponseAsync(responseId);
Console.WriteLine(response.GetOutputText());
import { OpenAI } from "openai";
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
const endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/";
// API key authentication
const openai = new OpenAI({
baseURL: endpoint,
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await openai.responses.retrieve("<response_id>");
console.log(response.output_text);
// Microsoft Entra ID authentication
const tokenProvider = getBearerTokenProvider(
new DefaultAzureCredential(),
"https://ai.azure.com/.default"
);
const openaiEntra = new OpenAI({
baseURL: endpoint,
apiKey: await tokenProvider(),
});
const responseEntra = await openaiEntra.responses.retrieve("<response_id>");
console.log(responseEntra.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
// Microsoft Entra ID authentication
OpenAIClient openAIClientEntra = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(BearerTokenCredential.create(
AuthenticationUtil.getBearerTokenSupplier(
new DefaultAzureCredentialBuilder().build(),
"https://ai.azure.com/.default")))
.build();
Response response = openAIClient.responses().retrieve("<response_id>");
System.out.println(response.outputText());
Microsoft Entra ID
curl -X GET https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id> \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AZURE_OPENAI_AUTH_TOKEN"
API 金鑰
curl -X GET https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id> \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
範例回應
{
"id": "resp_67cb61fa3a448190bcf2c42d96f0d1a8",
"output_text": "Hello! How can I assist you today?",
...
}
刪除回應
預設情況下,回應資料會保留30天。 依 ID 刪除已儲存的回應。
import os
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
# API key authentication
client = OpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
)
response = client.responses.delete("<response_id>")
print(response)
# Microsoft Entra ID authentication
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=token_provider,
)
response = client.responses.delete("<response_id>")
print(response)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
string responseId = "<response_id>";
var result = await openAIClient.DeleteResponseAsync(responseId);
Console.WriteLine(result); // result.Deleted == true if successful
import { OpenAI } from "openai";
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
const endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/";
// API key authentication
const openai = new OpenAI({
baseURL: endpoint,
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const result = await openai.responses.delete("<response_id>");
console.log(result);
// Microsoft Entra ID authentication
const tokenProvider = getBearerTokenProvider(
new DefaultAzureCredential(),
"https://ai.azure.com/.default"
);
const openaiEntra = new OpenAI({
baseURL: endpoint,
apiKey: await tokenProvider(),
});
const resultEntra = await openaiEntra.responses.delete("<response_id>");
console.log(resultEntra);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
// Microsoft Entra ID authentication
OpenAIClient openAIClientEntra = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(BearerTokenCredential.create(
AuthenticationUtil.getBearerTokenSupplier(
new DefaultAzureCredentialBuilder().build(),
"https://ai.azure.com/.default")))
.build();
Response result = openAIClient.responses().delete("<response_id>");
System.out.println(result);
Microsoft Entra ID
curl -X DELETE https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id> \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AZURE_OPENAI_AUTH_TOKEN"
API 金鑰
curl -X DELETE https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id> \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
儲存回應資料的加密
當 Responses API 持久保存訊息歷程記錄和相關內容時,該服務會對該內容進行靜態加密。 有關儲存加密的說明,請參閱 Microsoft Foundry 中由 Azure 銷售的模型的資料、隱私與安全性。 關於 CMK 的覆蓋範圍與前置條件,請參見 Microsoft Foundry 中的客戶管理金鑰加密。
此加密與您使用 store=false 管理交談狀態時傳回應用程式的加密推理項目不同。
將回應串連起來
鍊結傳回的方式是將先前的回覆識別碼傳遞給previous_response_id。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
first_response = client.responses.create(
model="MODEL_NAME",
input="Define catastrophic forgetting."
)
second_response = client.responses.create(
model="MODEL_NAME",
previous_response_id=first_response.id,
input="Explain it for a college freshman."
)
print(second_response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions firstOptions = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("Define and explain the concept of catastrophic forgetting?") }
};
ResponseResult firstResponse = await openAIClient.CreateResponseAsync(firstOptions);
Console.WriteLine(firstResponse.GetOutputText());
CreateResponseOptions secondOptions = new()
{
Model = "MODEL_NAME",
PreviousResponseId = firstResponse.Id,
InputItems = { ResponseItem.CreateUserMessageItem("Explain this at a level that could be understood by a college freshman") }
};
ResponseResult secondResponse = await openAIClient.CreateResponseAsync(secondOptions);
Console.WriteLine(secondResponse.GetOutputText());
import { OpenAI } from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const firstResponse = await client.responses.create({
model: "MODEL_NAME",
input: "Define catastrophic forgetting."
});
const secondResponse = await client.responses.create({
model: "MODEL_NAME",
previous_response_id: firstResponse.id,
input: "Explain it for a college freshman."
});
console.log(secondResponse.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Response first = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("Define and explain the concept of catastrophic forgetting?")
.build());
Response second = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.previousResponseId(first.id())
.input("Explain this at a level that could be understood by a college freshman.")
.build());
second.output().stream()
.flatMap(item -> item.message().stream())
.flatMap(m -> m.content().stream())
.flatMap(c -> c.outputText().stream())
.forEach(t -> System.out.println(t.text()));
# First turn
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "Define catastrophic forgetting."
}'
# Follow-up turn using previous_response_id from the first call
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"previous_response_id": "<response_id>",
"input": "Explain it for a college freshman."
}'
手動串接回應
或者,您也可以在下一個請求中手動轉轉輸出項目。
import os
from openai import OpenAI
client = OpenAI(
base_url = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
inputs = [{"type": "message", "role": "user", "content": "Define and explain the concept of catastrophic forgetting?"}]
response = client.responses.create(
model="gpt-4o", # replace with your model deployment name
input=inputs
)
inputs += response.output
inputs.append({"role": "user", "type": "message", "content": "Explain this at a level that could be understood by a college freshman"})
second_response = client.responses.create(
model="MODEL_NAME",
input=inputs
)
print(second_response.model_dump_json(indent=2))
壓縮回應
壓縮減少輸入上下文,同時保留後續回合的本質狀態。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
compacted = client.responses.compact(
model="MODEL_NAME",
input=[
{"role": "user", "content": "Create a simple landing page for a dog cafe."},
{
"id": "msg_001",
"type": "message",
"status": "completed",
"role": "assistant",
"content": [{"type": "output_text", "text": "..."}],
},
]
)
follow_up = client.responses.create(
model="MODEL_NAME",
input=[*compacted.output, {"role": "user", "content": "Add a booking form."}]
)
print(follow_up.output_text)
註
.NET SDK 目前尚未提供對回覆壓縮提供強類型的 Surface。 請參考 REST 標籤中的呼叫形狀,或直接用 BinaryContent JSON 呼叫協定方法。
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const compacted = await client.responses.compact({
model: "MODEL_NAME",
input: [
{ role: "user", content: "Create a simple landing page for a dog cafe." },
{
id: "msg_001",
type: "message",
status: "completed",
role: "assistant",
content: [{ type: "output_text", text: "..." }],
},
],
});
const followUp = await client.responses.create({
model: "MODEL_NAME",
input: [...compacted.output, { role: "user", content: "Add a booking form." }],
});
console.log(followUp.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.CompactedResponse;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCompactParams;
import com.openai.models.responses.ResponseCreateParams;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Response initial = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("Create a simple landing page for a dog cafe.")
.build());
CompactedResponse compacted = openAIClient.responses().compact(
ResponseCompactParams.builder()
.model("MODEL_NAME")
.previousResponseId(initial.id())
.build());
Response followUp = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.previousResponseId(compacted.id())
.input("Add a booking form.")
.build());
System.out.println(followUp.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/compact \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{"role": "user", "content": "Create a simple landing page for a dog cafe."},
{
"id": "msg_001",
"type": "message",
"status": "completed",
"role": "assistant",
"content": [{"type": "output_text", "text": "..."}]
}
]
}'
使用返回的項目進行壓縮
你可以壓縮所有來自先前請求的內容,例如推理、訊息、函式呼叫等。
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/compact \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $AZURE_OPENAI_AUTH_TOKEN" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role" : "user",
"content": "Create a simple landing page for a dog petting café."
},
{
"id": "msg_001",
"type": "message",
"status": "completed",
"content": [
{
"type": "output_text",
"annotations": [],
"logprobs": [],
"text": "Below is a single file, ready-to-use landing page for a dog petting café:..."
}
],
"role": "assistant"
}
]
}'
# Use the compacted output as input for the next turn.
next_response = client.responses.create(
model="MODEL_NAME",
input=[*compacted.output, {"role": "user", "content": "Add opening hours."}],
)
print(next_response.output_text)
使用先前的回應 ID 壓縮
你也可以用先前的回應 ID 來壓縮。
initial_response = client.responses.create(
model="MODEL_NAME",
input="What is the size of France?"
)
compacted_response = client.responses.compact(
model="MODEL_NAME",
previous_response_id=initial_response.id
)
follow_up_response = client.responses.create(
model="MODEL_NAME",
input=[
*compacted_response.output,
{"role": "user", "content": "What is the capital?"}
]
)
print(follow_up_response.output_text)
伺服器端壓縮
你也可以直接在回應POST /responses或client.responses.create中使用伺服器端壓縮,透過設定context_managementcompact_threshold。
- 當輸出令牌數超過設定的門檻時,回應 API 會自動執行壓縮。
- 在此模式下,您不需要單獨執行
/responses/compact。
- 回應包含一個加密的壓縮項目。
- 當您在「Responses創建請求」中設定store=false時,伺服器端壓縮會生效。
壓縮項目會將必要的先前狀態與推理,延續到下一回合,同時使用較少的詞元。 它不透明,並非設計給人類閱讀。
如果你使用無狀態輸入陣列鏈,請像平常一樣附加輸出項目。 如果你用的是 previous_response_id,每回合只傳遞新用戶訊息。 在這兩種模式中,壓縮項目都包含下一個視窗所需的上下文。
提示
在將輸出項目附加到前一個輸入項目後,你可以刪除最近壓縮項目之前的項目,以減少請求並降低長尾延遲。 最新的壓縮項目會攜帶繼續交談所需的必要內容。 如果你使用previous_response_id 串接,請不要手動修剪。
Flow
- 照常打電話
responses 。 添加 context_management 合併 compact_threshold 來啟用伺服器端壓縮。
- 若輸出超過閾值,服務會觸發緊縮,在輸出流中發送壓縮項目,並在繼續推理前修整上下文。
- 請使用下列其中一種模式來繼續交談:
- 無狀態輸入陣列鏈接:將輸出項目(包括壓縮項目)附加到下一個輸入陣列。
-
previous_response_id 鏈結:每一回合只傳遞新的使用者訊息,並將最新的回應識別碼往後延續。
範例
conversation = [
{
"type": "message",
"role": "user",
"content": "Let's begin a long coding task.",
}
]
while keep_going:
response = client.responses.create(
model="MODEL_NAME",
input=conversation,
store=False,
context_management=[{"type": "compaction", "compact_threshold": 200000}],
)
conversation.append(
{
"type": "message",
"role": "user",
"content": get_next_user_input(),
}
)
串流
透過設定 stream=true來串流回應產生的過程。 該服務會發出增量事件,您可以使用它來逐詞元來呈現輸出。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
stream = client.responses.create(
model="MODEL_NAME",
input="Summarize Azure OpenAI Responses API in one sentence.",
stream=True,
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="")
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("Summarize Azure OpenAI Responses API in one sentence.") },
StreamingEnabled = true
};
await foreach (StreamingResponseUpdate update in openAIClient.CreateResponseStreamingAsync(options))
{
if (update is StreamingResponseOutputTextDeltaUpdate textDelta)
{
Console.Write(textDelta.Delta);
}
else if (update is StreamingResponseCompletedUpdate completed)
{
Console.WriteLine();
Console.WriteLine($"[done] response id: {completed.Response.Id}");
}
}
import { OpenAI } from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const stream = await client.responses.create({
model: "MODEL_NAME",
input: "Summarize Azure OpenAI Responses API in one sentence.",
stream: true,
});
for await (const event of stream) {
if (event.type === "response.output_text.delta") {
process.stdout.write(event.delta);
}
}
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseStreamEvent;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
ResponseCreateParams params = ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("This is a test")
.build();
try (StreamResponse<ResponseStreamEvent> stream = openAIClient.responses().createStreaming(params)) {
stream.stream()
.flatMap(event -> event.outputTextDelta().stream())
.forEach(delta -> System.out.print(delta.delta()));
}
curl -N -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "Summarize Azure OpenAI Responses API in one sentence.",
"stream": true
}'
在串流過程中,若中段發生錯誤,系統會嘗試內部重試以解決錯誤。 如果請求仍然失敗,服務會遇到無法恢復的錯誤。 在這些情況下,HTTP 回應碼為 200(成功),但串流中的錯誤事件包含中游錯誤的詳細資訊。
伺服器回傳以下錯誤類型:
| 錯誤類型 |
可翻譯為 |
server_error |
回傳代碼 500 |
too_many_requests |
回傳代碼 429 |
forbidden |
回傳代碼 403 |
user_error |
回傳代碼 400 |
範例錯誤事件:
{
"type": "error",
"error": {
"type": "too_many_requests",
"code": "no_capacity",
"headers": {
"skip-error-remapping": "true"
},
"message": "The system is currently experiencing high demand and cannot process your request. Your request exceeds the maximum usage size allowed during peak load. For improved capacity reliability, consider switching to Provisioned Throughput.",
"param": null
}
}
應用程式應該能偵測這些錯誤,並優雅地停止或重新啟動串流。 串流回應失敗期間產生的詞元不會向您收費。
結構化輸出
使用結構化輸出來讓回應遵循 JSON 架構。 在回應 API 請求中,請在 中定義結構 text.format。 聊天完成功能則是用 response_format 來代替的。 關於 SDK 與 REST 範例、支援的結構限制與限制,請參見 結構化輸出。
函式呼叫
回應 API 支援函式呼叫。
import os
import json
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
tools=[
{
"type": "function",
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
}
],
input="What is the weather in San Francisco?",
)
tool_outputs = []
for item in response.output:
if item.type == "function_call" and item.name == "get_weather":
args = json.loads(item.arguments)
weather = {"location": args["location"], "temperature": "70 F"}
tool_outputs.append(
{
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(weather),
}
)
final_response = client.responses.create(
model="MODEL_NAME",
previous_response_id=response.id,
input=tool_outputs,
)
print(final_response.output_text)
#pragma warning disable OPENAI001
using System.Text.Json;
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
FunctionTool getWeatherTool = ResponseTool.CreateFunctionTool(
functionName: "get_weather",
functionParameters: BinaryData.FromBytes("""
{
"type": "object",
"properties": {
"location": { "type": "string", "description": "The city, e.g. Boston, MA" }
},
"required": ["location"]
}
"""u8.ToArray()),
strictModeEnabled: false,
functionDescription: "Get the current weather for a location.");
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("What is the weather in San Francisco?") },
Tools = { getWeatherTool }
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
foreach (ResponseItem item in response.OutputItems)
{
if (item is FunctionCallResponseItem call && call.FunctionName == "get_weather")
{
using JsonDocument args = JsonDocument.Parse(call.FunctionArguments);
string location = args.RootElement.GetProperty("location").GetString();
string toolOutput = $"{{ \"location\": \"{location}\", \"temperature\": \"70 F\" }}";
CreateResponseOptions followUp = new()
{
Model = "MODEL_NAME",
PreviousResponseId = response.Id,
InputItems = { ResponseItem.CreateFunctionCallOutputItem(call.CallId, toolOutput) },
Tools = { getWeatherTool }
};
ResponseResult finalResponse = await openAIClient.CreateResponseAsync(followUp);
Console.WriteLine(finalResponse.GetOutputText());
}
}
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
tools: [
{
type: "function",
name: "get_weather",
description: "Get weather for a location",
parameters: {
type: "object",
properties: { location: { type: "string" } },
required: ["location"],
},
},
],
input: "What is the weather in San Francisco?",
});
const toolOutputs = [];
for (const item of response.output ?? []) {
if (item.type === "function_call" && item.name === "get_weather") {
const args = JSON.parse(item.arguments);
toolOutputs.push({
type: "function_call_output",
call_id: item.call_id,
output: JSON.stringify({ location: args.location, temperature: "70 F" }),
});
}
}
const finalResponse = await client.responses.create({
model: "MODEL_NAME",
previous_response_id: response.id,
input: toolOutputs,
});
console.log(finalResponse.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseFunctionToolCall;
import com.openai.models.responses.ResponseInputItem;
import java.util.ArrayList;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
// Strongly-typed function parameter class.
class GetWeather {
@JsonPropertyDescription("City and country, for example, Paris, France")
public String location;
}
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("What is the weather like in Paris today?")
.addTool(GetWeather.class)
.build());
List<ResponseInputItem> followUp = new ArrayList<>();
response.output().forEach(item -> {
if (item.isFunctionCall()) {
ResponseFunctionToolCall call = item.asFunctionCall();
// Execute the tool with call.arguments() and capture the result.
String result = "{\"temperature\":\"22 C\",\"conditions\":\"Sunny\"}";
followUp.add(ResponseInputItem.ofFunctionCallOutput(
ResponseInputItem.FunctionCallOutput.builder()
.callId(call.callId())
.output(result)
.build()));
}
});
Response finalResponse = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.previousResponseId(response.id())
.inputOfResponse(followUp)
.addTool(GetWeather.class)
.build());
System.out.println(finalResponse.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"]
}
}
],
"input": "What is the weather in San Francisco?"
}'
管理防護機制與內容過濾
在部署層級套用護欄(內容過濾器)。 每個設定的控制項評估其支援的內容與介入點:核心傷害過濾器評估輸入與輸出,使用者提示攻擊偵測評估使用者輸入,文件攻擊偵測在啟用時評估文件內容。 請分別設定防護機制。 欲了解更多資訊,請參閱 「配置護欄與控制」。 本節說明如何在呼叫回應 API 時偵測並處理護欄結果。
回覆 API 會以與聊天完成不同的方式顯示護欄結果。 回應物件不會使用聊天完成所回傳的 prompt_filter_results 和 content_filter_results 欄位,而是包含頂層的 content_filters 陣列。 每個項目描述一個濾鏡結果。
| Field |
Description |
blocked |
內容是否被封鎖。 |
source_type |
結果是適用於 prompt(輸入)還是 completion(輸出)。 |
content_filter_results |
類別結果如 hate、 sexual、 violence及 self_harm ,且具有嚴重程度等級,外加可選類別如 jailbreak、 indirect_attack、 protected_material_text、 protected_material_code和 。 |
content_filter_offsets |
結果所適用的字元偏移。 |
註
content_filters 陣列是 Microsoft Foundry 的擴充功能,不屬於基本 OpenAI 回應結構描述的一部分,因此 SDK 不會為其提供對應的型別化屬性。 可將其視為原始欄位或額外欄位,如以下範例所示。
當保護欄阻擋你的輸入時,API 會回傳一個帶有程式碼 content_filter的 HTTP 400 錯誤。 擷取此錯誤,以優雅地處理遭到阻擋的提示。
import os
from openai import OpenAI, BadRequestError
client = OpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
)
# A blocked prompt raises BadRequestError with the code "content_filter"
try:
response = client.responses.create(
model="MODEL_NAME",
input="This is a test."
)
print(response.output_text)
except BadRequestError as error:
if error.code == "content_filter":
print("The prompt was blocked by a guardrail.")
else:
raise
#pragma warning disable OPENAI001
using OpenAI.Responses;
using System.ClientModel;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("This is a test.") }
};
// A blocked prompt throws ClientResultException with HTTP 400
try
{
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
}
catch (ClientResultException error) when (error.Status == 400)
{
Console.WriteLine("The prompt was blocked by a guardrail.");
}
import { OpenAI, APIError } from "openai";
const openai = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
// A blocked prompt throws APIError with the code "content_filter"
try {
const response = await openai.responses.create({
model: "MODEL_NAME",
input: "This is a test."
});
console.log(response.output_text);
} catch (error) {
if (error instanceof APIError && error.code === "content_filter") {
console.log("The prompt was blocked by a guardrail.");
} else {
throw error;
}
}
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.AzureApiKeyCredential;
import com.openai.errors.BadRequestException;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl("https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1")
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
ResponseCreateParams params = ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("This is a test.")
.build();
// A blocked prompt throws BadRequestException (HTTP 400)
try {
Response response = openAIClient.responses().create(params);
System.out.println(response.outputText());
} catch (BadRequestException error) {
System.out.println("The prompt was blocked by a guardrail.");
}
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "This is a test."
}'
當保護欄阻擋輸入時,API 會回傳 HTTP 400 並返回程式碼:content_filter
{
"error": {
"code": "content_filter",
"message": "The response was filtered due to the prompt triggering content management policy."
}
}
閱讀護欄註解
當請求成功時,從回應中讀取 content_filters 陣列以檢查輸入與輸出的護欄結果。
在註解模式下,設定的控制項可以報告嚴重度或偵測結果,而不會據此強制執行。 對應的 blocked 和 filtered 值仍為 false。 四個核心危害類別的註釋模式需要核准修改過的護欄。
import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
)
response = client.responses.create(
model="MODEL_NAME",
input="This is a test."
)
# content_filters is an Azure extension, so read it from model_extra
content_filters = response.model_extra.get("content_filters", [])
for result in content_filters:
print(f"Source: {result['source_type']}, Blocked: {result['blocked']}")
#pragma warning disable OPENAI001
using OpenAI.Responses;
using System.ClientModel;
using System.ClientModel.Primitives;
using System.Text.Json;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("This is a test.") }
};
// content_filters has no typed property, so parse it from the raw response
ClientResult<ResponseResult> result = await openAIClient.CreateResponseAsync(options);
using JsonDocument doc = JsonDocument.Parse(result.GetRawResponse().Content);
if (doc.RootElement.TryGetProperty("content_filters", out JsonElement filters))
{
foreach (JsonElement filter in filters.EnumerateArray())
{
string source = filter.GetProperty("source_type").GetString()!;
bool blocked = filter.GetProperty("blocked").GetBoolean();
Console.WriteLine($"Source: {source}, Blocked: {blocked}");
}
}
import { OpenAI } from "openai";
const openai = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await openai.responses.create({
model: "MODEL_NAME",
input: "This is a test."
});
// content_filters is an Azure extension not in the typed response
const contentFilters = response.content_filters ?? [];
for (const result of contentFilters) {
console.log(`Source: ${result.source_type}, Blocked: ${result.blocked}`);
}
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.AzureApiKeyCredential;
import com.openai.core.JsonValue;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl("https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1")
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
ResponseCreateParams params = ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("This is a test.")
.build();
Response response = openAIClient.responses().create(params);
// content_filters has no typed accessor, so read it from additional properties
JsonValue contentFilters = response._additionalProperties().get("content_filters");
System.out.println(contentFilters);
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "This is a test."
}'
陣 content_filters 列會出現在回應物件上:
{
"id": "resp_<id>",
"content_filters": [
{
"source_type": "prompt",
"blocked": false,
"content_filter_results": {
"hate": { "filtered": false, "severity": "safe" },
"self_harm": { "filtered": false, "severity": "safe" },
"sexual": { "filtered": false, "severity": "safe" },
"violence": { "filtered": false, "severity": "safe" }
}
}
]
}
欲了解更多護欄類別與嚴重程度,請參閱 護欄概覽 及 註解工作。
程式碼直譯器
Code Interpreter 工具使模型能在安全且沙盒化的環境中撰寫並執行 Python 程式碼。 它支援一系列進階任務,包括:
- 處理具有多種資料格式與結構的檔案
- 產生包含資料與視覺化的檔案(例如圖表)
- 反覆撰寫並執行程式碼以解決問題——模型可以除錯並重試程式碼直到成功
- 使用支援的模型(例如 o3、o4-mini),增強視覺推理能力,啟用影像轉換功能,如裁切、縮放和旋轉
- 此工具特別適用於資料分析、數學計算及程式碼產生的情境。
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"tools": [
{ "type": "code_interpreter", "container": {"type": "auto"} }
],
"instructions": "You are a personal math tutor. When asked a math question, write and run code using the python tool to answer the question.",
"input": "I need to solve the equation 3x + 11 = 14. Can you help me?"
}'
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
tools=[{"type": "code_interpreter", "container": {"type": "auto"}}],
instructions="You are a math tutor. Write and run Python code to solve math problems.",
input="Solve 3x + 11 = 14."
)
print(response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Containers;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CodeInterpreterToolContainer container = new(
CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration());
CodeInterpreterTool codeInterpreterTool = new(container);
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem("Solve 3x + 11 = 14.")
},
Tools = { codeInterpreterTool }
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
tools: [{ type: "code_interpreter", container: { type: "auto" } }],
instructions: "You are a math tutor. Write and run Python code to solve math problems.",
input: "Solve 3x + 11 = 14.",
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.Tool;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Tool codeInterpreter = Tool.ofCodeInterpreter(
Tool.CodeInterpreter.builder()
.container(Tool.CodeInterpreter.Container.ofCodeInterpreterToolAuto(
Tool.CodeInterpreter.Container.CodeInterpreterToolAuto.builder().build()))
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("Solve 3x + 11 = 14.")
.addTool(codeInterpreter)
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"tools": [{"type": "code_interpreter", "container": {"type": "auto"}}],
"instructions": "You are a math tutor. Write and run Python code to solve math problems.",
"input": "Solve 3x + 11 = 14."
}'
容器
重要
Code Interpreter 在 Azure OpenAI 使用時,除了基於代幣的費用之外,還有額外收費。 如果你的回應 API 在兩個不同執行緒中同時呼叫 Code Interpreter,就會建立兩個 Code Interpreter 會話。 每次會談均按分鐘計費,最低收費為五分鐘。 只要您在 20 分鐘的閒置逾時內存取其容器,工作階段就會保持在作用中的狀態。
程式碼解譯器工具需要一個容器——一個完全沙盒化的虛擬機器,模型可執行 Python 程式碼。 容器可以包含上傳的檔案或執行過程中產生的檔案。
要建立容器,請在工具設定中指定 "container": { "type": "auto", "file_ids": ["file-1", "file-2"] } ,並建立新的回應物件。 這會自動建立一個新容器,或在模型的上下文中重複使用來自先前 code_interpreter_call 的作用中容器。 API 輸出中的 code_interpreter_call 會包含所產生的 container_id。 這個容器如果20分鐘內未使用即失效。
以下檔案限制適用:
- 一個請求最多可包含 50 個檔案 ID。
- 一個容器總共可容納多達 1,000 個檔案,包括輸入檔案及由 Code Interpreter 產生的檔案。
執行 Code Interpreter 時,模型可以建立自己的檔案。 舉例來說,如果你要求它建構圖表或建立 CSV 檔,它就會直接在你的容器上生成這些圖片。 它會在下一則訊息的註解中引用這些檔案。
模型輸入中的任何檔案都會自動上傳到容器。 您不需要將其明確上傳至容器。
支援檔案
| 檔案格式 |
MIME 類型 |
.c |
text/x-c |
.cs |
text/x-csharp |
.cpp |
text/x-c++ |
.csv |
文字/CSV |
.doc |
應用程式/MSWord |
.docx |
application/vnd.openxmlformats-officedocument.wordprocessingml.document |
.html |
文字/HTML |
.java |
text/x-java |
.json |
application/json |
.md |
text/markdown |
.pdf |
申請/PDF |
.php |
text/x-php |
.pptx |
application/vnd.openxmlformats-officedocument.presentationml.presentation |
.py |
text/x-python |
.py |
text/x-script.python |
.rb |
text/x-ruby |
.tex |
text/x-tex |
.txt |
text/plain |
.css |
文本/CSS |
.js |
文字/JavaScript |
.sh |
application/x-sh |
.ts |
application/TypeScript |
.csv |
應用程式/CSV |
.jpeg |
image/jpeg |
.jpg |
image/jpeg |
.gif |
image/gif |
.pkl |
應用程式/八位元組串流 |
.png |
圖像/PNG |
.tar |
application/x-tar |
.xlsx |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
.xml |
application/xml 或「text/xml」 |
.zip |
application/zip |
取得已傳送至回應的輸入項目。 這對於檢視完整的對話上下文非常有用,包括模型新增的任何項目(例如函式呼叫或壓縮項目)。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
items = client.responses.input_items.list("<response_id>")
print(items.model_dump_json(indent=2))
註
.NET SDK 僅將此端點作為協定方法公開。 請參見 REST 標籤中的呼叫格式,或直接呼叫協定方法。
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const items = await client.responses.inputItems.list("<response_id>");
console.log(JSON.stringify(items, null, 2));
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.inputitems.ResponseInputItemListPage;
import com.openai.models.responses.inputitems.ResponseInputItemListParams;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
ResponseInputItemListPage page = openAIClient.responses().inputItems().list(
ResponseInputItemListParams.builder()
.responseId("<response_id>")
.build());
page.autoPager().stream().forEach(item -> System.out.println(item));
curl -X GET https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id>/input_items \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
範例回應
{
"object": "list",
"data": [
{
"id": "msg_...",
"type": "message",
"role": "user",
"content": [{"type": "input_text", "text": "This is a test."}]
}
]
}
具備視覺功能的模型能同時解讀影像與文字。 他們能辨識物體、形狀、顏色和紋理,並閱讀圖片中包含的文字,但受本文後述限制限制。
你可以用以下任一方式,將圖片作為請求的輸入:
- 一個連至映像檔的完整網址
- 一個 Base64 編碼的資料 URI
- 一個使用 Files API 建立的檔案 ID
圖像網址
引用位於公開 URL 的圖片。 模型會擷取影像並將其納入輸入內容。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "What is in this image?"},
{"type": "input_image", "image_url": "<image_url>"}
]
}
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem(
[
ResponseContentPart.CreateInputTextPart("What is in this image?"),
ResponseContentPart.CreateInputImagePart(new Uri("<image_url>"))
])
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: [
{
role: "user",
content: [
{ type: "input_text", text: "What is in this image?" },
{ type: "input_image", image_url: "<image_url>" }
],
},
],
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputImage;
import com.openai.models.responses.ResponseInputItem;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
ResponseInputImage image = ResponseInputImage.builder()
.detail(ResponseInputImage.Detail.AUTO)
.imageUrl("<image_url>")
.build();
ResponseInputItem userMsg = ResponseInputItem.ofMessage(
ResponseInputItem.Message.builder()
.role(ResponseInputItem.Message.Role.USER)
.addInputTextContent("What is in this image?")
.addContent(image)
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.inputOfResponse(List.of(userMsg))
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "What is in this image?"},
{"type": "input_image", "image_url": "<image_url>"}
]
}
]
}'
Base64 編碼影像
透過將映像的位元組編碼為 base64 資料,來內嵌傳送映像 當圖片不是放在公開 URL 或你想避免額外網路擷取時,才會用這個模式。
import base64
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
with open("path_to_your_image.jpg", "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
response = client.responses.create(
model="MODEL_NAME",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "What is in this image?"},
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{base64_image}"}
]
}
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using System.IO;
using System.Threading.Tasks;
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
byte[] imageBytes = await File.ReadAllBytesAsync("path_to_your_image.jpg");
BinaryData imageData = BinaryData.FromBytes(imageBytes);
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem(
[
ResponseContentPart.CreateInputTextPart("What is in this image?"),
ResponseContentPart.CreateInputImagePart(imageData, "image/jpeg")
])
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import { readFileSync } from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const base64Image = readFileSync("path_to_your_image.jpg").toString("base64");
const response = await client.responses.create({
model: "MODEL_NAME",
input: [
{
role: "user",
content: [
{ type: "input_text", text: "What is in this image?" },
{ type: "input_image", image_url: `data:image/jpeg;base64,${base64Image}` }
],
},
],
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputImage;
import com.openai.models.responses.ResponseInputItem;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
byte[] bytes = Files.readAllBytes(Paths.get("cat.jpg"));
String dataUrl = "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(bytes);
ResponseInputImage image = ResponseInputImage.builder()
.detail(ResponseInputImage.Detail.AUTO)
.imageUrl(dataUrl)
.build();
ResponseInputItem userMsg = ResponseInputItem.ofMessage(
ResponseInputItem.Message.builder()
.role(ResponseInputItem.Message.Role.USER)
.addInputTextContent("What is in this image?")
.addContent(image)
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.inputOfResponse(List.of(userMsg))
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "What is in this image?"},
{"type": "input_image", "image_url": "data:image/jpeg;base64,<BASE64_IMAGE>"}
]
}
]
}'
檔案 ID
請用 檔案 API purpose="assistants"上傳圖片,然後在請求中參考回傳的檔案 ID。 當你想在多個請求中重複使用同一映像檔而不重新傳送位元組時,這種方法非常有用。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
def create_file(file_path):
with open(file_path, "rb") as file_content:
result = client.files.create(
file=file_content,
purpose="assistants",
)
return result.id
file_id = create_file("path_to_your_image.jpg")
response = client.responses.create(
model="MODEL_NAME",
input=[
{
"role": "user",
"content": [
{"type": "input_text", "text": "What is in this image?"},
{"type": "input_image", "file_id": file_id},
],
}
],
)
print(response.output_text)
#pragma warning disable OPENAI001
using System.IO;
using System.Threading.Tasks;
using Azure.Identity;
using OpenAI;
using OpenAI.Files;
using OpenAI.Responses;
using System.ClientModel;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
OpenAIFileClient fileClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new OpenAIClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
byte[] imageBytes = await File.ReadAllBytesAsync("path_to_your_image.jpg");
OpenAIFile uploadedFile = await fileClient.UploadFileAsync(
BinaryData.FromBytes(imageBytes),
"path_to_your_image.jpg",
FileUploadPurpose.Assistants);
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem(
[
ResponseContentPart.CreateInputTextPart("What is in this image?"),
ResponseContentPart.CreateInputImagePart(uploadedFile.Id)
])
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const file = await client.files.create({
file: fs.createReadStream("path_to_your_image.jpg"),
purpose: "assistants",
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: [
{
role: "user",
content: [
{ type: "input_text", text: "What is in this image?" },
{ type: "input_image", file_id: file.id },
],
},
],
});
console.log(response.output_text);
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.AzureApiKeyCredential;
import com.openai.models.files.FileCreateParams;
import com.openai.models.files.FileObject;
import com.openai.models.files.FilePurpose;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputImage;
import com.openai.models.responses.ResponseInputItem;
import java.nio.file.Paths;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
FileObject uploaded = openAIClient.files().create(
FileCreateParams.builder()
.file(Paths.get("path_to_your_image.jpg"))
.purpose(FilePurpose.ASSISTANTS)
.build());
ResponseInputImage image = ResponseInputImage.builder()
.detail(ResponseInputImage.Detail.AUTO)
.fileId(uploaded.id())
.build();
ResponseInputItem userMsg = ResponseInputItem.ofMessage(
ResponseInputItem.Message.builder()
.role(ResponseInputItem.Message.Role.USER)
.addInputTextContent("What is in this image?")
.addContent(image)
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.inputOfResponse(List.of(userMsg))
.build());
System.out.println(response.outputText());
# Upload the image
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/files \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-F purpose="assistants" \
-F file="@path_to_your_image.jpg"
# Use the returned file ID with Responses
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "What is in this image?"},
{"type": "input_image", "file_id": "<file_id>"}
]
}
]
}'
下表列出支援的影像輸入檔案類型。
| 檔案類型 |
MIME 類型 |
| PNG |
image/png |
| JPEG |
image/jpeg |
| WebP |
image/webp |
| 非動畫 GIF |
image/gif |
在一次請求中,你可以包含最多 50 張圖片。 每個獨立影像檔案必須在 512 MB 以下,且提示與該請求中所有圖片的總大小也必須低於 512 MB。
影像必須符合以下額外要求:
- 圖片必須與提示相關;這個模型並非為無關的視覺內容設計。
- 圖片不應包含違反內容政策的有害或敏感內容。
- 影像檔不會損壞或無法讀取。 如果模型無法處理影像,請求就會失敗。
選擇影像細節等級
使用 detail 內容部分上的 input_image 屬性,以控制模型如何處理影像。 細節越低,標記越少且速度越快;細節越少,模型能捕捉更細緻的特徵。
{
"type": "input_image",
"image_url": "<image_url>",
"detail": "high"
}
下表描述了每個細節層級。
| 詳細程度 |
Description |
low |
該模型使用較低解析度的影像版本。 此選項使用最少的標記,且回應最快,但模型可能會遺漏細節。 |
high |
模型使用較高解析度的影像版本。 此選項能捕捉更細緻的細節,但使用更多代幣且回覆時間較長。 |
auto |
預設值。 模型會根據圖片和提示選擇適當的細節等級。 |
具備視覺功能的模型有以下限制:
-
醫療影像:此模型不適合解讀像電腦斷層掃描(CT)等專業醫學影像,也不適合用於醫療建議。
-
非英文文字:當處理包含非拉丁字母(如日文或韓文)文字的影像時,模型可能無法達到最佳效能。
-
小字:放大圖片中的文字以提升可讀性,但避免裁切重要細節。
-
旋轉:模型可能會誤解旋轉或倒置的文字與影像。
-
視覺元素:對於顏色或樣式會變化的圖表或文字內容(例如實線、破折線或點線),模型可能難以辨識。
-
空間推理:模型在需要精確空間定位的任務上較為困難,例如識別西洋棋局面。
-
準確性:模型在某些情況下可能會產生錯誤的描述或說明。
-
影像形狀:模型在全景與魚眼鏡頭影像上有困難。
-
元資料與調整大小:模型不會處理原始檔案名稱或元資料,且影像在分析前會先調整大小,這會影響其原始尺寸。
-
計數:模型可能會給出影像中物體的近似計數。
-
CAPTCHA:出於安全考量,系統已建立以阻止提交 CAPTCHA。
具備視覺功能的模型支援 PDF 輸入。 您可以以下任一方式提供 PDF 檔案:
- Base64 編碼的資料
- 一個使用 Files API 建立的檔案 ID
- 外部檔案 URL(
file_url)
為了幫助模型解讀 PDF 內容,模型的上下文包含擷取後的文字與每頁的圖片。 當關鍵資訊透過圖表或非文字內容傳達時,此功能非常有用。
註
- 所有擷取的文字與圖片都會置於模型的上下文中。 務必了解使用 PDF 作為輸入時的定價及代幣使用影響。
- 在單一 API 請求中,你可以包含多個檔案,但每個檔案必須不超過 50 MB。 請求中所有檔案的總限制為 50 MB。
- 只有支援文字與圖片輸入的機型才能接受 PDF 檔案作為輸入。
- 目前不支援
purpose 為 user_data。 作為臨時的變通方法,你需要將目的設定為 assistants。
將 PDF 轉為 Base64 並進行分析
透過將 PDF 的位元組編碼為 base64 資料 URI,來內嵌傳送 PDF。 模型同時接收擷取的文字與每頁的渲染影像。
import base64
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
with open("PDF-FILE-NAME.pdf", "rb") as f:
base64_string = base64.b64encode(f.read()).decode("utf-8")
response = client.responses.create(
model="MODEL_NAME",
input=[
{
"role": "user",
"content": [
{
"type": "input_file",
"filename": "PDF-FILE-NAME.pdf",
"file_data": f"data:application/pdf;base64,{base64_string}",
},
{"type": "input_text", "text": "Summarize this PDF."},
],
},
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using System.IO;
using System.Threading.Tasks;
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
byte[] pdfBytes = await File.ReadAllBytesAsync("PDF-FILE-NAME.pdf");
BinaryData pdfData = BinaryData.FromBytes(pdfBytes);
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem(
[
ResponseContentPart.CreateInputFilePart(pdfData, "application/pdf", "PDF-FILE-NAME.pdf"),
ResponseContentPart.CreateInputTextPart("Summarize this PDF.")
])
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import { readFileSync } from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const base64Pdf = readFileSync("PDF-FILE-NAME.pdf").toString("base64");
const response = await client.responses.create({
model: "MODEL_NAME",
input: [
{
role: "user",
content: [
{
type: "input_file",
filename: "PDF-FILE-NAME.pdf",
file_data: `data:application/pdf;base64,${base64Pdf}`,
},
{ type: "input_text", text: "Summarize this PDF." },
],
},
],
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputFile;
import com.openai.models.responses.ResponseInputItem;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
byte[] pdfBytes = Files.readAllBytes(Paths.get("document.pdf"));
String dataUrl = "data:application/pdf;base64," + Base64.getEncoder().encodeToString(pdfBytes);
ResponseInputFile file = ResponseInputFile.builder()
.filename("document.pdf")
.fileData(dataUrl)
.build();
ResponseInputItem userMsg = ResponseInputItem.ofMessage(
ResponseInputItem.Message.builder()
.role(ResponseInputItem.Message.Role.USER)
.addInputTextContent("Summarize this PDF.")
.addContent(file)
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.inputOfResponse(List.of(userMsg))
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role": "user",
"content": [
{"type": "input_file", "filename": "PDF-FILE-NAME.pdf", "file_data": "data:application/pdf;base64,<BASE64_PDF>"},
{"type": "input_text", "text": "Summarize this PDF."}
]
}
]
}'
上傳 PDF 並進行分析
使用 purpose="assistants" 上傳 PDF 檔案。 目前不支援purpose的user_data。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
file = client.files.create(
file=open("nucleus_sampling.pdf", "rb"),
purpose="assistants"
)
response = client.responses.create(
model="MODEL_NAME",
input=[
{
"role": "user",
"content": [
{"type": "input_file", "file_id": file.id},
{"type": "input_text", "text": "Summarize this PDF."},
],
},
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using System.IO;
using System.Threading.Tasks;
using Azure.Identity;
using OpenAI;
using OpenAI.Files;
using OpenAI.Responses;
using System.ClientModel;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
OpenAIFileClient fileClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new OpenAIClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
byte[] pdfBytes = await File.ReadAllBytesAsync("nucleus_sampling.pdf");
OpenAIFile uploadedFile = await fileClient.UploadFileAsync(
BinaryData.FromBytes(pdfBytes),
"nucleus_sampling.pdf",
FileUploadPurpose.Assistants);
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem(
[
ResponseContentPart.CreateInputFilePart(uploadedFile.Id),
ResponseContentPart.CreateInputTextPart("Summarize this PDF.")
])
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const file = await client.files.create({
file: fs.createReadStream("nucleus_sampling.pdf"),
purpose: "assistants",
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: [
{
role: "user",
content: [
{ type: "input_file", file_id: file.id },
{ type: "input_text", text: "Summarize this PDF." },
],
},
],
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.files.FileCreateParams;
import com.openai.models.files.FileObject;
import com.openai.models.files.FilePurpose;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputFile;
import com.openai.models.responses.ResponseInputItem;
import java.nio.file.Paths;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
FileObject uploaded = openAIClient.files().create(
FileCreateParams.builder()
.file(Paths.get("document.pdf"))
.purpose(FilePurpose.ASSISTANTS)
.build());
ResponseInputFile file = ResponseInputFile.builder()
.fileId(uploaded.id())
.build();
ResponseInputItem userMsg = ResponseInputItem.ofMessage(
ResponseInputItem.Message.builder()
.role(ResponseInputItem.Message.Role.USER)
.addInputTextContent("Summarize this PDF.")
.addContent(file)
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.inputOfResponse(List.of(userMsg))
.build());
System.out.println(response.outputText());
# Upload the PDF
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/files \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-F purpose="assistants" \
-F file="@your_file.pdf"
# Use the returned file ID with Responses
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role": "user",
"content": [
{"type": "input_file", "file_id": "<file_id>"},
{"type": "input_text", "text": "Summarize this PDF."}
]
}
]
}'
從外部檔案網址分析 PDF
利用 file_url 內容項目的 input_file 屬性,參照由可公開存取的 URL 託管的 PDF。 你不需要先下載、轉碼或上傳檔案。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
input=[
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Analyze the letter and provide a summary of the key points.",
},
{
"type": "input_file",
"file_url": "https://www.berkshirehathaway.com/letters/2024ltr.pdf",
},
],
},
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem(
[
ResponseContentPart.CreateInputTextPart("Analyze the letter and provide a summary of the key points."),
ResponseContentPart.CreateInputFilePart(new Uri("https://www.berkshirehathaway.com/letters/2024ltr.pdf"))
])
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: [
{
role: "user",
content: [
{
type: "input_text",
text: "Analyze the letter and provide a summary of the key points.",
},
{
type: "input_file",
file_url: "https://www.berkshirehathaway.com/letters/2024ltr.pdf",
},
],
},
],
});
console.log(response.output_text);
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputFile;
import com.openai.models.responses.ResponseInputItem;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
ResponseInputFile file = ResponseInputFile.builder()
.fileUrl("https://www.berkshirehathaway.com/letters/2024ltr.pdf")
.build();
ResponseInputItem userMsg = ResponseInputItem.ofMessage(
ResponseInputItem.Message.builder()
.role(ResponseInputItem.Message.Role.USER)
.addInputTextContent("Analyze the letter and provide a summary of the key points.")
.addContent(file)
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.inputOfResponse(List.of(userMsg))
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": [
{
"role": "user",
"content": [
{
"type": "input_text",
"text": "Analyze the letter and provide a summary of the key points."
},
{
"type": "input_file",
"file_url": "https://www.berkshirehathaway.com/letters/2024ltr.pdf"
}
]
}
]
}'
使用遠端 MCP 伺服器
你可以透過連接遠端模型情境協定(MCP)伺服器上的工具來擴展模型的功能。 這些伺服器由開發者和組織維護,並公開可由相容 MCP 用戶端存取的工具,例如 Responses API。
模型上下文協定 (MCP)是一項開放標準,定義應用程式如何向大型語言模型(LLM)提供工具與上下文資料。 它能將外部工具整合到模型工作流程中,保持一致且可擴展。
以下範例說明如何利用遠端 MCP 伺服器查詢 Azure REST API 儲存庫的資訊。 模型會即時檢索並推理資料庫內容。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
tools=[
{
"type": "mcp",
"server_label": "github",
"server_url": "https://contoso.com/Azure/azure-rest-api-specs",
"require_approval": "never"
}
],
input="What transport protocols are supported in the 2025-03-26 version of the MCP spec?"
)
print(response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("What transport protocols are supported in the 2025-03-26 version of the MCP spec?") },
Tools =
{
new McpTool(serverLabel: "github", serverUri: new Uri("https://contoso.com/Azure/azure-rest-api-specs"))
{
ToolCallApprovalPolicy = GlobalMcpToolCallApprovalPolicy.NeverRequireApproval
}
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
tools: [
{
type: "mcp",
server_label: "github",
server_url: "https://contoso.com/Azure/azure-rest-api-specs",
require_approval: "never",
},
],
input: "What is this repo in 100 words?",
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.Tool;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Tool mcpTool = Tool.ofMcp(
Tool.Mcp.builder()
.serverLabel("github")
.serverUrl("https://contoso.com/Azure/azure-rest-api-specs")
.requireApproval(Tool.Mcp.RequireApproval.ofMcpToolApprovalSetting(
Tool.Mcp.RequireApproval.McpToolApprovalSetting.NEVER))
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("What is this repo in 100 words?")
.addTool(mcpTool)
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"tools": [
{
"type": "mcp",
"server_label": "github",
"server_url": "https://contoso.com/Azure/azure-rest-api-specs",
"require_approval": "never"
}
],
"input": "What is this repo in 100 words?"
}'
MCP 工具僅能在回應 API 中使用,且適用於所有較新的模型(gpt-4o、gpt-4.1 及我們的推理模型)。 使用MCP工具時,您只需支付匯入工具定義或工具呼叫時使用的代幣費用,無需額外費用。
核准
預設情況下,回應 API 要求在與遠端 MCP 伺服器分享資料前,先經過明確核准。 此審核步驟有助於確保透明度,並讓您掌控將哪些資訊傳送至外部。
我們建議審查所有與遠端 MCP 伺服器共享的資料,並可選擇性地記錄以供稽核。
當需要核准時,模型會在回應輸出中回傳一項 mcp_approval_request 項目。 此物件包含待處理請求的詳細資料,並允許您在繼續前檢查或修改資料。
{
"id": "mcpr_682bd9cd428c8198b170dc6b549d66fc016e86a03f4cc828",
"type": "mcp_approval_request",
"arguments": {},
"name": "fetch_azure_rest_api_docs",
"server_label": "github"
}
要進行遠端 MCP 呼叫,您必須透過建立包含 mcp_approval_response 項目的新回應物件來回應核准請求。 這個物件確認你允許模型將指定資料傳送到遠端 MCP 伺服器的意圖。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
tools=[
{
"type": "mcp",
"server_label": "github",
"server_url": "https://contoso.com/Azure/azure-rest-api-specs",
"require_approval": "never"
}
],
previous_response_id="<previous_response_id>",
input=[
{
"type": "mcp_approval_response",
"approve": True,
"approval_request_id": "<approval_request_id>"
}
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
McpTool mcpTool = new(serverLabel: "github", serverUri: new Uri("https://contoso.com/Azure/azure-rest-api-specs"));
ResponseResult priorResponse = await openAIClient.GetResponseAsync("<previous_response_id>");
foreach (ResponseItem item in priorResponse.OutputItems)
{
if (item is McpToolCallApprovalRequestItem approvalRequest)
{
CreateResponseOptions followUp = new()
{
Model = "MODEL_NAME",
PreviousResponseId = priorResponse.Id,
InputItems = { new McpToolCallApprovalResponseItem(approvalRequest.Id, approved: true) },
Tools = { mcpTool }
};
ResponseResult finalResponse = await openAIClient.CreateResponseAsync(followUp);
Console.WriteLine(finalResponse.GetOutputText());
}
}
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
tools: [
{
type: "mcp",
server_label: "github",
server_url: "https://contoso.com/Azure/azure-rest-api-specs",
require_approval: "never",
},
],
previous_response_id: "<previous_response_id>",
input: [
{
type: "mcp_approval_response",
approve: true,
approval_request_id: "<approval_request_id>",
},
],
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseInputItem;
import java.util.List;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.previousResponseId("<previous_response_id>")
.inputOfResponse(List.of(
ResponseInputItem.ofMcpApprovalResponse(
ResponseInputItem.McpApprovalResponse.builder()
.approvalRequestId("<approval_request_id>")
.approve(true)
.build())))
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"tools": [
{
"type": "mcp",
"server_label": "github",
"server_url": "https://contoso.com/Azure/azure-rest-api-specs",
"require_approval": "never"
}
],
"previous_response_id": "<previous_response_id>",
"input": [
{
"type": "mcp_approval_response",
"approve": true,
"approval_request_id": "<approval_request_id>"
}
]
}'
認證
重要
- 回應 API 中的 MCP 用戶端需要 TLS 1.2 或更高版本。
- 目前不支援雙向 TLS(mTLS)。
-
Azure 服務標籤目前不支援 MCP 用戶端流量。
與 GitHub MCP 伺服器不同,大多數遠端 MCP 伺服器需要驗證。 回應 API 中的 MCP 工具支援自訂標頭,讓你能使用這些伺服器所需的認證方案安全連接。
你可以在請求中直接指定標頭,例如 API 金鑰、OAuth 存取權杖或其他憑證。 最常用的標頭是Authorization標頭。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
input="What is this repo in 100 words?",
tools=[
{
"type": "mcp",
"server_label": "github",
"server_url": "https://contoso.com/Azure/azure-rest-api-specs",
"headers": {"Authorization": "Bearer $YOUR_MCP_TOKEN"}
}
]
)
print(response.output_text)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("What is this repo in 100 words?") },
Tools =
{
new McpTool(serverLabel: "github", serverUri: new Uri("https://contoso.com/Azure/azure-rest-api-specs"))
{
AuthorizationToken = Environment.GetEnvironmentVariable("YOUR_MCP_TOKEN"),
ToolCallApprovalPolicy = GlobalMcpToolCallApprovalPolicy.NeverRequireApproval
}
}
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
Console.WriteLine(response.GetOutputText());
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: "What is this repo in 100 words?",
tools: [
{
type: "mcp",
server_label: "github",
server_url: "https://contoso.com/Azure/azure-rest-api-specs",
headers: { Authorization: "Bearer $YOUR_MCP_TOKEN" },
},
],
});
console.log(response.output_text);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.JsonValue;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.Tool;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Tool mcpTool = Tool.ofMcp(
Tool.Mcp.builder()
.serverLabel("github")
.serverUrl("https://contoso.com/Azure/azure-rest-api-specs")
.headers(Tool.Mcp.Headers.builder()
.putAdditionalProperty("Authorization", JsonValue.from("Bearer $YOUR_MCP_TOKEN"))
.build())
.requireApproval(Tool.Mcp.RequireApproval.ofMcpToolApprovalSetting(
Tool.Mcp.RequireApproval.McpToolApprovalSetting.NEVER))
.build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("What is this repo in 100 words?")
.addTool(mcpTool)
.build());
System.out.println(response.outputText());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "What is this repo in 100 words?",
"tools": [
{
"type": "mcp",
"server_label": "github",
"server_url": "https://contoso.com/Azure/azure-rest-api-specs",
"headers": {"Authorization": "Bearer $YOUR_MCP_TOKEN"}
}
]
}'
背景任務
背景模式讓您能以非同步方式執行長時間執行的工作,並搭配如o3和o1-pro等推理模型。 它對於需要數分鐘完成的複雜任務非常有用(例如,像是Codex或Deep Research風格的特工)。 當要求和"background": true一起送出時,工作會以非同步方式處理,並您需輪詢以取得其狀態。
啟動背景任務
在請求中設定 background=true,以將該任務排入佇列。 服務會立即回傳回應 ID 和 queued 狀態——用該 ID 輪詢、串流或取消任務。
import os
from openai import OpenAI
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=os.getenv("AZURE_OPENAI_API_KEY")
)
response = client.responses.create(
model="MODEL_NAME",
input="Write me a very long story.",
background=True
)
print(response.status)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("Write me a very long story.") },
BackgroundModeEnabled = true
};
ResponseResult queued = await openAIClient.CreateResponseAsync(options);
Console.WriteLine($"Response id: {queued.Id}");
Console.WriteLine($"Status: {queued.Status}");
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: process.env.AZURE_OPENAI_API_KEY,
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: "Write me a very long story.",
background: true,
});
console.log(response.status);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("Write a 1000-word essay on the history of computing.")
.background(true)
.build());
System.out.println(response.status());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "Write me a very long story.",
"background": true
}'
輪詢直到完成
當狀態為 queued 或 in_progress 時,持續輪詢。 一旦回應達到終端狀態,即可被檢索。
from time import sleep
while response.status in {"queued", "in_progress"}:
print(f"Current status: {response.status}")
sleep(2)
response = client.responses.retrieve(response.id)
print(f"Final status: {response.status}\nOutput:\n{response.output_text}")
#pragma warning disable OPENAI001
using System.Threading.Tasks;
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
ResponseResult current = await openAIClient.GetResponseAsync("<response_id>");
while (current.Status == ResponseStatus.Queued || current.Status == ResponseStatus.InProgress)
{
Console.WriteLine($"Current status: {current.Status}");
await Task.Delay(TimeSpan.FromSeconds(2));
current = await openAIClient.GetResponseAsync(current.Id);
}
Console.WriteLine($"Final status: {current.Status}");
if (current.Status == ResponseStatus.Completed)
{
Console.WriteLine(current.GetOutputText());
}
let current = response;
while (current.status === "queued" || current.status === "in_progress") {
console.log(`Current status: ${current.status}`);
await new Promise((r) => setTimeout(r, 2000));
current = await client.responses.retrieve(current.id);
}
console.log(`Final status: ${current.status}\nOutput:\n${current.output_text}`);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Response current = openAIClient.responses().retrieve("<response_id>");
while (current.status().filter(s ->
s.equals(Response.Status.QUEUED) || s.equals(Response.Status.IN_PROGRESS)).isPresent()) {
System.out.println("Current status: " + current.status());
Thread.sleep(2000);
current = openAIClient.responses().retrieve(current.id());
}
System.out.println("Final status: " + current.status());
System.out.println("Output:\n" + current.outputText());
curl -X GET https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id> \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
取消背景任務
使用 cancel 端點取消進行中的背景工作。 取消是冪零式的——後續呼叫會回傳最終回應物件。
response = client.responses.cancel("<response_id>")
print(response.status)
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
ResponseResult cancelled = await openAIClient.CancelResponseAsync("<response_id>");
Console.WriteLine($"Status: {cancelled.Status}");
const cancelled = await client.responses.cancel("<response_id>");
console.log(cancelled.status);
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Response cancelled = openAIClient.responses().cancel("<response_id>");
System.out.println(cancelled.status());
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id>/cancel \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
若要串流背景回應,請將兩者 backgroundstream 和 都設為 true。 這個模式讓你在連線斷線時繼續串流。 透過各場活動的 sequence_number 追蹤你的排名。
stream = client.responses.create(
model="MODEL_NAME",
input="Write me a very long story.",
background=True,
stream=True,
)
cursor = None
for event in stream:
print(event)
cursor = event["sequence_number"]
#pragma warning disable OPENAI001
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
CreateResponseOptions createOptions = new()
{
Model = "MODEL_NAME",
InputItems = { ResponseItem.CreateUserMessageItem("Write me a very long story.") },
BackgroundModeEnabled = true,
StreamingEnabled = true
};
string queuedResponseId = null;
int lastSequenceNumber = 0;
await foreach (StreamingResponseUpdate update in openAIClient.CreateResponseStreamingAsync(createOptions))
{
if (update is StreamingResponseQueuedUpdate queuedUpdate)
{
queuedResponseId = queuedUpdate.Response.Id;
lastSequenceNumber = queuedUpdate.SequenceNumber;
Console.WriteLine($"Queued response: {queuedResponseId}, sequence {lastSequenceNumber}");
break;
}
}
// Resume streaming from where we disconnected.
GetResponseOptions resumeOptions = new(queuedResponseId)
{
StartingAfter = lastSequenceNumber,
StreamingEnabled = true
};
await foreach (StreamingResponseUpdate update in openAIClient.GetResponseStreamingAsync(resumeOptions))
{
Console.WriteLine(update.GetType().Name);
if (update is StreamingResponseCompletedUpdate completed)
{
Console.WriteLine($"[done] final id: {completed.Response.Id}");
}
}
const stream = await client.responses.create({
model: "MODEL_NAME",
input: "Write me a very long story.",
background: true,
stream: true,
});
let cursor = null;
for await (const event of stream) {
console.log(event);
cursor = event.sequence_number;
}
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.StreamResponse;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.ResponseRetrieveParams;
import com.openai.models.responses.ResponseStreamEvent;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
long cursor = 0L;
try (StreamResponse<ResponseStreamEvent> stream = openAIClient.responses().retrieveStreaming(
"<response_id>",
ResponseRetrieveParams.builder().startingAfter(cursor).build())) {
stream.stream().forEach(event -> System.out.println(event));
}
curl -N -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-d '{
"model": "MODEL_NAME",
"input": "Write me a very long story.",
"background": true,
"stream": true
}'
背景回應目前的第一個詞元延遲時間比同步回應更高。 目前正進行改善以縮小這個差距。
限制
- 背景模式需要
store=true。 不支援無狀態請求。
- 只有當原始請求包含
stream=true時,才能繼續串流。
- 若要取消同步回應,請直接終止連線。
從特定位置繼續串流
如果串流連線中斷,您可以透過在回覆的stream=true上一併傳遞starting_after=<sequence_number>和GET,從已知事件重新開始。 服務會重播該序號之後發出的事件。
curl -N -X GET "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses/<response_id>?stream=true&starting_after=42" \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY"
加密推理
當你使用推理模型,並使用 Responses API 的無狀態模式(store=false)時,你的應用程式會為每個後續請求提供上下文。 先前訊息提供對話歷史,但不包含模型的內部推理。 加密推理項目能讓你將相容的推理上下文帶入後續請求,而不會將推理暴露為對您的應用程式可讀的文字。
為什麼要用加密推理?
當你的應用程式管理對話狀態並需要持續多回合推理工作流程時,請使用加密推理。 例如,使用者可能會提出後續問題,或模型呼叫工具後,在收到結果後繼續進行。
僅僅傳遞先前訊息並不能傳遞模型前一回合的推理上下文。 加密的推理項目會將這些上下文傳遞下去,同時保持其內容對你的應用程式不透明。
如何使用
- 設定
store=false。 要明確請求加密推理,將 reasoning.encrypted_content 加入 include 參數中,如下範例所示。
- 保留所有傳回的輸出項目的原始順序,包括帶有
encrypted_content 屬性的推理項目。
- 下一次通話時,將這些項目與其他相關對話項目一起放入
input,並繼續設定 store=false。 不要將 previous_response_id 用於未儲存的回應。
無狀態回應預設回傳加密內容;include 參數仍受支援,以維持相容性。 重播一個項目可使用相容推理,但模型使用哪種推理取決於其支援的推理上下文模式。 如需詳細資訊,請參閱在呼叫之間保留推理內容。
在無狀態模式下,加密的推理項目會傳回您的應用程式。 您的應用程式負責安全保存該資料並在後續請求時傳回該資料。 選擇符合您安全性與生命週期需求的應用端儲存地點。
以下範例使用了 API 金鑰驗證。 Python 範例使用 OpenAI 用戶端函式庫。 其他範例則直接呼叫 Responses REST 端點,並將完整輸出項目保留為 JSON。
安裝你的語言所需的相依套件:
-
Python:使用
pip install --upgrade openai 安裝客戶端。
-
C#:使用.NET 8或更新版本的主控台應用程式。 不需要其他套件。
-
JavaScript:使用 Node.js 18 或更新版本,並將每個樣本儲存為
.mjs 檔案。 不需要其他套件。
-
Java:使用 JDK 17 或更新版本,並新增 Maven 相依性
com.fasterxml.jackson.core:jackson-databind:2.22.4。 將每個樣本以其分頁中顯示的檔名儲存。
-
REST:用 PowerShell 7 或更新版本執行 PowerShell 範例。
為每種語言設定以下環境變數:
-
AZURE_OPENAI_ENDPOINT:你的資源端點,例如 https://YOUR-RESOURCE-NAME.openai.azure.com。
-
AZURE_OPENAI_API_KEY:你的 API 金鑰。
-
AZURE_OPENAI_DEPLOYMENT:一個支援的推理模型部署名稱。
兩個樣本都會檢查是否有加密推理項目,若未回傳則會產生錯誤。 使用部署與推理設定,產生範例請求的推理項目。
繼續無狀態對話
此範例會將回傳項目保留在應用程式管理的清單中,並將它們傳送到後續請求中。
import os
from openai import BadRequestError, OpenAI
client = OpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
)
deployment = os.environ["AZURE_OPENAI_DEPLOYMENT"]
# Application-managed state. This example keeps it in memory.
conversation = [
{"role": "user", "content": "Explain the trade-offs of this design."}
]
def add_response_items(response):
items = [item.model_dump(exclude_none=True) for item in response.output]
if not any(
item.get("type") == "reasoning" and item.get("encrypted_content")
for item in items
):
raise RuntimeError(
"No encrypted reasoning item was returned. Check the deployment "
"and the request's include parameter."
)
# Preserve the returned items, including encrypted reasoning.
conversation.extend(items)
try:
first = client.responses.create(
model=deployment,
input=conversation,
store=False,
include=["reasoning.encrypted_content"],
)
add_response_items(first)
print("First answer:", first.output_text)
conversation.append({
"role": "user",
"content": "Which trade-off matters most for reliability?",
})
second = client.responses.create(
model=deployment,
input=conversation,
store=False,
include=["reasoning.encrypted_content"],
)
add_response_items(second)
print("Follow-up answer:", second.output_text)
except BadRequestError as exc:
# Inspect the service error before deciding whether to restart.
print(f"Request rejected: {exc}")
raise
using System;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
string endpoint = RequiredEnvironment("AZURE_OPENAI_ENDPOINT").TrimEnd('/');
string deployment = RequiredEnvironment("AZURE_OPENAI_DEPLOYMENT");
using HttpClient openAIClient = new();
openAIClient.DefaultRequestHeaders.Add(
"api-key", RequiredEnvironment("AZURE_OPENAI_API_KEY"));
// Application-managed state. Preserve each complete output item.
JsonArray conversation = new()
{
new JsonObject
{
["role"] = "user",
["content"] = "Explain the trade-offs of this design."
}
};
JsonObject first = await CreateResponseAsync();
AddResponseItems(first);
Console.WriteLine($"First answer: {GetOutputText(first)}");
conversation.Add(new JsonObject
{
["role"] = "user",
["content"] = "Which trade-off matters most for reliability?"
});
JsonObject second = await CreateResponseAsync();
AddResponseItems(second);
Console.WriteLine($"Follow-up answer: {GetOutputText(second)}");
async Task<JsonObject> CreateResponseAsync()
{
JsonObject request = new()
{
["model"] = deployment,
["input"] = conversation.DeepClone(),
["store"] = false,
["include"] = new JsonArray("reasoning.encrypted_content")
};
using StringContent content = new(
request.ToJsonString(), Encoding.UTF8, "application/json");
using HttpResponseMessage response = await openAIClient.PostAsync(
$"{endpoint}/openai/v1/responses", content);
string body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Request rejected ({(int)response.StatusCode}): {body}");
}
return JsonNode.Parse(body)?.AsObject()
?? throw new InvalidOperationException("No response body was returned.");
}
void AddResponseItems(JsonObject response)
{
JsonArray items = response["output"]?.AsArray()
?? throw new InvalidOperationException("No output items were returned.");
if (!items.OfType<JsonObject>().Any(item =>
item["type"]?.GetValue<string>() == "reasoning" &&
!string.IsNullOrEmpty(item["encrypted_content"]?.GetValue<string>())))
{
throw new InvalidOperationException(
"No encrypted reasoning item was returned.");
}
foreach (JsonNode? item in items)
{
conversation.Add(item?.DeepClone()
?? throw new InvalidOperationException("An output item was null."));
}
}
static string GetOutputText(JsonObject response) => string.Concat(
response["output"]!.AsArray().OfType<JsonObject>()
.Where(item => item["type"]?.GetValue<string>() == "message")
.SelectMany(item => item["content"]!.AsArray().OfType<JsonObject>())
.Where(part => part["type"]?.GetValue<string>() == "output_text")
.Select(part => part["text"]!.GetValue<string>()));
static string RequiredEnvironment(string name)
{
string? value = Environment.GetEnvironmentVariable(name);
return !string.IsNullOrEmpty(value) ? value
: throw new InvalidOperationException($"Set {name} before running.");
}
const requiredEnvironment = (name) => {
const value = process.env[name];
if (!value) throw new Error(`Set ${name} before running.`);
return value;
};
const endpoint = requiredEnvironment("AZURE_OPENAI_ENDPOINT").replace(/\/+$/, "");
const deployment = requiredEnvironment("AZURE_OPENAI_DEPLOYMENT");
const apiKey = requiredEnvironment("AZURE_OPENAI_API_KEY");
// Application-managed state. Preserve each complete output item.
const conversation = [
{ role: "user", content: "Explain the trade-offs of this design." },
];
async function createResponse() {
const response = await fetch(`${endpoint}/openai/v1/responses`, {
method: "POST",
headers: { "Content-Type": "application/json", "api-key": apiKey },
body: JSON.stringify({
model: deployment,
input: conversation,
store: false,
include: ["reasoning.encrypted_content"],
}),
});
if (!response.ok) {
throw new Error(
`Request rejected (${response.status}): ${await response.text()}`,
);
}
return response.json();
}
function addResponseItems(response) {
if (!Array.isArray(response.output)) {
throw new Error("No output items were returned.");
}
if (!response.output.some(
(item) => item.type === "reasoning" && item.encrypted_content,
)) {
throw new Error("No encrypted reasoning item was returned.");
}
conversation.push(...response.output);
}
function getOutputText(response) {
return response.output
.filter((item) => item.type === "message")
.flatMap((item) => item.content)
.filter((part) => part.type === "output_text")
.map((part) => part.text)
.join("");
}
const first = await createResponse();
addResponseItems(first);
console.log("First answer:", getOutputText(first));
conversation.push({
role: "user",
content: "Which trade-off matters most for reliability?",
});
const second = await createResponse();
addResponseItems(second);
console.log("Follow-up answer:", getOutputText(second));
將此樣本儲存為 StatelessConversation.java。
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class StatelessConversation {
private static final ObjectMapper JSON = new ObjectMapper();
public static void main(String[] args) throws Exception {
String endpoint = requiredEnvironment("AZURE_OPENAI_ENDPOINT")
.replaceAll("/+$", "");
String deployment = requiredEnvironment("AZURE_OPENAI_DEPLOYMENT");
String apiKey = requiredEnvironment("AZURE_OPENAI_API_KEY");
HttpClient openAIClient = HttpClient.newHttpClient();
// Application-managed state. Preserve each complete output item.
ArrayNode conversation = JSON.createArrayNode();
conversation.add(JSON.createObjectNode()
.put("role", "user")
.put("content", "Explain the trade-offs of this design."));
JsonNode first = createResponse(
openAIClient, endpoint, apiKey, deployment, conversation);
addResponseItems(conversation, first);
System.out.println("First answer: " + getOutputText(first));
conversation.add(JSON.createObjectNode()
.put("role", "user")
.put("content", "Which trade-off matters most for reliability?"));
JsonNode second = createResponse(
openAIClient, endpoint, apiKey, deployment, conversation);
addResponseItems(conversation, second);
System.out.println("Follow-up answer: " + getOutputText(second));
}
private static JsonNode createResponse(
HttpClient openAIClient, String endpoint, String apiKey,
String deployment, ArrayNode conversation) throws Exception {
ObjectNode payload = JSON.createObjectNode();
payload.put("model", deployment);
payload.set("input", conversation);
payload.put("store", false);
payload.set("include", JSON.createArrayNode()
.add("reasoning.encrypted_content"));
HttpRequest request = HttpRequest.newBuilder(
URI.create(endpoint + "/openai/v1/responses"))
.header("Content-Type", "application/json")
.header("api-key", apiKey)
.POST(HttpRequest.BodyPublishers.ofString(
JSON.writeValueAsString(payload)))
.build();
HttpResponse<String> response = openAIClient.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException(
"Request rejected (" + response.statusCode() + "): "
+ response.body());
}
return JSON.readTree(response.body());
}
private static void addResponseItems(
ArrayNode conversation, JsonNode response) {
JsonNode items = response.get("output");
if (items == null || !items.isArray()) {
throw new IllegalStateException("No output items were returned.");
}
boolean hasEncryptedReasoning = false;
for (JsonNode item : items) {
JsonNode encrypted = item.get("encrypted_content");
if ("reasoning".equals(item.path("type").asText())
&& encrypted != null && encrypted.isTextual()
&& !encrypted.asText().isEmpty()) {
hasEncryptedReasoning = true;
}
}
if (!hasEncryptedReasoning) {
throw new IllegalStateException(
"No encrypted reasoning item was returned.");
}
for (JsonNode item : items) {
conversation.add(item);
}
}
private static String getOutputText(JsonNode response) {
StringBuilder text = new StringBuilder();
for (JsonNode item : response.get("output")) {
if ("message".equals(item.path("type").asText())) {
for (JsonNode part : item.get("content")) {
if ("output_text".equals(part.path("type").asText())) {
text.append(part.get("text").asText());
}
}
}
}
return text.toString();
}
private static String requiredEnvironment(String name) {
String value = System.getenv(name);
if (value == null || value.isEmpty()) {
throw new IllegalStateException("Set " + name + " before running.");
}
return value;
}
}
這個 PowerShell 範例會直接將 JSON 請求傳送到 REST 端點。
$ErrorActionPreference = "Stop"
foreach ($name in "AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_API_KEY",
"AZURE_OPENAI_DEPLOYMENT") {
if (-not [Environment]::GetEnvironmentVariable($name)) {
throw "Set $name before running."
}
}
$endpoint = $env:AZURE_OPENAI_ENDPOINT.TrimEnd("/")
$deployment = $env:AZURE_OPENAI_DEPLOYMENT
$headers = @{ "api-key" = $env:AZURE_OPENAI_API_KEY }
# Application-managed state. Preserve each complete output item.
$conversation = [System.Collections.Generic.List[object]]::new()
$conversation.Add(@{
role = "user"
content = "Explain the trade-offs of this design."
})
function New-Response {
$body = @{
model = $deployment
input = $conversation.ToArray()
store = $false
include = @("reasoning.encrypted_content")
} | ConvertTo-Json -Depth 100
Invoke-RestMethod -Method Post -Uri "$endpoint/openai/v1/responses" `
-Headers $headers -ContentType "application/json" -Body $body
}
function Add-ResponseItems($response) {
$items = @($response.output)
if (-not ($items | Where-Object {
$_.type -eq "reasoning" -and $_.encrypted_content
})) {
throw "No encrypted reasoning item was returned."
}
foreach ($item in $items) {
$conversation.Add($item)
}
}
function Get-OutputText($response) {
$parts = foreach ($item in $response.output) {
if ($item.type -eq "message") {
foreach ($part in $item.content) {
if ($part.type -eq "output_text") { $part.text }
}
}
}
$parts -join ""
}
$first = New-Response
Add-ResponseItems $first
Write-Output "First answer: $(Get-OutputText $first)"
$conversation.Add(@{
role = "user"
content = "Which trade-off matters most for reliability?"
})
$second = New-Response
Add-ResponseItems $second
Write-Output "Follow-up answer: $(Get-OutputText $second)"
範例會印出第一個答案和後續答案。 它保留所有輸出項目,包括加密推理,而非僅保留可讀答案。
conversation 清單是此範例應用程式保留項目的地方。 它被儲存在記憶體中,在程序重新啟動後不會保留。 若應用程式需要稍後繼續執行,就必須自行選擇儲存體,並確保其安全性。
此範例保留推理與函式呼叫項目,執行範例函式,並使用相符的 call_id 將結果傳回。
import json
import os
from openai import BadRequestError, OpenAI
client = OpenAI(
api_key=os.environ["AZURE_OPENAI_API_KEY"],
base_url=f"{os.environ['AZURE_OPENAI_ENDPOINT'].rstrip('/')}/openai/v1/",
)
deployment = os.environ["AZURE_OPENAI_DEPLOYMENT"]
tools = [{
"type": "function",
"name": "get_order_status",
"description": "Look up the status of an example order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"}
},
"required": ["order_id"],
"additionalProperties": False,
},
}]
def get_order_status(order_id):
# Replace this example with your own trusted data source.
if order_id == "A123":
return {"order_id": order_id, "status": "Shipped"}
return {"order_id": order_id, "status": "Not found"}
conversation = [{
"role": "user",
"content": "What is the status of order A123?",
}]
def create_response():
return client.responses.create(
model=deployment,
input=conversation,
tools=tools,
store=False,
include=["reasoning.encrypted_content"],
)
try:
# Bound the number of tool rounds.
for _ in range(3):
response = create_response()
items = [item.model_dump(exclude_none=True) for item in response.output]
if not any(
item.get("type") == "reasoning" and item.get("encrypted_content")
for item in items
):
raise RuntimeError("No encrypted reasoning item was returned.")
# Preserve returned items in order, including reasoning and tool calls.
conversation.extend(items)
calls = [
item for item in response.output
if item.type == "function_call"
]
if not calls:
print(response.output_text)
break
for call in calls:
if call.name != "get_order_status":
raise ValueError(f"Unexpected tool: {call.name}")
arguments = json.loads(call.arguments)
result = get_order_status(arguments["order_id"])
conversation.append({
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result),
})
else:
raise RuntimeError("The tool-call limit was reached.")
except BadRequestError as exc:
print(f"Request rejected: {exc}")
raise
using System;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
string endpoint = RequiredEnvironment("AZURE_OPENAI_ENDPOINT").TrimEnd('/');
string deployment = RequiredEnvironment("AZURE_OPENAI_DEPLOYMENT");
using HttpClient openAIClient = new();
openAIClient.DefaultRequestHeaders.Add(
"api-key", RequiredEnvironment("AZURE_OPENAI_API_KEY"));
JsonArray tools = JsonNode.Parse("""
[
{
"type": "function",
"name": "get_order_status",
"description": "Look up the status of an example order.",
"parameters": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"],
"additionalProperties": false
}
}
]
""")!.AsArray();
JsonArray conversation = new()
{
new JsonObject
{
["role"] = "user",
["content"] = "What is the status of order A123?"
}
};
// Preserve reasoning and tool calls before appending each tool result.
for (int round = 0; round < 3; round++)
{
JsonObject response = await CreateResponseAsync();
JsonArray items = response["output"]?.AsArray()
?? throw new InvalidOperationException("No output items were returned.");
if (!items.OfType<JsonObject>().Any(item =>
item["type"]?.GetValue<string>() == "reasoning" &&
!string.IsNullOrEmpty(item["encrypted_content"]?.GetValue<string>())))
{
throw new InvalidOperationException(
"No encrypted reasoning item was returned.");
}
foreach (JsonNode? item in items)
{
conversation.Add(item?.DeepClone()
?? throw new InvalidOperationException("An output item was null."));
}
JsonObject[] calls = items.OfType<JsonObject>()
.Where(item => item["type"]?.GetValue<string>() == "function_call")
.ToArray();
if (calls.Length == 0)
{
Console.WriteLine(GetOutputText(response));
return;
}
foreach (JsonObject call in calls)
{
if (call["name"]?.GetValue<string>() != "get_order_status")
{
throw new InvalidOperationException($"Unexpected tool: {call["name"]}");
}
JsonObject arguments = JsonNode.Parse(
call["arguments"]!.GetValue<string>())?.AsObject()
?? throw new InvalidOperationException("Invalid tool arguments.");
if (arguments["order_id"] is not JsonValue orderIdNode ||
!orderIdNode.TryGetValue<string>(out string? orderId) ||
orderId is null)
{
throw new InvalidOperationException("Missing or invalid order_id.");
}
// Replace this example data with your own trusted data source.
JsonObject result = new()
{
["order_id"] = orderId,
["status"] = orderId == "A123" ? "Shipped" : "Not found"
};
conversation.Add(new JsonObject
{
["type"] = "function_call_output",
["call_id"] = call["call_id"]!.GetValue<string>(),
["output"] = result.ToJsonString()
});
}
}
throw new InvalidOperationException("The tool-call limit was reached.");
async Task<JsonObject> CreateResponseAsync()
{
JsonObject request = new()
{
["model"] = deployment,
["input"] = conversation.DeepClone(),
["tools"] = tools.DeepClone(),
["store"] = false,
["include"] = new JsonArray("reasoning.encrypted_content")
};
using StringContent content = new(
request.ToJsonString(), Encoding.UTF8, "application/json");
using HttpResponseMessage response = await openAIClient.PostAsync(
$"{endpoint}/openai/v1/responses", content);
string body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException(
$"Request rejected ({(int)response.StatusCode}): {body}");
}
return JsonNode.Parse(body)?.AsObject()
?? throw new InvalidOperationException("No response body was returned.");
}
static string GetOutputText(JsonObject response) => string.Concat(
response["output"]!.AsArray().OfType<JsonObject>()
.Where(item => item["type"]?.GetValue<string>() == "message")
.SelectMany(item => item["content"]!.AsArray().OfType<JsonObject>())
.Where(part => part["type"]?.GetValue<string>() == "output_text")
.Select(part => part["text"]!.GetValue<string>()));
static string RequiredEnvironment(string name)
{
string? value = Environment.GetEnvironmentVariable(name);
return !string.IsNullOrEmpty(value) ? value
: throw new InvalidOperationException($"Set {name} before running.");
}
const requiredEnvironment = (name) => {
const value = process.env[name];
if (!value) throw new Error(`Set ${name} before running.`);
return value;
};
const endpoint = requiredEnvironment("AZURE_OPENAI_ENDPOINT").replace(/\/+$/, "");
const deployment = requiredEnvironment("AZURE_OPENAI_DEPLOYMENT");
const apiKey = requiredEnvironment("AZURE_OPENAI_API_KEY");
const tools = [{
type: "function",
name: "get_order_status",
description: "Look up the status of an example order.",
parameters: {
type: "object",
properties: { order_id: { type: "string" } },
required: ["order_id"],
additionalProperties: false,
},
}];
const conversation = [{
role: "user",
content: "What is the status of order A123?",
}];
async function createResponse() {
const response = await fetch(`${endpoint}/openai/v1/responses`, {
method: "POST",
headers: { "Content-Type": "application/json", "api-key": apiKey },
body: JSON.stringify({
model: deployment,
input: conversation,
tools,
store: false,
include: ["reasoning.encrypted_content"],
}),
});
if (!response.ok) {
throw new Error(
`Request rejected (${response.status}): ${await response.text()}`,
);
}
return response.json();
}
function getOutputText(response) {
return response.output
.filter((item) => item.type === "message")
.flatMap((item) => item.content)
.filter((part) => part.type === "output_text")
.map((part) => part.text)
.join("");
}
// Preserve reasoning and tool calls before appending each tool result.
let completed = false;
for (let round = 0; round < 3; round++) {
const response = await createResponse();
if (!Array.isArray(response.output)) {
throw new Error("No output items were returned.");
}
if (!response.output.some(
(item) => item.type === "reasoning" && item.encrypted_content,
)) {
throw new Error("No encrypted reasoning item was returned.");
}
conversation.push(...response.output);
const calls = response.output.filter((item) => item.type === "function_call");
if (calls.length === 0) {
console.log(getOutputText(response));
completed = true;
break;
}
for (const call of calls) {
if (call.name !== "get_order_status") {
throw new Error(`Unexpected tool: ${call.name}`);
}
const argumentsObject = JSON.parse(call.arguments);
if (typeof argumentsObject.order_id !== "string") {
throw new Error("Missing or invalid order_id.");
}
// Replace this example data with your own trusted data source.
const result = {
order_id: argumentsObject.order_id,
status: argumentsObject.order_id === "A123" ? "Shipped" : "Not found",
};
conversation.push({
type: "function_call_output",
call_id: call.call_id,
output: JSON.stringify(result),
});
}
}
if (!completed) throw new Error("The tool-call limit was reached.");
將此樣本儲存為 StatelessToolCalling.java。
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
public class StatelessToolCalling {
private static final ObjectMapper JSON = new ObjectMapper();
public static void main(String[] args) throws Exception {
String endpoint = requiredEnvironment("AZURE_OPENAI_ENDPOINT")
.replaceAll("/+$", "");
String deployment = requiredEnvironment("AZURE_OPENAI_DEPLOYMENT");
String apiKey = requiredEnvironment("AZURE_OPENAI_API_KEY");
HttpClient openAIClient = HttpClient.newHttpClient();
JsonNode tools = JSON.readTree("""
[{
"type": "function",
"name": "get_order_status",
"description": "Look up the status of an example order.",
"parameters": {
"type": "object",
"properties": { "order_id": { "type": "string" } },
"required": ["order_id"],
"additionalProperties": false
}
}]
""");
ArrayNode conversation = JSON.createArrayNode();
conversation.add(JSON.createObjectNode()
.put("role", "user")
.put("content", "What is the status of order A123?"));
// Preserve reasoning and tool calls before appending each tool result.
for (int round = 0; round < 3; round++) {
JsonNode response = createResponse(openAIClient, endpoint, apiKey,
deployment, conversation, tools);
JsonNode items = response.get("output");
if (items == null || !items.isArray()) {
throw new IllegalStateException("No output items were returned.");
}
boolean hasEncryptedReasoning = false;
List<JsonNode> calls = new ArrayList<>();
for (JsonNode item : items) {
JsonNode encrypted = item.get("encrypted_content");
if ("reasoning".equals(item.path("type").asText())
&& encrypted != null && encrypted.isTextual()
&& !encrypted.asText().isEmpty()) {
hasEncryptedReasoning = true;
}
if ("function_call".equals(item.path("type").asText())) {
calls.add(item);
}
}
if (!hasEncryptedReasoning) {
throw new IllegalStateException(
"No encrypted reasoning item was returned.");
}
for (JsonNode item : items) {
conversation.add(item);
}
if (calls.isEmpty()) {
System.out.println(getOutputText(response));
return;
}
for (JsonNode call : calls) {
if (!"get_order_status".equals(call.path("name").asText())) {
throw new IllegalArgumentException(
"Unexpected tool: " + call.path("name").asText());
}
JsonNode arguments = JSON.readTree(
call.get("arguments").asText());
JsonNode orderIdNode = arguments.get("order_id");
if (orderIdNode == null || !orderIdNode.isTextual()) {
throw new IllegalArgumentException(
"Missing or invalid order_id.");
}
String orderId = orderIdNode.asText();
// Replace this example data with your trusted data source.
ObjectNode result = JSON.createObjectNode()
.put("order_id", orderId)
.put("status", "A123".equals(orderId)
? "Shipped" : "Not found");
conversation.add(JSON.createObjectNode()
.put("type", "function_call_output")
.put("call_id", call.get("call_id").asText())
.put("output", JSON.writeValueAsString(result)));
}
}
throw new IllegalStateException("The tool-call limit was reached.");
}
private static JsonNode createResponse(
HttpClient openAIClient, String endpoint, String apiKey,
String deployment, ArrayNode conversation,
JsonNode tools) throws Exception {
ObjectNode payload = JSON.createObjectNode();
payload.put("model", deployment);
payload.set("input", conversation);
payload.set("tools", tools);
payload.put("store", false);
payload.set("include", JSON.createArrayNode()
.add("reasoning.encrypted_content"));
HttpRequest request = HttpRequest.newBuilder(
URI.create(endpoint + "/openai/v1/responses"))
.header("Content-Type", "application/json")
.header("api-key", apiKey)
.POST(HttpRequest.BodyPublishers.ofString(
JSON.writeValueAsString(payload)))
.build();
HttpResponse<String> response = openAIClient.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException(
"Request rejected (" + response.statusCode() + "): "
+ response.body());
}
return JSON.readTree(response.body());
}
private static String getOutputText(JsonNode response) {
StringBuilder text = new StringBuilder();
for (JsonNode item : response.get("output")) {
if ("message".equals(item.path("type").asText())) {
for (JsonNode part : item.get("content")) {
if ("output_text".equals(part.path("type").asText())) {
text.append(part.get("text").asText());
}
}
}
}
return text.toString();
}
private static String requiredEnvironment(String name) {
String value = System.getenv(name);
if (value == null || value.isEmpty()) {
throw new IllegalStateException("Set " + name + " before running.");
}
return value;
}
}
這個 PowerShell 範例會直接將 JSON 請求傳送到 REST 端點。
$ErrorActionPreference = "Stop"
foreach ($name in "AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_API_KEY",
"AZURE_OPENAI_DEPLOYMENT") {
if (-not [Environment]::GetEnvironmentVariable($name)) {
throw "Set $name before running."
}
}
$endpoint = $env:AZURE_OPENAI_ENDPOINT.TrimEnd("/")
$deployment = $env:AZURE_OPENAI_DEPLOYMENT
$headers = @{ "api-key" = $env:AZURE_OPENAI_API_KEY }
$tools = @(@{
type = "function"
name = "get_order_status"
description = "Look up the status of an example order."
parameters = @{
type = "object"
properties = @{ order_id = @{ type = "string" } }
required = @("order_id")
additionalProperties = $false
}
})
$conversation = [System.Collections.Generic.List[object]]::new()
$conversation.Add(@{
role = "user"
content = "What is the status of order A123?"
})
function New-Response {
$body = @{
model = $deployment
input = $conversation.ToArray()
tools = $tools
store = $false
include = @("reasoning.encrypted_content")
} | ConvertTo-Json -Depth 100
Invoke-RestMethod -Method Post -Uri "$endpoint/openai/v1/responses" `
-Headers $headers -ContentType "application/json" -Body $body
}
function Get-OutputText($response) {
$parts = foreach ($item in $response.output) {
if ($item.type -eq "message") {
foreach ($part in $item.content) {
if ($part.type -eq "output_text") { $part.text }
}
}
}
$parts -join ""
}
# Preserve reasoning and tool calls before appending each tool result.
$completed = $false
for ($round = 0; $round -lt 3; $round++) {
$response = New-Response
$items = @($response.output)
if (-not ($items | Where-Object {
$_.type -eq "reasoning" -and $_.encrypted_content
})) {
throw "No encrypted reasoning item was returned."
}
foreach ($item in $items) {
$conversation.Add($item)
}
$calls = @($items | Where-Object { $_.type -eq "function_call" })
if ($calls.Count -eq 0) {
Write-Output (Get-OutputText $response)
$completed = $true
break
}
foreach ($call in $calls) {
if ($call.name -cne "get_order_status") {
throw "Unexpected tool: $($call.name)"
}
$arguments = $call.arguments | ConvertFrom-Json
if ($arguments.order_id -isnot [string]) {
throw "Missing or invalid order_id."
}
# Replace this example data with your own trusted data source.
$status = if ($arguments.order_id -ceq "A123") {
"Shipped"
} else {
"Not found"
}
$result = @{
order_id = $arguments.order_id
status = $status
} | ConvertTo-Json -Compress
$conversation.Add(@{
type = "function_call_output"
call_id = $call.call_id
output = $result
})
}
}
if (-not $completed) { throw "The tool-call limit was reached." }
範例在處理範例訂單狀態後,會列印模型的最終答案。 此函數使用範例資料,而非即時訂單系統。 迴圈限制回應請求次數為三個,若模型繼續請求工具,則會產生錯誤。
保持加密推理項目完整;不要嘗試閱讀或修改他們的加密內容。 關於函式定義及工具-結果格式,請參見 函式呼叫。
路由考量
如果你是透過 Azure API 管理 路由,請先驗證已加密的 reasoning replay 是否能在你設定的後端之間運作,再決定是否依賴它。 如果服務返回 invalid_encrypted_content,請檢查錯誤及資源路由,再決定是否重新啟動對話。
資料保護考量
加密推理項目在請求之間帶有不透明的推理上下文。 它們不會說明服務如何加密儲存的資料、哪些金鑰保護儲存的提示或對話狀態,或你的應用程式必須將傳回的項目存放在哪裡。
設定 store=false 並不代表能全面保證所有服務處理流程皆不保留任何資料。 關於服務端儲存與濫用監控的細節,請參見 Azure OpenAI 的資料、隱私與安全。
影像產生
回應 API 讓影像生成成為對話和多步驟工作流程的一部分。 它支援在情境中輸入與輸出影像,並內建產生與編輯影像的工具。
與獨立的影像 API 相比,回應 API 有兩大優勢:
-
串流:在產生過程中顯示部分影像輸出以改善感知延遲。
-
彈性輸入:除了原始影像位元組外,還接受影像檔案 ID 作為輸入。
註
回應 API 中的影像生成工具支援 gpt-image-1-series 模型,你可以從相容的聊天與推理模型中呼叫它。 關於目前支援的編排模型清單,請參閱本文後面的 支援模型 章節。
影像生成工具目前不支援串流模式。 若要串流部分影像,請直接在回應 API 外呼叫 影像生成 API 。
使用 Responses API 與 GPT 影像模型建立對話式影像體驗。
import base64
import os
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = OpenAI(
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
api_key=token_provider,
default_headers={
"x-ms-oai-image-generation-deployment": os.getenv("IMAGE_MODEL_NAME"),
"api_version": "preview",
},
)
response = client.responses.create(
model="MODEL_NAME",
input="Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
tools=[{"type": "image_generation"}],
)
image_data = [
output.result
for output in response.output
if output.type == "image_generation_call"
]
if image_data:
with open("otter.png", "wb") as f:
f.write(base64.b64decode(image_data[0]))
#pragma warning disable OPENAI001
using System.IO;
using System.Threading.Tasks;
using Azure.Identity;
using OpenAI.Responses;
using System.ClientModel.Primitives;
string endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
// API key authentication
ResponsesClient openAIClient = new(
credential: new ApiKeyCredential(Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")!),
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
// Microsoft Entra ID authentication (recommended)
BearerTokenPolicy tokenPolicy = new(
new DefaultAzureCredential(),
"https://ai.azure.com/.default");
ResponsesClient openAIClientEntra = new(
authenticationPolicy: tokenPolicy,
options: new ResponsesClientOptions { Endpoint = new Uri(endpoint) });
ImageGenerationTool imageTool = ResponseTool.CreateImageGenerationTool(model: "gpt-image-1");
CreateResponseOptions options = new()
{
Model = "MODEL_NAME",
InputItems =
{
ResponseItem.CreateUserMessageItem("Generate an image of an otter swimming in a pond.")
},
Tools = { imageTool }
};
ResponseResult response = await openAIClient.CreateResponseAsync(options);
foreach (ResponseItem item in response.OutputItems)
{
if (item is ImageGenerationCallResponseItem imageCall && imageCall.ImageResultBytes is not null)
{
await File.WriteAllBytesAsync("otter.png", imageCall.ImageResultBytes.ToArray());
Console.WriteLine($"Saved image. Revised prompt: {imageCall.RevisedPrompt}");
}
}
import fs from "fs";
import OpenAI from "openai";
import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
const tokenProvider = getBearerTokenProvider(
new DefaultAzureCredential(),
"https://ai.azure.com/.default"
);
const client = new OpenAI({
baseURL: "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",
apiKey: await tokenProvider(),
defaultHeaders: {
"x-ms-oai-image-generation-deployment": process.env.IMAGE_MODEL_NAME,
api_version: "preview",
},
});
const response = await client.responses.create({
model: "MODEL_NAME",
input: "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
tools: [{ type: "image_generation" }],
});
const imageBase64 = response.output
.filter((o) => o.type === "image_generation_call")
.map((o) => o.result)[0];
if (imageBase64) {
fs.writeFileSync("otter.png", Buffer.from(imageBase64, "base64"));
}
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.AuthenticationUtil;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.credential.BearerTokenCredential;
import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;
import com.openai.models.responses.ResponseOutputItem;
import com.openai.models.responses.Tool;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
String endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1";
OpenAIClient openAIClient = OpenAIOkHttpClient.builder()
.baseUrl(endpoint)
.credential(AzureApiKeyCredential.create(System.getenv("AZURE_OPENAI_API_KEY")))
.build();
Tool imageGen = Tool.ofImageGeneration(Tool.ImageGeneration.builder().build());
Response response = openAIClient.responses().create(
ResponseCreateParams.builder()
.model("MODEL_NAME")
.input("Generate an image of a gray tabby cat hugging an otter with an orange scarf.")
.addTool(imageGen)
.build());
response.output().stream()
.filter(ResponseOutputItem::isImageGenerationCall)
.map(ResponseOutputItem::asImageGenerationCall)
.findFirst()
.flatMap(call -> call.result())
.ifPresent(b64 -> {
try {
Files.write(Paths.get("otter.png"), Base64.getDecoder().decode(b64));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/responses \
-H "Content-Type: application/json" \
-H "api-key: $AZURE_OPENAI_API_KEY" \
-H "x-ms-oai-image-generation-deployment: $IMAGE_MODEL_NAME" \
-d '{
"model": "MODEL_NAME",
"input": "Generate an image of a gray tabby cat hugging an otter with an orange scarf.",
"tools": [{ "type": "image_generation" }]
}'
推理模型
關於如何搭配回應 API 使用推理模型的範例,請參考 推理模型指南。
電腦應用
搭配 Playwright 使用電腦的內容已移至專用的電腦使用模型指南。
故障排除
為什麼我的 API 會被終止以防萬一?
使用 Astra 模型時,為確保代理正確解讀並遵循您的指令,我們有一套系統,若偵測到代理可能未正確解讀您的指令,例如傳輸敏感資料、存取敏感資料或做出破壞性變更,則會停止回應 API 的會話。 如果你的會話結束了,這不一定代表客服犯了錯,只是值得回顧客服的操作,確保他正確解讀並遵循你的指示。
這個系統監控哪些 API 請求?
上述所述的同一個系統會在 Responses API 中以非同步方式監控發送至 Astra 的請求。 聊天完成 API 不會被這個特定的監控系統掃描。 我們建議使用 Responses API,以獲得代理型使用情境中最高的效能與安全性。
如何偵測這個系統在 API 中已經結束對話?
當安全系統偵測到代理程式可能以嚴重偏差的方式錯誤解讀指示時,API 會傳回安全註釋代碼 misalignment-enforcement。 此時,該會話無法繼續。
如果偵測到這樣的案例,我的申請應該怎麼做?
你可以考慮建立某種系統,讓某人能查看客服在這類對話中所採取的操作,例如提供使用者介面讓最終使用者檢視。 一旦 API 因此原因停止對話,便無法恢復。
解決常見的 API 錯誤
請參考以下指引來解決常見的 API 錯誤:
-
401/403:如果你使用 Microsoft Entra ID,請確保你的令牌範圍設定為
https://ai.azure.com/.default。 如果你使用 API 金鑰,請確認你使用的是該資源的正確金鑰。
-
404:確認
model 與你的部署名稱相符。
相關內容