지식이란 무엇인가?

CrewAI에서 지식은 AI 에이전트가 작업을 수행하는 동안 외부 정보 소스에 접근하고 활용할 수 있게 해주는 강력한 시스템이다. 여러분의 에이전트에게 작업 중 참고할 수 있는 도서관을 제공한다고 생각하면 된다.

지식을 사용할 때의 주요 이점:

  • 도메인별 정보로 에이전트의 능력을 강화
  • 실제 데이터를 기반으로 의사결정 지원
  • 대화 간 컨텍스트 유지
  • 사실에 기반한 응답 제공

지원되는 지식 소스

CrewAI는 다양한 유형의 지식 소스를 기본적으로 지원한다:

텍스트 소스

  • 원시 문자열
  • 텍스트 파일 (.txt)
  • PDF 문서

구조화된 데이터

  • CSV 파일
  • Excel 스프레드시트
  • JSON 문서

지원되는 지식 파라미터

파라미터타입필수 여부설명
sourcesList[BaseKnowledgeSource]저장되고 쿼리될 콘텐츠를 제공하는 지식 소스 목록. PDF, CSV, Excel, JSON, 텍스트 파일 또는 문자열 콘텐츠를 포함할 수 있다.
collection_namestr아니오지식이 저장될 컬렉션의 이름. 서로 다른 지식 집합을 식별하는 데 사용된다. 제공되지 않으면 기본값으로 “knowledge”가 사용된다.
storageOptional[KnowledgeStorage]아니오지식이 저장되고 검색되는 방식을 관리하는 커스텀 스토리지 설정. 제공되지 않으면 기본 스토리지가 생성된다.

빠른 시작 예제

파일 기반 지식 소스를 사용할 때는 프로젝트 루트에 knowledge 디렉토리를 만들고, 파일을 해당 디렉토리에 배치한다. 또한, 소스를 생성할 때 knowledge 디렉토리를 기준으로 상대 경로를 사용한다.

다음은 문자열 기반 지식을 사용한 예제다:

from crewai import Agent, Task, Crew, Process, LLM
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource

# 지식 소스 생성
content = "Users name is John. He is 30 years old and lives in San Francisco."
string_source = StringKnowledgeSource(
    content=content,
)

# 결정적 출력을 위해 temperature를 0으로 설정한 LLM 생성
llm = LLM(model="gpt-4o-mini", temperature=0)

# 지식 저장소를 가진 에이전트 생성
agent = Agent(
    role="About User",
    goal="You know everything about the user.",
    backstory="""You are a master at understanding people and their preferences.""",
    verbose=True,
    allow_delegation=False,
    llm=llm,
)
task = Task(
    description="Answer the following questions about the user: {question}",
    expected_output="An answer to the question.",
    agent=agent,
)

crew = Crew(
    agents=[agent],
    tasks=[task],
    verbose=True,
    process=Process.sequential,
    knowledge_sources=[string_source], # 지식 소스를 추가해 지식을 활성화한다. 소스 목록에 더 많은 소스를 추가할 수도 있다.
)

result = crew.kickoff(inputs={"question": "What city does John live in and how old is he?"})

다음은 CrewDoclingSource를 사용한 예제다. CrewDoclingSource는 MD, PDF, DOCX, HTML 등 다양한 파일 포맷을 처리할 수 있다.

다음 예제를 실행하려면 docling을 설치해야 한다: uv add docling

from crewai import LLM, Agent, Crew, Process, Task
from crewai.knowledge.source.crew_docling_source import CrewDoclingSource

# 지식 소스 생성
content_source = CrewDoclingSource(
    file_paths=[
        "https://lilianweng.github.io/posts/2024-11-28-reward-hacking",
        "https://lilianweng.github.io/posts/2024-07-07-hallucination",
    ],
)

# 결정적 출력을 위해 temperature를 0으로 설정한 LLM 생성
llm = LLM(model="gpt-4o-mini", temperature=0)

# 지식 저장소를 가진 에이전트 생성
agent = Agent(
    role="About papers",
    goal="You know everything about the papers.",
    backstory="""You are a master at understanding papers and their content.""",
    verbose=True,
    allow_delegation=False,
    llm=llm,
)
task = Task(
    description="Answer the following questions about the papers: {question}",
    expected_output="An answer to the question.",
    agent=agent,
)

crew = Crew(
    agents=[agent],
    tasks=[task],
    verbose=True,
    process=Process.sequential,
    knowledge_sources=[
        content_source
    ],  # 지식 소스를 추가해 지식을 활성화한다. 소스 목록에 더 많은 소스를 추가할 수도 있다.
)

