본문 바로가기
HRDI_AI/[인공지능] AI 멀티 에이전트 서비스 개발을 위한 CrewAI

3. Agent 및 Task 설계, 프롬프트 작성법

by Toddler_AD 2025. 5. 30.

Agent 및 Task 설계와 프롬프트 작성법

실습 목표

  • CrewAI 프레임워크를 활용하여 다중 에이전트 시스템을 구성하고 여행 일정 생성 예제를 통해 실습합니다.
  • Agent(에이전트)의 역할(Role), 목표(Goal), 배경(Backstory)을 정의하고 Task(태스크)의 설명(프롬프트)과 기대 출력(Expected Output)을 작성하는 방법을 익힙니다.
  • 여러 에이전트가 협업하여 작업을 수행하는 과정(예: 정보 조사 에이전트 + 일정 기획 에이전트)을 단계별로 경험합니다.
  • 프롬프트에 추가 정보를 요구하거나 제약조건을 넣어 출력 결과의 품질을 개선하는 방법을 학습합니다.

사전 요구사항

  • Python 3.x가 설치되어 있어야 합니다 (권장: Python 3.10 이상).
  • CrewAI 라이브러리가 설치되어 있어야 합니다 (터미널에서 pip install crewai 및 추가 도구를 위해 pip install 'crewai[tools]' 실행).
  • 인터넷 연결: 실습 코드 중 웹 검색 도구를 사용하는 부분이 있으므로 인터넷 접속이 가능해야 합니다.
  • OpenAI API 키: OpenAI의 GPT 모델을 사용하므로, .env 파일에 OPENAI_API_KEY를 설정해야 합니다 (없으면 코드 실행 시 오류 발생).
  • 코드 편집기/실행 환경: Visual Studio Code (VS Code)와 같은 IDE 또는 터미널에서 Python 파일을 실행할 수 있는 환경.

NOTE: .env 파일은 프로젝트 루트에 위치시키고, 내용에 OPENAI_API_KEY=<YOUR_API_KEY> 형식으로 OpenAI API 키를 적어두세요. CrewAI의 LLM으로 OpenAI의 GPT-4 모델(gpt-4o-mini)을 사용하므로 해당 키가 필요합니다.


03-1.travel_planner.py : 단일 에이전트로 여행 일정 생성

시나리오: CrewAI 프레임워크로 부산 3일 여행 일정을 자동 생성하는 단일 에이전트 시스템을 구현합니다. 한 명의 "여행 기획자" 에이전트가 주어진 요청에 따라 일정을 계획합니다.

코드 설명

먼저 필요한 라이브러리를 불러오고 환경변수를 설정합니다. .env에서 OpenAI API 키를 로드하고, LLM(Large Language Model)을 초기화합니다. 이 예제에서는 OpenAI의 GPT-4 모델의 미니 버전을 사용하며, 온도(temperature)는 0.7로 설정했습니다 (출력의 창의성 정도 조절).

from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
from crewai import Agent, Task, Crew, Process

# .env 파일 로드하여 OPENAI_API_KEY 등 환경변수 설정
load_dotenv()
openai_key = os.getenv("OPENAI_API_KEY")
if not openai_key:
    raise EnvironmentError("OPENAI_API_KEY not found. Please set it in a .env file.")

# LLM 초기화 (OpenAI GPT-4o-mini 모델 사용)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)

이어서 여행 기획자 에이전트를 정의합니다. Agent 클래스를 사용하여 에이전트를 생성하며, 다음과 같은 속성을 부여합니다:

  • role: 에이전트의 역할 명칭 (예: "여행 기획자").
  • goal: 에이전트의 목표 또는 임무 설명. 여기서는 *"사용자의 요청에 따라 여행 일정을 계획하고 제안합니다."*와 같이 정의했습니다.
  • backstory: 에이전트의 배경 설정으로, 실제 성능에는 직접 영향은 없지만 에이전트의 행동 스타일에 간접 영향을 줄 수 있습니다. 예에서는 *"여행사에서 10년 경력의 전문 여행 플래너"*로 설정했습니다.
  • llm: 앞서 초기화한 LLM 객체를 지정합니다 (이 에이전트가 사용할 언어 모델).
  • verbose: True로 설정하면 동작 과정을 상세히 콘솔에 출력합니다 (디버깅이나 학습용으로 유용).
