크루(Crew)란 무엇인가?

크루(Crew)는 crewAI에서 여러 에이전트가 협력하여 일련의 작업을 수행하는 협업 그룹을 의미한다. 각 크루는 작업 실행 전략, 에이전트 간 협업 방식, 그리고 전체 워크플로우를 정의한다.

크루 속성

속성매개변수설명
Taskstasks크루에 할당된 작업 목록
Agentsagents크루에 속한 에이전트 목록
Process (선택 사항)process크루가 따르는 프로세스 흐름 (예: 순차적, 계층적). 기본값은 sequential.
Verbose (선택 사항)verbose실행 중 로깅을 위한 상세 정보 수준. 기본값은 False.
Manager LLM (선택 사항)manager_llm계층적 프로세스에서 관리자 에이전트가 사용하는 언어 모델. 계층적 프로세스 사용 시 필수.
Function Calling LLM (선택 사항)function_calling_llm이 값을 전달하면 크루는 모든 에이전트의 도구에 대해 함수 호출을 수행할 때 이 LLM을 사용한다. 각 에이전트는 자체 LLM을 가질 수 있으며, 이는 크루의 LLM을 재정의한다.
Config (선택 사항)config크루를 위한 선택적 구성 설정. Json 또는 Dict[str, Any] 형식.
Max RPM (선택 사항)max_rpm실행 중 크루가 준수하는 최대 분당 요청 수. 기본값은 None.
Language (선택 사항)language크루에서 사용할 언어. 기본값은 영어.
Language File (선택 사항)language_file크루에서 사용할 언어 파일의 경로.
Memory (선택 사항)memory실행 메모리(단기, 장기, 엔티티 메모리)를 저장하는 데 사용.
Memory Config (선택 사항)memory_config크루가 사용할 메모리 프로바이더의 구성.
Cache (선택 사항)cache도구 실행 결과를 캐시에 저장할지 여부를 지정. 기본값은 True.
Embedder (선택 사항)embedder크루가 사용할 임베더의 구성. 현재는 주로 메모리에서 사용. 기본값은 {"provider": "openai"}.
Full Output (선택 사항)full_output크루가 모든 작업의 출력을 포함한 전체 출력을 반환할지, 아니면 최종 출력만 반환할지 여부. 기본값은 False.
Step Callback (선택 사항)step_callback각 에이전트의 각 단계 후에 호출되는 함수. 에이전트의 작업을 기록하거나 다른 작업을 수행하는 데 사용할 수 있으며, 에이전트별 step_callback을 재정의하지 않는다.
Task Callback (선택 사항)task_callback각 작업 완료 후 호출되는 함수. 작업 실행 후 모니터링 또는 추가 작업에 유용.
Share Crew (선택 사항)share_crew크루 정보와 실행 결과를 crewAI 팀과 공유하여 라이브러리를 개선하고 모델을 훈련할 수 있도록 할지 여부.
Output Log File (선택 사항)output_log_file로그를 현재 디렉토리에 logs.txt로 저장하거나 파일 경로를 제공. 파일 이름이 .json으로 끝나면 JSON 형식, 그렇지 않으면 .txt 형식으로 저장. 기본값은 None.
Manager Agent (선택 사항)manager_agentmanager는 관리자로 사용할 커스텀 에이전트를 설정한다.
Prompt File (선택 사항)prompt_file크루에서 사용할 프롬프트 JSON 파일의 경로.
Planning (선택 사항)planning크루에 계획 능력을 추가. 활성화하면 각 크루 반복 전에 모든 크루 데이터가 AgentPlanner로 전송되어 작업을 계획하고, 이 계획이 각 작업 설명에 추가된다.
Planning LLM (선택 사항)planning_llm계획 프로세스에서 AgentPlanner가 사용하는 언어 모델.

Crew Max RPM: max_rpm 속성은 크루가 분당 수행할 수 있는 최대 요청 수를 설정하여 속도 제한을 피한다. 이 값을 설정하면 개별 에이전트의 max_rpm 설정을 재정의한다.

크루 생성하기

CrewAI에서 크루를 생성하는 방법은 두 가지가 있다: YAML 설정 파일 사용(권장) 또는 코드에서 직접 정의하는 방법이다.

YAML 설정 (권장)