result = crew.kickoff(
    inputs={
        "question": "What is the reward hacking paper about? Be sure to provide sources."
    }
)

다양한 예제

다양한 지식 소스를 활용하는 방법에 대한 예제를 소개한다:

텍스트 파일 지식 소스

from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource

# 텍스트 파일 지식 소스 생성
text_source = TextFileKnowledgeSource(
    file_paths=["document.txt", "another.txt"]
)

# 에이전트 또는 크루 레벨에 텍스트 파일 소스 추가
agent = Agent(
    ...
    knowledge_sources=[text_source]
)

crew = Crew(
    ...
    knowledge_sources=[text_source]
)

PDF 지식 소스

from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource

# PDF 지식 소스 생성
pdf_source = PDFKnowledgeSource(
    file_paths=["document.pdf", "another.pdf"]
)

# 에이전트 또는 크루 레벨에 PDF 지식 소스 추가
agent = Agent(
    ...
    knowledge_sources=[pdf_source]
)

crew = Crew(
    ...
    knowledge_sources=[pdf_source]
)

CSV 지식 소스

from crewai.knowledge.source.csv_knowledge_source import CSVKnowledgeSource

# CSV 지식 소스 생성
csv_source = CSVKnowledgeSource(
    file_paths=["data.csv"]
)

# 에이전트 또는 크루에 CSV 지식 소스 추가
agent = Agent(
    ...
    knowledge_sources=[csv_source]
)

crew = Crew(
    ...
    knowledge_sources=[csv_source]
)

엑셀 지식 소스

from crewai.knowledge.source.excel_knowledge_source import ExcelKnowledgeSource

# 엑셀 지식 소스 생성
excel_source = ExcelKnowledgeSource(
    file_paths=["spreadsheet.xlsx"]
)

# 에이전트나 크루 수준에서 엑셀 지식 소스 활용
agent = Agent(
    ...
    knowledge_sources=[excel_source]
)

crew = Crew(
    ...
    knowledge_sources=[excel_source]
)

JSON 지식 소스

from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource

# JSON 지식 소스 생성
json_source = JSONKnowledgeSource(
    file_paths=["data.json"]
)

# 에이전트 또는 크루 레벨에 JSON 지식 소스 추가
agent = Agent(
    ...
    knowledge_sources=[json_source]
)

crew = Crew(
    ...
    knowledge_sources=[json_source]
)

지식 구성

청킹 설정

지식 소스는 더 나은 처리를 위해 콘텐츠를 자동으로 청크로 나눈다. 지식 소스에서 청킹 동작을 다음과 같이 설정할 수 있다:

from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource

source = StringKnowledgeSource(
    content="여기에 콘텐츠를 입력",
    chunk_size=4000,      # 각 청크의 최대 크기 (기본값: 4000)
    chunk_overlap=200     # 청크 간 겹치는 부분 (기본값: 200)
)

청킹 설정은 다음에 도움을 준다:

  • 대규모 문서를 관리 가능한 크기로 분할
  • 청크 간 겹치는 부분을 통해 컨텍스트 유지
  • 검색 정확도 최적화

임베딩 설정

지식 저장소를 위한 임베딩 설정도 가능하다. 에이전트와는 다른 임베딩 모델을 지식 저장소에 사용하고 싶을 때 유용하다. embedder 파라미터는 다양한 임베딩 모델 프로바이더를 지원한다:

  • openai: OpenAI의 임베딩 모델
  • google: Google의 텍스트 임베딩 모델
  • azure: Azure OpenAI 임베딩
  • ollama: Ollama를 사용한 로컬 임베딩
  • vertexai: Google Cloud VertexAI 임베딩
  • cohere: Cohere의 임베딩 모델
  • voyageai: VoyageAI의 임베딩 모델
  • bedrock: AWS Bedrock 임베딩
  • huggingface: Hugging Face 모델
  • watson: IBM Watson 임베딩

Google의 text-embedding-004 모델을 사용해 지식 저장소의 임베딩을 설정하는 예제는 다음과 같다:

from crewai import Agent, Task, Crew, Process, LLM
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource
import os

# GEMINI API 키 가져오기
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")

# 지식 소스 생성
content = "Users name is John. He is 30 years old and lives in San Francisco."
string_source = StringKnowledgeSource(
    content=content,
)