# 여행 기획자 에이전트 정의
travel_agent = Agent(
    role="여행 기획자",
    goal="사용자의 요청에 따라 여행 일정을 계획하고 제안합니다.",
    backstory="여행사에서 10년 경력의 전문 여행 플래너로, 다양한 국내 여행 코스를 알고 있습니다.",
    llm=llm,
    verbose=True
)

이제 **여행 일정 작성 작업(Task)**을 정의합니다. Task 클래스에는 주어진 작업에 대한 **프롬프트(description)**와 해당 작업을 수행할 에이전트, 그리고 예상 출력 형식을 기술합니다:

  • description: 에이전트에게 주어지는 지시사항 또는 프롬프트입니다. 문자열로 작성하며, 여러 줄에 걸쳐 상세 요구사항을 기술할 수 있습니다.
    ➡ 예시 프롬프트: 부산에서 3일간 여행 일정을 계획하도록 요청하면서, *"1일차, 2일차, 3일차로 나누고 각 일자마다 아침/점심/저녁에 할 활동을 상세히 제안"*하도록 요구했습니다. 또한 "부산의 주요 관광지와 현지 맛집 추천 포함, 교통 수단 정보나 팁이 있으면 제공" 등 세부 요구사항도 포함되어 있습니다.
  • agent: 이 Task를 수행할 책임이 있는 에이전트를 지정합니다 (travel_agent를 연결).
  • expected_output: 예상되는 출력 형태나 내용에 대한 요약을 적습니다. (예: "Day 1, Day 2, Day 3으로 구분된 상세 일정 제안"). 엄격한 검증 용도는 아니지만, 어떤 결과를 기대하는지 표현하여 나중에 결과를 확인하거나 디버깅할 때 도움을 줍니다.
# 부산 3일 여행 일정 작성 Task 정의
itinerary_task = Task(
    description=(
        "부산에서 3일간 여행 일정을 계획해 주세요.\n"
        "1일차, 2일차, 3일차로 나누고, 각 일자마다 아침/점심/저녁에 할 활동을 상세히 제안하세요.\n"
        "여행 일정에는 부산의 주요 관광지와 현지 맛집 추천을 포함하고, 교통 수단 정보나 팁이 있으면 함께 제공하세요."
    ),
    agent=travel_agent,
    expected_output="Day 1, Day 2, Day 3으로 구분된 상세 일정 제안"
)

마지막으로 Crew를 구성하고 실행합니다. Crew는 에이전트와 태스크를 묶어 전체 프로세스를 관리하는 객체입니다. 여기서는 에이전트 리스트에 travel_agent 하나, 태스크 리스트에 itinerary_task 하나만 넣었습니다. process=Process.sequential로 설정하여 Task들을 순차적으로 실행하도록 합니다 (지금은 태스크가 하나라 자동으로 순차 실행됩니다).

crew_single.kickoff()를 호출하면 Crew에 속한 태스크들이 정의된 순서에 따라 실행됩니다. 실행 결과는 result_single 변수에 저장되며, 이어서 콘솔에 출력합니다.

# Crew 생성 및 실행 (순차 실행 - Task가 하나뿐이므로 순차 처리)
crew_single = Crew(
    agents=[travel_agent],
    tasks=[itinerary_task],
    process=Process.sequential,
    verbose=True
)
print("=== [단일 에이전트] 부산 3일 일정 생성 시작 ===")
result_single = crew_single.kickoff()
print("=== [단일 에이전트] 생성된 부산 3일 일정 ===")
print(result_single)

실행 방법

  1. 터미널에서 해당 파일이 있는 디렉토리로 이동합니다.
  2. 다음 명령을 실행하여 코드를 실행합니다:
    python 03-1.travel_planner.py
    
  3. 실행하면 OpenAI API를 통해 에이전트가 프롬프트에 답을 생성하고, 최종적으로 부산 3일 여행 일정 텍스트가 출력됩니다. (API 키 미설정 등 문제가 있다면 오류가 발생하니, 사전 요구사항을 확인하세요.)

예상 실행 결과

콘솔에 에이전트의 프롬프트 응답 결과가 출력됩니다. 예를 들어, 다음과 같이 Day 1Day 2Day 3로 구분된 여행 일정이 생성될 것입니다:

=== [단일 에이전트] 생성된 부산 3일 일정 ===
Day 1:
- **아침:** 해운대 해수욕장에서 일출 감상. 주변 카페에서 간단한 조식.
- **점심:** 해운대 시장 탐방 후 돼지국밥 맛집에서 점심 식사.
- **저녁:** 광안리 해변 산책 및 광안대교 야경 감상. 해변 근처 횟집에서 저녁 식사.

Day 2:
- **아침:** 감천문화마을 방문하여 벽화마을 골목 산책.
- **점심:** 자갈치 시장에서 신선한 해산물로 식사.
- **저녁:** 남포동 BIFF 거리 구경 후 부산역 인근 밀면 맛집에서 저녁.

Day 3:
- **아침:** 태종대 공원에서 등대 산책 및 경치 감상.
- **점심:** 송도 해상케이블카 이용 후 송도 해수욕장 근처 음식점에서 식사.
- **저녁:** 부산 대표 음식인 씨앗호떡 등 길거리 간식 맛보고 귀경 준비.

예시 출력은 이해를 돕기 위한 것으로, 실행할 때마다 세부 내용은 달라질 수 있지만 각 날의 오전/점심/저녁으로 구성된 일정과 주요 관광지, 음식점, 활동 등이 포함된다는 점은 공통적입니다. 또한 에이전트가 자체 지식에 기반해 일정을 생성하므로, 최신 정보나 실제 이동 시간 등은 반영되지 않을 수 있습니다 (이 부분을 개선하기 위해 다음 실습에서 정보 검색을 도입할 것입니다).


03-2.travel_planner.py : 두 에이전트 협업으로 일정 생성

시나리오: 이번에는 두 명의 에이전트가 협업하여 부산 3일 일정을 작성합니다. 하나의 에이전트는 정보를 검색하고, 다른 에이전트는 그 정보를 활용해 일정 작성을 합니다. 이를 통해 역할 분담과 태스크 간 컨텍스트 공유를 배우겠습니다.

코드 설명

이전 실습과 마찬가지로 환경설정 (env 로드, LLM 초기화)은 동일하게 이뤄집니다. 핵심 차이는 두 가지입니다:

  1. **웹 검색 도구(Tool)**의 도입과 정보 조사 에이전트에 해당 도구 장착
  2. 두 개의 에이전트와 두 개의 태스크를 순차적으로 실행하고 앞 태스크의 결과를 다음 태스크에 전달하는 구조

1. 커스텀 웹 검색 도구 준비

CrewAI에서는 에이전트에 **도구(Tool)**를 장착하여 외부 기능을 사용할 수 있습니다. 여기서는 DuckDuckGo 검색을 위한 커스텀 도구를 만들고 정보 조사자가 사용하도록 합니다. BaseTool 클래스를 상속하여 MyCustomDuckDuckGoTool을 정의하고 _run 메서드에서 실제 검색 동작을 구현했습니다 (LangChain 커뮤니티의 DuckDuckGoSearchRun 도구를 활용). 이렇게 함으로써 에이전트는 프롬프트를 해결하기 위해 인터넷 검색을 할 수 있게 됩니다.

from crewai.tools import BaseTool
from langchain_community.tools import DuckDuckGoSearchRun

class MyCustomDuckDuckGoTool(BaseTool):
    name: str = "DuckDuckGo Search Tool"
    description: str = "웹에서 최신 정보를 검색할 수 있는 도구입니다."

    def _run(self, query: str) -> str:
        duckduckgo_tool = DuckDuckGoSearchRun()
        response = duckduckgo_tool.invoke(query)
        return response

# DuckDuckGo 검색 도구 인스턴스 생성
search_tool = MyCustomDuckDuckGoTool()

2. 두 에이전트 정의 (정보 조사자 & 일정 기획자)

이제 정보 조사자 에이전트와 여행 일정 기획자 에이전트 두 명을 정의합니다.

  • research_agent (정보 조사자): 최신 여행 정보를 찾아 제공하는 역할입니다. 앞서 만든 search_tool을 tools 매개변수에 넣어, 이 에이전트가 프롬프트를 처리하는 중에 웹 검색을 활용할 수 있게 합니다. 목표는 *"여행에 필요한 최신 정보를 조사하여 제공"*하는 것이며, 배경은 *"온라인 정보 검색에 능통한 여행 정보 전문가"*로 설정했습니다.
  • planner_agent (일정 기획자): 제공된 정보를 활용해 완성도 높은 일정을 작성하는 역할입니다. 이 에이전트는 주어진 컨텍스트(앞서 조사된 정보)를 바탕으로 일정을 계획합니다. 목표는 *"제공된 정보를 활용해 완성도 높은 여행 일정을 작성"*하는 것이며, 배경은 *"국내 여행 일정을 여러 차례 기획한 경험이 풍부한 전문가"*로 설정했습니다. 이 에이전트는 별도의 도구 없이 LLM만 사용합니다.