YAML 설정을 사용하면 크루를 정의하는 더 깔끔하고 유지보수하기 쉬운 방법을 제공하며, CrewAI 프로젝트에서 에이전트와 태스크를 정의하는 방식과 일관성을 유지한다.

설치 섹션에서 설명한 대로 CrewAI 프로젝트를 생성한 후, CrewBase를 상속받는 클래스에서 크루를 정의하고 데코레이터를 사용해 에이전트, 태스크, 그리고 크루 자체를 정의할 수 있다.

데코레이터를 활용한 Crew 클래스 예제

from crewai import Agent, Crew, Task, Process
from crewai.project import CrewBase, agent, task, crew, before_kickoff, after_kickoff


@CrewBase
class YourCrewName:
    """여러분의 크루에 대한 설명"""

    # YAML 설정 파일 경로
    # YAML로 정의된 에이전트와 태스크 예제는 다음 링크를 참고하세요:
    # - 태스크: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended
    # - 에이전트: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended
    agents_config = 'config/agents.yaml' 
    tasks_config = 'config/tasks.yaml' 

    @before_kickoff
    def prepare_inputs(self, inputs):
        # 크루 시작 전 입력값 수정
        inputs['additional_data'] = "추가 정보"
        return inputs

    @after_kickoff
    def process_output(self, output):
        # 크루 완료 후 출력값 처리
        output.raw += "\n크루 완료 후 처리됨."
        return output

    @agent
    def agent_one(self) -> Agent:
        return Agent(
            config=self.agents_config['agent_one'],
            verbose=True
        )

    @agent
    def agent_two(self) -> Agent:
        return Agent(
            config=self.agents_config['agent_two'],
            verbose=True
        )

    @task
    def task_one(self) -> Task:
        return Task(
            config=self.tasks_config['task_one']
        )

    @task
    def task_two(self) -> Task:
        return Task(
            config=self.tasks_config['task_two']
        )

    @crew
    def crew(self) -> Crew:
        return Crew(
            agents=self.agents,  # @agent 데코레이터로 자동 수집
            tasks=self.tasks,    # @task 데코레이터로 자동 수집
            process=Process.sequential,
            verbose=True,
        )

태스크는 정의된 순서대로 실행된다.

CrewBase 클래스와 이 데코레이터들은 에이전트와 태스크를 자동으로 수집해 관리 작업을 줄여준다.

annotations.py의 데코레이터 개요

CrewAI는 annotations.py 파일에 여러 데코레이터를 제공한다. 이 데코레이터들은 여러분의 crew 클래스 내부의 메서드에 특별한 처리를 위해 사용된다:

  • @CrewBase: 클래스를 crew 베이스 클래스로 표시한다.
  • @agent: Agent 객체를 반환하는 메서드를 나타낸다.
  • @task: Task 객체를 반환하는 메서드를 나타낸다.
  • @crew: Crew 객체를 반환하는 메서드를 나타낸다.
  • @before_kickoff: (선택 사항) crew가 시작되기 전에 실행될 메서드를 표시한다.
  • @after_kickoff: (선택 사항) crew가 종료된 후에 실행될 메서드를 표시한다.

이 데코레이터들은 crew의 구조를 조직화하고, 에이전트와 작업을 수동으로 나열하지 않고도 자동으로 수집하는 데 도움을 준다.

직접 코드로 정의하기 (대안)

YAML 설정 파일을 사용하지 않고 코드 내에서 직접 크루를 정의할 수도 있다.

from crewai import Agent, Crew, Task, Process
from crewai_tools import YourCustomTool

class YourCrewName:
    def agent_one(self) -> Agent:
        return Agent(
            role="데이터 분석가",
            goal="시장 내 데이터 트렌드 분석",
            backstory="경제학 배경을 가진 경험 많은 데이터 분석가",
            verbose=True,
            tools=[YourCustomTool()]
        )

    def agent_two(self) -> Agent:
        return Agent(
            role="시장 조사원",
            goal="시장 동향에 대한 정보 수집",
            backstory="세부 사항에 민감한 성실한 연구원",
            verbose=True
        )

    def task_one(self) -> Task:
        return Task(
            description="최근 시장 데이터를 수집하고 트렌드를 파악한다.",
            expected_output="시장의 주요 트렌드를 요약한 보고서",
            agent=self.agent_one()
        )

    def task_two(self) -> Task:
        return Task(
            description="시장 동향에 영향을 미치는 요인을 조사한다.",
            expected_output="시장에 영향을 미치는 요인 분석",
            agent=self.agent_two()
        )

    def crew(self) -> Crew:
        return Crew(
            agents=[self.agent_one(), self.agent_two()],
            tasks=[self.task_one(), self.task_two()],
            process=Process.sequential,
            verbose=True
        )