# 결정적 출력을 위해 온도를 0으로 설정한 LLM 생성
gemini_llm = LLM(
    model="gemini/gemini-1.5-pro-002",
    api_key=GEMINI_API_KEY,
    temperature=0,
)

# 지식 저장소를 가진 에이전트 생성
agent = Agent(
    role="About User",
    goal="You know everything about the user.",
    backstory="""You are a master at understanding people and their preferences.""",
    verbose=True,
    allow_delegation=False,
    llm=gemini_llm,
    embedder={
        "provider": "google",
        "config": {
            "model": "models/text-embedding-004",
            "api_key": GEMINI_API_KEY,
        }
    }
)

task = Task(
    description="Answer the following questions about the user: {question}",
    expected_output="An answer to the question.",
    agent=agent,
)

crew = Crew(
    agents=[agent],
    tasks=[task],
    verbose=True,
    process=Process.sequential,
    knowledge_sources=[string_source],
    embedder={
        "provider": "google",
        "config": {
            "model": "models/text-embedding-004",
            "api_key": GEMINI_API_KEY,
        }
    }
)

result = crew.kickoff(inputs={"question": "What city does John live in and how old is he?"})

지식 초기화

CrewAI에 저장된 지식을 초기화해야 한다면 crewai reset-memories 커맨드에 --knowledge 옵션을 사용한다.

Command
crewai reset-memories --knowledge

이 명령은 지식 소스를 업데이트한 후 에이전트가 최신 정보를 사용하도록 보장할 때 유용하다.

에이전트별 지식

crew.knowledge_sources를 사용해 크루 전체에 지식을 제공할 수 있지만, 개별 에이전트도 knowledge_sources 매개변수를 통해 자신만의 지식 소스를 가질 수 있다.

from crewai import Agent, Task, Crew
from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource

# 제품에 대한 에이전트별 지식 생성
product_specs = StringKnowledgeSource(
    content="""XPS 13 노트북 사양:
    - 13.4인치 4K 디스플레이
    - Intel Core i7 프로세서
    - 16GB RAM
    - 512GB SSD 저장 공간
    - 12시간 배터리 지속 시간""",
    metadata={"category": "product_specs"}
)

# 제품 지식을 가진 지원 에이전트 생성
support_agent = Agent(
    role="기술 지원 전문가",
    goal="정확한 제품 정보와 지원 제공.",
    backstory="노트북 제품과 사양에 대한 전문가입니다.",
    knowledge_sources=[product_specs]  # 에이전트별 지식
)

# 제품 지식이 필요한 태스크 생성
support_task = Task(
    description="고객 질문에 답변하세요: {question}",
    agent=support_agent
)

# 크루 생성 및 실행
crew = Crew(
    agents=[support_agent],
    tasks=[support_task]
)

# 노트북 사양에 대한 답변 얻기
result = crew.kickoff(
    inputs={"question": "XPS 13의 저장 용량은 얼마인가요?"}
)

에이전트별 지식의 장점:

  • 에이전트에게 역할에 맞는 특화된 정보 제공
  • 에이전트 간 관심사 분리 유지
  • 크루 레벨 지식과 결합해 계층적 정보 접근 가능

커스텀 지식 소스 생성

CrewAI는 BaseKnowledgeSource 클래스를 확장하여 다양한 타입의 데이터에 대한 커스텀 지식 소스를 생성할 수 있다. 여기서는 우주 뉴스 기사를 가져와 처리하는 실제 예제를 만들어 보자.

우주 뉴스 지식 소스 예제

from crewai import Agent, Task, Crew, Process, LLM
from crewai.knowledge.source.base_knowledge_source import BaseKnowledgeSource
import requests
from datetime import datetime
from typing import Dict, Any
from pydantic import BaseModel, Field

class SpaceNewsKnowledgeSource(BaseKnowledgeSource):
    """Space News API에서 데이터를 가져오는 지식 소스."""

    api_endpoint: str = Field(description="API 엔드포인트 URL")
    limit: int = Field(default=10, description="가져올 기사 수")

    def load_content(self) -> Dict[Any, str]:
        """우주 뉴스 기사를 가져와 포맷팅한다."""
        try:
            response = requests.get(
                f"{self.api_endpoint}?limit={self.limit}"
            )
            response.raise_for_status()

            data = response.json()
            articles = data.get('results', [])

            formatted_data = self._format_articles(articles)
            return {self.api_endpoint: formatted_data}
        except Exception as e:
            raise ValueError(f"우주 뉴스를 가져오는 데 실패: {str(e)}")

    def _format_articles(self, articles: list) -> str:
        """기사를 읽기 쉬운 텍스트로 포맷팅한다."""
        formatted = "우주 뉴스 기사:\n\n"
        for article in articles:
            formatted += f"""
                제목: {article['title']}
                게시일: {article['published_at']}
                요약: {article['summary']}
                뉴스 사이트: {article['news_site']}
                URL: {article['url']}
                -------------------"""
        return formatted

    def add(self) -> None:
        """기사를 처리하고 저장한다."""
        content = self.load_content()
        for _, text in content.items():
            chunks = self._chunk_text(text)
            self.chunks.extend(chunks)

        self._save_documents()