# 정보 조사 에이전트 정의
research_agent = Agent(
    role="정보 조사자",
    goal="여행에 필요한 최신 정보를 조사하여 제공합니다.",
    backstory="온라인 정보 검색에 능통한 여행 정보 전문가입니다.",
    llm=llm,
    tools=[search_tool],    # 웹 검색 도구 장착
    verbose=True
)

# 일정 작성 에이전트 정의
planner_agent = Agent(
    role="여행 일정 기획자",
    goal="제공된 정보를 활용해 완성도 높은 여행 일정을 작성합니다.",
    backstory="국내 여행 일정을 여러 차례 기획한 경험이 풍부한 전문가입니다.",
    llm=llm,
    verbose=True
)

3. 두 개의 Task 정의 및 연결

이제 두 개의 Task를 만듭니다. 첫 번째 Task는 정보 조사자가 수행할 내용이고, 두 번째 Task는 일정 기획자가 수행할 내용입니다.

  • research_task: 부산 여행에 필요한 핵심 정보를 조사하는 작업입니다. description에 예시로 *"부산의 인기 관광지 목록, 지역별 맛집 추천, 이동 시 유용한 교통 정보 등을 최신 자료 기반으로 정리"*하도록 지시하고 있습니다. 이 Task는 agent=research_agent로 설정되어 있어 정보 조사자에게 할당됩니다. expected_output에는 *"부산 여행에 대한 요약 정보 목록"*이라고 적어, 이 작업의 결과로 부산 여행과 관련된 요약 정보(장소 리스트, 팁 등)가 나올 것으로 기대함을 명시했습니다.
  • planning_task: 위에서 조사된 정보를 참고하여 실제 3일 일정 표를 짜는 작업입니다. description에서는 *"위의 조사 결과를 참고하여 부산 3일 여행 일정을 작성"*하고, 각 날짜별 오전/오후/저녁 계획을 세우며, 조사된 관광지와 맛집 정보를 일정에 반영하도록 요청합니다. 또한 *"일정에는 방문지에 대한 간단한 설명이나 여행 팁도 포함"*하도록 요구하여, 단순 나열이 아니라 부가 설명도 달도록 했습니다. 이 Task는 agent=planner_agent로 설정되어 일정 기획자가 담당합니다. 중요한 부분은 context=[research_task]로 설정한 것입니다. 이것은 이 Task를 실행할 때 research_task의 결과를 컨텍스트로 전달한다는 뜻입니다. 즉, 일정 기획자 에이전트는 프롬프트를 생성할 때 이전에 조사된 정보를 참고할 수 있게 됩니다. expected_output에는 *"조사된 정보를 반영한 3일간의 여행 일정"*이라고 기대 결과를 작성했습니다.
# 정보 조사 Task 정의
research_task = Task(
    description=(
        "부산 여행을 위해 알아야 할 핵심 정보를 조사하세요.\n"
        "부산의 인기 관광지 목록, 지역별 맛집 추천, 이동 시 유용한 교통 정보 등을 최신 자료를 기반으로 정리해 주세요."
    ),
    agent=research_agent,
    expected_output="부산 여행에 대한 요약 정보 목록"
)

# 일정 작성 Task 정의 (이전 Task 결과를 context로 활용)
planning_task = Task(
    description=(
        "위의 조사 결과를 참고하여 부산에서 3일 동안 머무는 여행 일정을 작성해 주세요.\n"
        "각 날짜별로 오전/오후/저녁 계획을 세우고, 조사된 관광지와 맛집 정보를 일정에 반영하세요.\n"
        "일정에는 방문지에 대한 간단한 설명이나 여행 팁도 포함해 주세요."
    ),
    agent=planner_agent,
    context=[research_task],  # 이전 조사 결과를 컨텍스트로 전달
    expected_output="조사된 정보를 반영한 3일간의 여행 일정"
)

