ai-agents-for-beginners

Planning Design Pattern

(위 이미지를 클릭하면 이 강의의 영상을 볼 수 있습니다)

계획 설계

소개

이 강의에서는 다음 내용을 다룹니다:

학습 목표

이 강의를 완료한 후, 다음에 대한 이해를 갖게 됩니다:

전체 목표 정의 및 작업 분해

목표 및 작업 정의

대부분의 실제 작업은 한 번에 해결하기에는 너무 복잡합니다. AI 에이전트는 계획과 행동을 안내할 간결한 목표가 필요합니다. 예를 들어, 다음과 같은 목표를 생각해 보세요:

"3일 여행 일정표를 생성하세요."

이 목표는 간단히 표현할 수 있지만, 여전히 세부적으로 다듬어야 합니다. 목표가 명확할수록 에이전트(및 인간 협력자)가 올바른 결과를 달성하는 데 집중할 수 있습니다. 예를 들어, 항공편 옵션, 호텔 추천, 활동 제안이 포함된 포괄적인 일정표를 만드는 것처럼요.

작업 분해

크거나 복잡한 작업은 더 작고 목표 지향적인 하위 작업으로 나누면 더 관리하기 쉬워집니다.
여행 일정표 예제를 기준으로 목표를 다음과 같이 분해할 수 있습니다:

각 하위 작업은 전담 에이전트나 프로세스가 처리할 수 있습니다. 한 에이전트는 최적의 항공편 거래를 검색하는 데 특화될 수 있고, 다른 에이전트는 호텔 예약에 집중할 수 있습니다. 이후 조정 또는 “다운스트림” 에이전트가 이러한 결과를 하나의 통합된 일정표로 사용자에게 제공할 수 있습니다.

이 모듈식 접근 방식은 점진적인 개선도 가능하게 합니다. 예를 들어, 음식 추천이나 현지 활동 제안을 위한 전문 에이전트를 추가하고, 일정표를 시간이 지남에 따라 세부적으로 조정할 수 있습니다.

구조화된 출력

대규모 언어 모델(LLM)은 다운스트림 에이전트나 서비스가 더 쉽게 구문 분석하고 처리할 수 있는 구조화된 출력(예: JSON)을 생성할 수 있습니다. 이는 특히 계획 출력이 수신된 후 작업을 실행할 수 있는 다중 에이전트 환경에서 유용합니다. 간단한 개요는 다음과 같습니다.

다음 Python 코드 스니펫은 목표를 하위 작업으로 분해하고 구조화된 계획을 생성하는 간단한 계획 에이전트를 보여줍니다:

from pydantic import BaseModel
from enum import Enum
from typing import List, Optional, Union
import json
import os
from typing import Optional
from pprint import pprint
from autogen_core.models import UserMessage, SystemMessage, AssistantMessage
from autogen_ext.models.azure import AzureAIChatCompletionClient
from azure.core.credentials import AzureKeyCredential

class AgentEnum(str, Enum):
    FlightBooking = "flight_booking"
    HotelBooking = "hotel_booking"
    CarRental = "car_rental"
    ActivitiesBooking = "activities_booking"
    DestinationInfo = "destination_info"
    DefaultAgent = "default_agent"
    GroupChatManager = "group_chat_manager"

# Travel SubTask Model
class TravelSubTask(BaseModel):
    task_details: str
    assigned_agent: AgentEnum  # we want to assign the task to the agent

class TravelPlan(BaseModel):
    main_task: str
    subtasks: List[TravelSubTask]
    is_greeting: bool

client = AzureAIChatCompletionClient(
    model="gpt-4o-mini",
    endpoint="https://models.inference.ai.azure.com",
    # To authenticate with the model you will need to generate a personal access token (PAT) in your GitHub settings.
    # Create your PAT token by following instructions here: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
    credential=AzureKeyCredential(os.environ["GITHUB_TOKEN"]),
    model_info={
        "json_output": False,
        "function_calling": True,
        "vision": True,
        "family": "unknown",
    },
)