이 예시에서:

  • 에이전트와 태스크를 데코레이터 없이 클래스 내에서 직접 정의한다.
  • 에이전트와 태스크 리스트를 수동으로 생성하고 관리한다.
  • 이 방식은 더 많은 제어권을 제공하지만, 대규모 프로젝트에서는 유지보수가 어려울 수 있다.

CrewAI 프레임워크의 Crew Output

CrewAI 프레임워크에서 크루의 출력은 CrewOutput 클래스로 캡슐화된다. 이 클래스는 크루 실행 결과에 접근할 수 있는 구조화된 방식을 제공하며, 원시 문자열, JSON, Pydantic 모델 등 다양한 형식의 결과를 포함한다. CrewOutput은 최종 작업의 출력 결과, 토큰 사용량, 그리고 각 작업의 개별 출력 결과를 담고 있다.

크루 출력 속성

속성매개변수타입설명
원본 출력rawstr크루의 원본 출력. 이는 기본 출력 형식이다.
PydanticpydanticOptional[BaseModel]크루의 구조화된 출력을 나타내는 Pydantic 모델 객체.
JSON 딕셔너리json_dictOptional[Dict[str, Any]]크루의 JSON 출력을 나타내는 딕셔너리.
태스크 출력tasks_outputList[TaskOutput]크루 내 각 태스크의 출력을 나타내는 TaskOutput 객체의 리스트.
토큰 사용량token_usageDict[str, Any]실행 중 언어 모델의 성능을 보여주는 토큰 사용량 요약.

Crew 출력 메서드와 속성

메서드/속성설명
json출력 형식이 JSON일 경우, JSON 문자열 표현을 반환한다.
to_dictJSON과 Pydantic 출력을 딕셔너리로 변환한다.
**str**Crew 출력의 문자열 표현을 반환하며, Pydantic을 우선시하고, 그다음 JSON, 마지막으로 원시 데이터를 반환한다.

크루 실행 결과 접근하기

크루를 실행한 후, 그 결과는 Crew 객체의 output 속성을 통해 접근할 수 있다. CrewOutput 클래스는 이 결과를 다양한 방식으로 상호작용하고 표시하는 방법을 제공한다.

예제

# 크루 실행 예제
crew = Crew(
    agents=[research_agent, writer_agent],
    tasks=[research_task, write_article_task],
    verbose=True
)

crew_output = crew.kickoff()

# 크루 출력에 접근
print(f"원본 출력: {crew_output.raw}")
if crew_output.json_dict:
    print(f"JSON 출력: {json.dumps(crew_output.json_dict, indent=2)}")
if crew_output.pydantic:
    print(f"Pydantic 출력: {crew_output.pydantic}")
print(f"작업 출력: {crew_output.tasks_output}")
print(f"토큰 사용량: {crew_output.token_usage}")

크루 실행 로그 접근

output_log_fileTrue(불리언) 또는 file_name(문자열)로 설정하면 크루 실행 로그를 실시간으로 확인할 수 있다. 이벤트 로그는 file_name.txtfile_name.json 두 가지 형식으로 저장된다.

True(불리언)로 설정하면 logs.txt 파일로 저장된다.

output_log_fileFalse(불리언) 또는 None으로 설정되면 로그가 저장되지 않는다.

# 크루 로그 저장
crew = Crew(output_log_file = True)  # 로그가 logs.txt로 저장됨
crew = Crew(output_log_file = file_name)  # 로그가 file_name.txt로 저장됨
crew = Crew(output_log_file = file_name.txt)  # 로그가 file_name.txt로 저장됨
crew = Crew(output_log_file = file_name.json)  # 로그가 file_name.json로 저장됨

메모리 활용

크루는 단기, 장기, 엔티티 메모리를 활용해 시간이 지남에 따라 실행과 학습을 개선할 수 있다. 이 기능을 통해 크루는 실행 메모리를 저장하고 불러올 수 있어 의사결정과 작업 실행 전략에 도움을 준다.