여기서 context=[research_task] 설정에 주목하세요. CrewAI에서는 이렇게 앞선 Task의 결과를 다음 Task에 넘겨줄 수 있습니다. 내부적으로는 research_task의 출력이 planning_task에 입력으로 제공되어, 일정 기획자 LLM 프롬프트에 자동으로 포함됩니다. 따라서 두 번째 에이전트는 첫 번째 에이전트가 찾아준 최신 정보를 활용해 일정을 세울 수 있습니다.

4. Crew 실행 설정 및 실행

두 에이전트와 두 태스크를 준비했으니, Crew를 생성합니다. 에이전트 리스트에는 [research_agent, planner_agent]를, 태스크 리스트에는 [research_task, planning_task]를 지정합니다. process=Process.sequential로 하여 순차 처리를 명시합니다 (첫 번째 태스크 완료 후 두 번째 태스크 실행).

# 두 에이전트를 Crew로 묶어 순차 실행
crew_multi = Crew(
    agents=[research_agent, planner_agent],
    tasks=[research_task, planning_task],
    process=Process.sequential,
    verbose=True
)

print("\n=== [협업 에이전트] 부산 3일 일정 생성 시작 ===")
result_multi = crew_multi.kickoff()
print("=== [협업 에이전트] 생성된 부산 3일 일정 ===")
print(result_multi)

crew_multi.kickoff()를 호출하면 먼저 정보 조사자 에이전트가 research_task를 수행합니다. 이 과정에서 에이전트는 내부적으로 필요한 정보를 검색하기 위해 우리가 장착한 DuckDuckGo Search Tool을 사용할 것입니다. (예: 부산 관광지, 맛집 등을 검색하고 요약 정리). 그 결과가 나오면, 일정 기획자 에이전트가 planning_task를 수행하며, 첫 번째 결과를 컨텍스트로 활용해 최종 일정을 작성합니다. result_multi에는 최종 생성된 일정이 반환되며 이를 출력합니다.

실행 방법

  1. 터미널에서 해당 파일 디렉토리로 이동합니다.
  2. 다음 명령어를 실행하세요:
    python 03-2.travel_planner.py
    
  3. 실행 과정에서 정보 조사자 에이전트가 웹 검색을 수행하므로, 콘솔에 검색 키워드나 중간 결과 등이 verbose=True로 인해 출력될 수 있습니다. 이어서 일정 기획자의 결과가 나오며, 최종적으로 부산 3일 여행 일정이 완성됩니다.

예상 실행 결과

이번에는 두 단계의 출력이 이뤄집니다. 첫 번째 에이전트의 조사 결과와 두 번째 에이전트의 최종 일정인데, 코드에서는 최종 일정(planning_task의 결과)만 print하고 있습니다. 그러나 verbose=True 설정으로 인해 실행 중간에 검색 과정 로그나 1차 조사 내용이 나타날 수 있습니다.

최종 출력되는 일정은 03-1 버전과 유사한 3일치 여행 일정이지만, 내용 면에서 더 최신 정보나 구체적인 장소 이름이 반영되어 있을 것입니다. 예를 들어, 정보 조사 결과에 따라 실제 부산의 최신 인기 카페나 새로운 관광지가 언급될 수 있고, 일정에 그 내용이 반영됩니다. 또한 각 장소에 대한 간단한 설명이나 팁도 포함되어 한층 풍부한 일정표가 될 것입니다.

예상 예시: Day 1에 해운대 해수욕장 방문이 포함되면서 "해운대 해수욕장은 부산의 대표 해변으로, 아침 산책을 하기에 좋습니다."와 같은 설명이 붙고, 맛집으로 최근 현지인들에게 인기있는 식당 이름이 언급될 수 있습니다. 이러한 디테일은 첫 번째 에이전트의 조사에 달려 있으며, 두 번째 에이전트는 그 정보를 활용하게 됩니다.

비교: 03-1의 결과와 03-2의 결과를 비교해 보면, 03-2 (협업 에이전트 버전)가 보다 실제 정보에 기반한 일정을 제시할 가능성이 높습니다. 즉, 단일 에이전트가 자체 지식으로 만든 일정보다, 하나의 에이전트가 정보를 찾아주고 다른 하나가 일정을 짜는 협업 방식이 더 신뢰도 높은 세부사항을 제공하게 됩니다.


