이 항목에서는 AI Agent Studio 내에서 사용자 정의 모델 정의에 대해 Microsoft Entra ID(이전의 Azure AD) 인증을 구성하는 단계를 설명하며, 이를 통해 사용자의 모델이 Automation 360와 원활하게 통합될 수 있도록 지원합니다.

Entra ID는 OAuth2 인증을 통해서만 지원되며, Entra 기반 액세스 토큰이 필요한 Microsoft 호스팅 모델과 통합할 때는 이 방법이 필수입니다.
  • 대상 모델 공급업체가 OAuth2 인증만 지원하는 경우 Entra ID를 사용하십시오.
  • API 키 인증을 OAuth2와 병행하여 사용할 수 없는 경우, Azure 호스팅 서비스에서 발생하는 상황입니다.
  • 예를 들어, Azure OpenAI 모델은 기본적으로 API 키 인증을 사용하지만, 보안 요구 사항에 따라 Entra ID를 통한 OAuth2가 필요하다면 사용자 정의 모델 정의 경로를 통해 모델을 구성해야 합니다.

Postman 컬렉션(Entra ID 샘플)을 다운로드하고 사용하려면, 이 링크 Postman 컬렉션 - Entra ID 샘플을 클릭하십시오.

전제 조건

  • Entra ID가 활성화된 Azure 계정. 필요한 세부 정보를 수집합니다.
    • 클라이언트 ID
    • 클라이언트 비밀
    • 인증 URL
    • 토큰 URL
  • Entra ID를 사용하여 OAuth 연결을 구성합니다. 자세한 내용은 Microsoft Entra ID 구성 항목을 참조하십시오.

왜 사용자 정의 모델과 Entra ID를 사용하나요?

Azure OpenAI는 UI에서 API Key 인증을 지원합니다. 하지만 OAuth2/Entra ID를 사용해야 하는 경우라면 사용자 정의 모델 API를 통해 정의해야 합니다. 이는 공급업체가 UI에서 한 번에 하나의 인증 방식만 노출할 수 있기 때문입니다.

프로시저

  1. OAuth 연결이 설정되면 사용자 지정 모델 API 생성를 사용하여 사용자 정의 모델 정의를 생성할 수 있습니다. 이 API는 공급업체 이름, 모델 이름, 인증 프로토콜, 그리고 API 엔드포인트 세부 정보를 포함하여 모델을 설명하는 JSON 페이로드 스키마를 필요로 합니다.
  2. 구성된 Entra ID를 사용하여 사용자 정의 모델 연결을 만들려면 다음 authAction 블록을 사용하십시오. 주요 인증 매개변수는 다음과 같습니다.
    "authAction": {
      "authType": "OAUTH2",
      "oAuth": {
        "location": "header",
        "keyName": "Authorization",
        "prefix": "Bearer "
      }
    }
    
    • authType: OAUTH2
    • 위치: header
    • keyName: Authorization
    • 접두사: Bearer 및 토큰 포함(Bearer 뒤에 공백 포함)
  3. 요청을 보냅니다. 요청에 대한 예시는 아래에 설명되어 있습니다. 여기까지 성공하면, 사용자 정의 모델 정의가 생성되며 AI Agent Studio에서 모델 연결을 만들 때 선택할 수 있습니다.

Entra ID로 사용자 정의 모델 정의

다음은 Entra OAuth2를 사용한 Azure OpenAI GPT-4.1 mini 배포의 간략한 예시입니다.