# Define the user message
messages = [
    SystemMessage(content="""You are an planner agent.
    Your job is to decide which agents to run based on the user's request.
                      Provide your response in JSON format with the following structure:
{'main_task': 'Plan a family trip from Singapore to Melbourne.',
 'subtasks': [{'assigned_agent': 'flight_booking',
               'task_details': 'Book round-trip flights from Singapore to '
                               'Melbourne.'}
    Below are the available agents specialised in different tasks:
    - FlightBooking: For booking flights and providing flight information
    - HotelBooking: For booking hotels and providing hotel information
    - CarRental: For booking cars and providing car rental information
    - ActivitiesBooking: For booking activities and providing activity information
    - DestinationInfo: For providing information about destinations
    - DefaultAgent: For handling general requests""", source="system"),
    UserMessage(
        content="Create a travel plan for a family of 2 kids from Singapore to Melboune", source="user"),
]

response = await client.create(messages=messages, extra_create_args={"response_format": 'json_object'})

response_content: Optional[str] = response.content if isinstance(
    response.content, str) else None
if response_content is None:
    raise ValueError("Response content is not a valid JSON string" )

pprint(json.loads(response_content))

# # Ensure the response content is a valid JSON string before loading it
# response_content: Optional[str] = response.content if isinstance(
#     response.content, str) else None
# if response_content is None:
#     raise ValueError("Response content is not a valid JSON string")

# # Print the response content after loading it as JSON
# pprint(json.loads(response_content))

# Validate the response content with the MathReasoning model
# TravelPlan.model_validate(json.loads(response_content))

다중 에이전트 오케스트레이션을 활용한 계획 에이전트

이 예제에서는 Semantic Router Agent가 사용자 요청(예: “여행을 위한 호텔 계획이 필요합니다.”)을 수신합니다.

플래너는 다음을 수행합니다:


from pydantic import BaseModel

from enum import Enum
from typing import List, Optional, Union

class AgentEnum(str, Enum):
    FlightBooking = "flight_booking"
    HotelBooking = "hotel_booking"
    CarRental = "car_rental"
    ActivitiesBooking = "activities_booking"
    DestinationInfo = "destination_info"
    DefaultAgent = "default_agent"
    GroupChatManager = "group_chat_manager"

# Travel SubTask Model

class TravelSubTask(BaseModel):
    task_details: str
    assigned_agent: AgentEnum # we want to assign the task to the agent

class TravelPlan(BaseModel):
    main_task: str
    subtasks: List[TravelSubTask]
    is_greeting: bool
import json
import os
from typing import Optional

from autogen_core.models import UserMessage, SystemMessage, AssistantMessage
from autogen_ext.models.openai import AzureOpenAIChatCompletionClient

# Create the client with type-checked environment variables

client = AzureOpenAIChatCompletionClient(
    azure_deployment=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME"),
    model=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME"),
    api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
)

from pprint import pprint

# Define the user message

messages = [
    SystemMessage(content="""You are an planner agent.
    Your job is to decide which agents to run based on the user's request.
    Below are the available agents specialized in different tasks:
    - FlightBooking: For booking flights and providing flight information
    - HotelBooking: For booking hotels and providing hotel information
    - CarRental: For booking cars and providing car rental information
    - ActivitiesBooking: For booking activities and providing activity information
    - DestinationInfo: For providing information about destinations
    - DefaultAgent: For handling general requests""", source="system"),
    UserMessage(content="Create a travel plan for a family of 2 kids from Singapore to Melbourne", source="user"),
]

response = await client.create(messages=messages, extra_create_args={"response_format": TravelPlan})

# Ensure the response content is a valid JSON string before loading it

response_content: Optional[str] = response.content if isinstance(response.content, str) else None
if response_content is None:
    raise ValueError("Response content is not a valid JSON string")

# Print the response content after loading it as JSON

pprint(json.loads(response_content))

이전 코드의 출력은 다음과 같으며, 이를 사용하여 assigned_agent로 라우팅하고 최종 사용자에게 여행 계획을 요약할 수 있습니다.