03-3.travel_planner.py : 개선된 프롬프트로 일정 품질 향상

시나리오: 두 에이전트 협업 구조는 03-2와 동일하지만, 프롬프트를 개선하여 더 현실적이고 상세한 일정을 만들어 봅니다. 특히 예산과 교통 수단 등의 제약 조건을 프롬프트에 추가로 명시하여, 에이전트가 이를 고려한 계획을 세우도록 유도합니다.

코드 설명

이 코드의 구조는 03-2와 거의 같으며, 에이전트 정의와 1차 정보 조사 Task는 동일합니다. 달라진 점은 두 번째 Task의 description (프롬프트) 부분입니다. 즉, 일정 작성 Task에 추가 지침을 줌으로써 결과의 질을 높이려는 것입니다.

개선된 일정 작성 Task 정의: improved_planning_task의 description에는 이전과 동일한 내용에 더하여 여행 예산과 대중교통 이용에 대한 조건이 포함됩니다. 구체적으로 추가/변경된 요구사항은 다음과 같습니다:

  • 예산 제한: "가능하면 예산은 하루 10만원 내외로 맞추고" – 하루 예산을 약 10만원 정도로 고려하라는 지시입니다. 이를 통해 에이전트는 지나치게 비싼 활동을 지양하고, 비용 정보를 염두에 둘 것입니다.
  • 교통 수단: "이동은 모두 대중교통을 이용" – 택시나 렌터카 대신 버스, 지하철 등 대중교통으로 다니도록 계획하게 합니다.
  • 교통 경로 제안: "버스정류장 및 지하철역을 포함한 대중교통 경로를 제안해 주세요." – 이동 시 어떤 버스나 지하철을 탈지, 어디서 승차/하차하는지 등의 구체적인 경로를 제시하도록 합니다.
  • 이동 소요 시간: "버스 및 지하철을 이용할 때의 소요 시간도 포함해 주세요." – 각 이동 구간에 걸리는 시간까지 언급해주면 일정 계획에 현실감을 더할 수 있습니다.
  • 결과 언어 명시: "결과는 한국어로 작성해 주세요." – 혹시 모를 영문 출력 등을 방지하고, 결과를 반드시 한국어로 작성하도록 명시했습니다 (현재 프롬프트 자체가 한국어이므로 출력도 한국어일 가능성이 높지만, 요구사항을 분명히 하는 차원).

아래는 개선된 두 번째 Task 정의 부분입니다:

# 개선된 일정 작성 Task 정의 (예산 및 교통 고려 추가)
improved_planning_task = Task(
    description=(
        "위의 조사 결과를 참고하여 부산에서 3일 동안 머무는 여행 일정을 작성해 주세요.\n"
        "각 날짜별로 오전/오후/저녁 계획을 세우고, 조사된 관광지와 맛집 정보를 일정에 반영하세요.\n"
        "가능하면 **예산은 하루 10만원 내외로 맞추고, 이동은 모두 대중교통**을 이용하는 것으로 고려하세요.\n"
        "버스정류장 및 지하철역을 포함한 대중교통 경로를 제안해 주세요.\n"
        "버스 및 지하철을 이용할 때의 소요 시간도 포함해 주세요.\n"
        "일정에는 방문지에 대한 간단한 설명이나 여행 팁도 포함해 주세요. 결과는 한국어로 작성해 주세요.\n"
    ),
    agent=planner_agent,
    context=[research_task],
    expected_output="예산과 교통을 고려한 3일간의 여행 일정"
)

위 코드에서 볼 수 있듯이, 粗체로 강조된 부분(예산 10만원, 대중교통 이용)이 새로 추가되었습니다. 이러한 세부 지침으로 인해 에이전트는 일정을 세울 때 비용과 교통을 신경 쓰게 됩니다. (프롬프트 문자열 내에 **...**로 감싼 부분은 마크다운 문법으로 강조를 의미하며, 모델에 해당 부분을 강조하여 인식시키기 위한 기법입니다.)

나머지 구성은 03-2와 동일합니다. 동일한 research_task를 사용하고, 에이전트들도 동일합니다. Crew 설정 시 이번에는 tasks=[research_task, improved_planning_task]로 두 번째 태스크만 바뀐 채 추가됩니다. 실행 순서는 여전히 sequential입니다.