캐시 활용

캐시는 도구 실행 결과를 저장하는 데 사용할 수 있다. 이를 통해 동일한 작업을 다시 실행할 필요가 줄어들어 전체 프로세스의 효율성을 높일 수 있다.

크루 사용 메트릭

크루 실행이 완료되면, usage_metrics 속성을 통해 모든 작업에서 사용된 언어 모델(LLM)의 사용 메트릭을 확인할 수 있다. 이를 통해 운영 효율성과 개선이 필요한 부분을 파악할 수 있다.

# 크루의 사용 메트릭에 접근
crew = Crew(agents=[agent1, agent2], tasks=[task1, task2])
crew.kickoff()
print(crew.usage_metrics)

크루 실행 프로세스

  • 순차적 프로세스: 작업을 하나씩 순서대로 실행하여 선형적인 작업 흐름을 유지한다.
  • 계층적 프로세스: 매니저 에이전트가 크루를 조율하고 작업을 위임한 후 결과를 검증한다. 참고: 이 프로세스에는 manager_llm 또는 manager_agent가 필요하며, 프로세스 흐름을 검증하는 데 필수적이다.

크루 작업 시작하기

크루가 구성되면 kickoff() 메서드를 사용해 워크플로우를 시작한다. 이 메서드는 정의된 프로세스 흐름에 따라 작업 실행을 시작한다.

# 크루의 작업 실행 시작
result = my_crew.kickoff()
print(result)

크루 작업 시작 방법

크루를 구성한 후, 적절한 방법으로 작업 흐름을 시작한다. CrewAI는 작업 시작 과정을 더 잘 제어할 수 있도록 여러 메서드를 제공한다: kickoff(), kickoff_for_each(), kickoff_async(), kickoff_for_each_async().

  • kickoff(): 정의된 프로세스 흐름에 따라 실행을 시작한다.
  • kickoff_for_each(): 제공된 입력 이벤트나 컬렉션의 각 항목에 대해 순차적으로 작업을 실행한다.
  • kickoff_async(): 비동기적으로 작업 흐름을 시작한다.
  • kickoff_for_each_async(): 제공된 입력 이벤트나 컬렉션의 각 항목에 대해 비동기 처리를 활용해 동시에 작업을 실행한다.
# 크루의 작업 실행 시작
result = my_crew.kickoff()
print(result)

# kickoff_for_each 사용 예제
inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}]
results = my_crew.kickoff_for_each(inputs=inputs_array)
for result in results:
    print(result)

# kickoff_async 사용 예제
inputs = {'topic': 'AI in healthcare'}
async_result = my_crew.kickoff_async(inputs=inputs)
print(async_result)

# kickoff_for_each_async 사용 예제
inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}]
async_results = my_crew.kickoff_for_each_async(inputs=inputs_array)
for async_result in async_results:
    print(async_result)

이 메서드들은 동기 및 비동기 작업 흐름을 필요에 맞게 관리하고 실행할 수 있는 유연성을 제공한다.

특정 작업부터 재실행하기

이제 CLI 커맨드 replay를 사용해 특정 작업부터 재실행할 수 있다.

CrewAI의 재실행 기능은 커맨드라인 인터페이스(CLI)를 통해 특정 작업부터 재실행할 수 있게 해준다. crewai replay -t <task_id> 커맨드를 실행하면 재실행할 task_id를 지정할 수 있다.

Kickoffs는 이제 최신 kickoffs에서 반환된 작업 결과를 로컬에 저장하여 재실행할 수 있도록 한다.

특정 작업부터 다시 실행하기 (CLI 사용)

다시 실행 기능을 사용하려면 다음 단계를 따르면 된다.

  1. 터미널이나 커맨드라인을 연다.
  2. CrewAI 프로젝트가 있는 디렉토리로 이동한다.
  3. 다음 명령어를 실행한다:

가장 최근의 킥오프 작업 ID를 확인하려면:

crewai log-tasks-outputs

그리고 특정 작업부터 다시 실행하려면:

crewai replay -t <task_id>

이 명령어들은 가장 최근의 킥오프 작업부터 다시 실행할 수 있게 해주며, 이전에 실행한 작업의 컨텍스트도 유지된다.