{
    "is_greeting": "False",
    "main_task": "Plan a family trip from Singapore to Melbourne.",
    "subtasks": [
        {
            "assigned_agent": "flight_booking",
            "task_details": "Book round-trip flights from Singapore to Melbourne."
        },
        {
            "assigned_agent": "hotel_booking",
            "task_details": "Find family-friendly hotels in Melbourne."
        },
        {
            "assigned_agent": "car_rental",
            "task_details": "Arrange a car rental suitable for a family of four in Melbourne."
        },
        {
            "assigned_agent": "activities_booking",
            "task_details": "List family-friendly activities in Melbourne."
        },
        {
            "assigned_agent": "destination_info",
            "task_details": "Provide information about Melbourne as a travel destination."
        }
    ]
}

이전 코드 샘플이 포함된 예제 노트북은 여기에서 확인할 수 있습니다.

반복적 계획

일부 작업은 하위 작업의 결과가 다음 작업에 영향을 미치는 경우처럼, 반복적이거나 재계획이 필요합니다. 예를 들어, 에이전트가 항공편 예약 중 예상치 못한 데이터 형식을 발견하면, 호텔 예약으로 넘어가기 전에 전략을 조정해야 할 수 있습니다.

또한, 사용자 피드백(예: 사용자가 더 이른 항공편을 선호한다고 결정하는 경우)은 부분적인 재계획을 유발할 수 있습니다. 이러한 동적이고 반복적인 접근 방식은 최종 솔루션이 현실적인 제약 조건과 변화하는 사용자 선호도에 맞도록 보장합니다.

예: 샘플 코드

from autogen_core.models import UserMessage, SystemMessage, AssistantMessage
#.. same as previous code and pass on the user history, current plan
messages = [
    SystemMessage(content="""You are a planner agent to optimize the
    Your job is to decide which agents to run based on the user's request.
    Below are the available agents specialized in different tasks:
    - FlightBooking: For booking flights and providing flight information
    - HotelBooking: For booking hotels and providing hotel information
    - CarRental: For booking cars and providing car rental information
    - ActivitiesBooking: For booking activities and providing activity information
    - DestinationInfo: For providing information about destinations
    - DefaultAgent: For handling general requests""", source="system"),
    UserMessage(content="Create a travel plan for a family of 2 kids from Singapore to Melbourne", source="user"),
    AssistantMessage(content=f"Previous travel plan - {TravelPlan}", source="assistant")
]
# .. re-plan and send the tasks to respective agents

더 포괄적인 계획을 위해 Magnetic One을 확인해 보세요.

요약

이 글에서는 사용 가능한 에이전트를 동적으로 선택할 수 있는 플래너를 생성하는 방법의 예를 살펴보았습니다. 플래너의 출력은 작업을 분해하고 에이전트를 할당하여 실행할 수 있도록 합니다. 에이전트가 작업을 수행하는 데 필요한 기능/도구에 접근할 수 있다고 가정합니다. 에이전트 외에도 반영, 요약, 라운드 로빈 채팅과 같은 다른 패턴을 포함하여 추가로 사용자 정의할 수 있습니다.

추가 자료

. 이 구현에서는 오케스트레이터가 작업별 계획을 생성하고 이러한 작업을 사용 가능한 에이전트에 위임합니다. 오케스트레이터는 계획뿐만 아니라 작업 진행 상황을 모니터링하고 필요에 따라 재계획하는 추적 메커니즘도 사용합니다.

계획 설계 패턴에 대해 더 궁금한 점이 있으신가요?

Azure AI Foundry Discord에 참여하여 다른 학습자들과 만나고, 오피스 아워에 참석하며 AI 에이전트에 대한 질문에 답을 얻으세요.

이전 강의

신뢰할 수 있는 AI 에이전트 구축

다음 강의

다중 에이전트 설계 패턴


면책 조항:
이 문서는 AI 번역 서비스 Co-op Translator를 사용하여 번역되었습니다. 정확성을 위해 최선을 다하고 있지만, 자동 번역에는 오류나 부정확성이 포함될 수 있습니다. 원본 문서를 해당 언어로 작성된 상태에서 권위 있는 자료로 간주해야 합니다. 중요한 정보의 경우, 전문 번역가에 의한 번역을 권장합니다. 이 번역 사용으로 인해 발생하는 오해나 잘못된 해석에 대해 당사는 책임을 지지 않습니다.