crew_multi_improved = Crew(
    agents=[research_agent, planner_agent],
    tasks=[research_task, improved_planning_task],
    process=Process.sequential,
    verbose=True
)
print("\n=== [협업 에이전트] 개선된 프롬프트로 일정 생성 ===")
result_multi_improved = crew_multi_improved.kickoff()
print("=== [협업 에이전트] 개선된 일정 결과 ===")
print(result_multi_improved)

실행 방법

이전과 마찬가지로 터미널에서 다음 명령을 실행합니다:

python 03-3.travel_planner.py

실행 과정 역시 03-2와 유사하게 진행되지만, 두 번째 에이전트의 프롬프트가 강화되었으므로 출력까지 약간 더 시간이 걸릴 수 있습니다 (LLM이 더 많은 내용을 생성할 수 있으므로).

예상 실행 결과

출력되는 부산 3일 여행 일정은 이전보다 더 현실적이고 상세한 정보를 담고 있을 것입니다. 특히, 각 이동 단계에 대중교통 경로와 시간, 그리고 비용 측면이 언급될 것으로 기대됩니다. 예를 들어 일정의 일부는 다음과 같을 수 있습니다:

Day 2:
- **오전:** 감천문화마을 투어 (지하철 1호선 토성역 하차, 7번 출구에서 마을 버스 2번 이용, 약 15분 소요). 알록달록한 벽화를 감상하며 산책.
- **오후:** 자갈치 시장 방문 및 점심 (토성역에서 1호선 이용, 자갈치역 하차, 도보 5분). 신선한 회 시식 예산 약 2만원. 
- **저녁:** 광안리 해변에서 야경 감상 (자갈치에서 버스 41번 탑승 후 광안리해변 정류장 하차, 약 30분 소요). 해변 근처 식당에서 돼지국밥으로 저녁 (~8천원).

위는 예상 예시로, 실제 결과와 다를 수 있지만 형식은 유사할 것입니다. 개선된 프롬프트 덕분에 일정마다:

  • 교통: (어느 역에서 몇 번 버스를 타고, 몇 분 걸리는지) 같은 내용이 포함되고,
  • 예산: (식사에 얼마 정도 비용이 드는지) 등의 언급이 추가됩니다.

또한 모든 출력은 한국어로 명시적으로 요구했으므로 한글로 제공될 것이 확실해졌습니다. 전체적으로 사용자는 보다 구체적이고 실행 가능한 여행 일정을 얻게 됩니다.


정리 및 팁

이상으로, CrewAI를 활용한 Agent 및 Task 설계, 그리고 프롬프트 작성 실습을 완료했습니다. 이번 실습에서 배운 주요 사항을 정리하면:

  • Agent 정의: 역할, 목표, 배경을 명확히 설정함으로써 에이전트의 행동 방향을 결정할 수 있습니다. 필요한 경우 도구를 부여하여 정보 검색이나 계산 등의 능력을 확장할 수 있습니다.
  • Task 정의: 프롬프트(설명)를 구체적으로 작성하고, 어떤 출력물을 기대하는지 expected_output으로 표현해 두면 좋습니다. 여러 Task가 있을 때 이전 Task를 context로 넘겨줄 수 있어, 태스크 간에 정보 공유가 가능합니다.
  • Crew 활용: Crew 객체로 에이전트들과 태스크들을 엮어 일괄 실행할 수 있습니다. Process.sequential을 사용하면 지정된 순서대로 태스크를 실행하고, 각 단계의 결과를 다음 단계에 전달할 수 있습니다.
  • 프롬프트 개선: 출력 결과를 향상시키기 위해서는 프롬프트에 명확한 요구사항과 제약을 추가하는 것이 효과적입니다. 요구사항이 구체적일수록 에이전트(LLM)는 더 관련성 높은 세부정보를 포함한 답변을 생성합니다. 다만 과도하게 제한하면 창의성이 떨어질 수 있으므로 균형을 잡는 것이 중요합니다.

이 실습을 통해 간단한 여행 일정 플래너를 만들어보았지만, 동일한 개념을 활용하면 다양한 도메인에 에이전트와 태스크를 설계하여 복잡한 문제를 해결할 수 있습니다. CrewAI를 활용한 에이전트 기반 시스템 설계에 익숙해졌기를 바랍니다. 즐거운 여행 플래닝 실습이었길 바랍니다!