# 지식 소스 생성
recent_news = SpaceNewsKnowledgeSource(
    api_endpoint="https://api.spaceflightnewsapi.net/v4/articles",
    limit=10,
)

# 전문가 에이전트 생성
space_analyst = Agent(
    role="우주 뉴스 분석가",
    goal="우주 뉴스에 대한 질문에 정확하고 포괄적으로 답변한다",
    backstory="""우주 탐사, 위성 기술, 우주 산업 동향에 전문 지식을 가진 우주 산업 분석가다. 
    우주 뉴스에 대한 질문에 답변하고 상세하고 정확한 정보를 제공하는 데 뛰어나다.""",
    knowledge_sources=[recent_news],
    llm=LLM(model="gpt-4", temperature=0.0)
)

# 사용자 질문을 처리하는 태스크 생성
analysis_task = Task(
    description="우주 뉴스에 대한 이 질문에 답변한다: {user_question}",
    expected_output="최신 우주 뉴스 기사를 기반으로 한 상세한 답변",
    agent=space_analyst
)

# 크루 생성 및 실행
crew = Crew(
    agents=[space_analyst],
    tasks=[analysis_task],
    verbose=True,
    process=Process.sequential
)

# 사용 예시
result = crew.kickoff(
    inputs={"user_question": "우주 탐사의 최신 동향은 무엇인가?"}
)

주요 컴포넌트 설명

  1. 커스텀 지식 소스 (SpaceNewsKnowledgeSource):

    • CrewAI와의 통합을 위해 BaseKnowledgeSource를 상속받는다.
    • 구성 가능한 API 엔드포인트와 기사 제한 수를 설정한다.
    • 세 가지 주요 메서드를 구현한다:
      • load_content(): API에서 기사를 가져온다.
      • _format_articles(): 기사를 읽기 쉬운 텍스트로 구조화한다.
      • add(): 콘텐츠를 처리하고 저장한다.
  2. 에이전트 구성:

    • Space News Analyst라는 특화된 역할을 가진다.
    • 지식 소스를 활용해 우주 뉴스에 접근한다.
  3. 태스크 설정:

    • {user_question}을 통해 사용자 질문을 입력받는다.
    • 지식 소스를 기반으로 상세한 답변을 제공하도록 설계된다.
  4. Crew 오케스트레이션:

    • 에이전트와 태스크 간의 워크플로를 관리한다.
    • kickoff 메서드를 통해 입력과 출력을 처리한다.

이 예제는 다음과 같은 방법을 보여준다:

  • 실시간 데이터를 가져오는 커스텀 지식 소스를 만든다.
  • 외부 데이터를 AI가 사용할 수 있도록 처리하고 구조화한다.
  • 지식 소스를 사용해 특정 사용자 질문에 답변한다.
  • 모든 것을 CrewAI의 에이전트 시스템과 원활하게 통합한다.

Spaceflight News API 소개

이 예제는 Spaceflight News API를 사용한다. 이 API는 다음과 같은 특징을 가진다:

  • 우주 관련 뉴스 기사에 무료로 접근할 수 있다
  • 인증이 필요하지 않다
  • 우주 뉴스에 대한 구조화된 데이터를 반환한다
  • 페이징과 필터링을 지원한다

API 쿼리는 엔드포인트 URL을 수정하여 커스터마이징할 수 있다:

# 더 많은 기사 가져오기
recent_news = SpaceNewsKnowledgeSource(
    api_endpoint="https://api.spaceflightnewsapi.net/v4/articles",
    limit=20,  # 기사 수를 늘림
)

# 검색 파라미터 추가
recent_news = SpaceNewsKnowledgeSource(
    api_endpoint="https://api.spaceflightnewsapi.net/v4/articles?search=NASA", # NASA 관련 뉴스 검색
    limit=10,
)

모범 사례