POST https:/{{ControlRoomURL}}/gai/prompttools/v1/custommodel
요청 본문:
{
	"name": "AAI Docs Example - Entra",
	"version": "0",
	"authAction": {
		"authType": "OAUTH2",
		"oAuth": {
			"location": "header",
			"keyName": "Authorization",
			"prefix": "Bearer "
		}
	},
	"apiType": "REST",
	"actions": [
		{
			"name": "gpt-4.1-mini",
			"displayName": "GPT-4.1 mini",
			"description": "GPT-4.1 mini provides a balance between intelligence, speed, and cost that makes it an attractive model for many use cases.",
			"method": "POST",
			"uri": "https://{resourceName}.openai.azure.com/openai/deployments/{deployment}/chat/completions?api-version={apiVersion}",
			"params": [
				{
					"type": "PATH_PARAM",
					"attribute": [
						{
							"name": "resourceName",
							"label": "Resource Name",
							"value": {
								"type": "TEXT",
								"string": "genaitemplateplatformeastca"
							}
						}
					]
				},
				{
					"type": "PATH_PARAM",
					"attribute": [
						{
							"name": "deployment",
							"label": "Deployment",
							"value": {
								"type": "TEXT",
								"string": "deploy-gpt-4.1"
							}
						}
					]
				},
				{
					"type": "PATH_PARAM",
					"attribute": [
						{
							"name": "apiVersion",
							"label": "API Version",
							"value": {
								"type": "TEXT",
								"string": "2025-01-01-preview"
							}
						}
					]
				}
			],
			"request": {
				"raw": {
					"body": "{\"model\": \"gpt-4.1\",\"messages\":[{\"role\":\"system\",\"content\":\"system prompt\"},{\"role\":\"user\",\"content\":\"some prompt query\"}],\"max_completion_tokens\":500}",
					"variables": [
						{
							"path": "$.max_completion_tokens",
							"attribute": {
								"name": "max_completion_tokens",
								"label": "Max tokens",
								"value": {
									"type": "INTEGER",
									"number": "2048"
								},
								"annotations": [
									"MODEL_PARAMETER"
								],
								"canonicalName": "choices[0].completionTokens"
							}
						},
						{
							"path": "$.messages[1].content",
							"attribute": {
								"name": "prompt",
								"label": "prompt",
								"value": {
									"type": "TEXT"
								},
								"annotations": [
									"PROMPT_QUERY"
								]
							}
						},
						{
							"path": "$.messages[0].content",
							"attribute": {
								"name": "systemPrompt",
								"label": "System Prompt",
								"value": {
									"type": "TEXT"
								},
								"annotations": [
									"SYSTEM_PROMPT_MESSAGE"
								]
							}
						}
					]
				}
			},
			"response": {
				"body": "{\n    \"id\": \"chatcmpl-APwQdLa9WCQAdZg0dO5OjGr2ER4sX\",\n    \"object\": \"chat.completion\",\n    \"created\": 1730746163,\n    \"model\": \"o3-mini-2025-01-31\",\n    \"choices\": [\n        {\n            \"index\": 0,\n            \"message\": {\n                \"role\": \"assistant\",\n                \"content\": \"Sure! They are one of the most mysterious and exciting objects in space.\",\n                \"refusal\": null\n            },\n            \"finish_reason\": \"stop\"\n        }\n    ],\n    \"usage\": {\n        \"prompt_tokens\": 17,\n        \"completion_tokens\": 959,\n        \"total_tokens\": 976,\n        \"prompt_tokens_details\": {\n            \"cached_tokens\": 0\n        },\n        \"completion_tokens_details\": {\n            \"reasoning_tokens\": 64\n        }\n    },\n    \"system_fingerprint\": \"fp_35c19d48ca\"\n}",
				"variables": [
					{
						"path": "$.usage.completion_tokens",
						"attribute": {
							"name": "completion_tokens",
							"label": "completion_tokens",
							"value": {
								"type": "INTEGER"
							},
							"annotations": [
								"RESPONSE_PARAMETER"
							],
							"canonicalName": "choices[0].completionTokens"
						}
					},
					{
						"path": "$.choices[0].message.content",
						"attribute": {
							"name": "content",
							"label": "content",
							"value": {
								"type": "TEXT",
								"string": "Some response from LLM"
							},
							"annotations": [
								"RESPONSE_PARAMETER"
							],
							"canonicalName": "choices[0].value"
						}
					},
					{
						"path": "$.model",
						"attribute": {
							"name": "model",
							"label": "model",
							"value": {
								"type": "TEXT"
							},
							"annotations": [
								"RESPONSE_PARAMETER"
							],
							"canonicalName": "model_name"
						}
					},
					{
						"path": "$.usage.prompt_tokens",
						"attribute": {
							"name": "prompt_tokens",
							"label": "prompt_tokens",
							"value": {
								"type": "INTEGER"
							},
							"annotations": [
								"RESPONSE_PARAMETER"
							],
							"canonicalName": "choices[0].promptTokens"
						}
					},
					{
						"path": "$.usage.total_tokens",
						"attribute": {
							"name": "total_tokens",
							"label": "total_tokens",
							"value": {
								"type": "INTEGER"
							},
							"annotations": [
								"RESPONSE_PARAMETER"
							],
							"canonicalName": "choices[0].totalTokens"
						}
					}
				]
			}
		}
	]
}