스타터 튜토리얼

스타터 튜토리얼 (OpenAI 사용하기)

LlamaIndex로 에이전트를 구축하는 방법을 시작부터 배워요. 기본 계산기 예제로 시작한 뒤, 문서 검색을 더한 RAG(Retrieval-Augmented Generation) 기능을 추가해 봅시다.

출처: 문서

본문

이 튜토리얼에서는 LlamaIndex로 에이전트를 구축하는 방법을 시작부터 보여드립니다. 기본 예제로 시작한 뒤 RAG(Retrieval-Augmented Generation) 기능을 추가하는 방법을 보여드리겠습니다.

팁

먼저 설치 단계를 따랐는지 확인하세요.

팁

로컬 모델을 사용하고 싶나요? 로컬 모델만으로 스타터 튜토리얼을 하고 싶다면 이 튜토리얼을 대신 확인하세요.

OpenAI API 키 설정

LlamaIndex는 기본적으로 OpenAI의 gpt-3.5-turbo를 사용하지만, 이 예제에서는 LLM으로 gpt-4o-mini를 사용합니다. API 키를 환경 변수로 설정해 코드에서 사용할 수 있게 하세요.

터미널 창

# MacOS/Linux
export OPENAI_API_KEY=XXXXX


# Windows
set OPENAI_API_KEY=XXXXX

팁

OpenAI 호환 API를 사용한다면 OpenAILike LLM 클래스를 사용할 수 있습니다. 더 자세한 내용은 OpenAILike LLM 통합과 OpenAILike Embeddings 통합에서 확인하세요.

기본 에이전트 예제

도구(tool)를 호출해 기본적인 곱셈을 수행하는 간단한 에이전트 예제부터 시작해 보겠습니다. starter.py라는 파일을 만드세요.

import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI




# Define a simple calculator tool
def multiply(a: float, b: float) -> float:
    """Useful for multiplying two numbers."""
    return a * b




# Create an agent workflow with our calculator tool
agent = FunctionAgent(
    tools=[multiply],
    llm=OpenAI(model="gpt-4o-mini"),
    system_prompt="You are a helpful assistant that can multiply two numbers.",
)




async def main():
    # Run the agent
    response = await agent.run("What is 1234 * 4567?")
    print(str(response))




# Run the agent
if __name__ == "__main__":
    asyncio.run(main())

이렇게 하면 다음과 같은 출력이 나옵니다: The result of \\( 1234 \\times 4567 \\) is \\( 5,678,678 \\).

무슨 일이 일어났는지 정리하면:

  • 에이전트에 질문이 주어졌습니다: What is 1234 * 4567?
  • 내부적으로 이 질문과 도구의 스키마(이름, docstring, 인자)가 LLM에 전달되었습니다.
  • 에이전트가 multiply 도구를 선택하고 도구에 인자를 작성했습니다.
  • 에이전트가 도구에서 결과를 받아 최종 응답에 반영했습니다.

팁

보시다시피 async Python 함수를 사용하고 있습니다. 많은 LLM과 모델이 비동기 호출을 지원하며, 애플리케이션 성능을 높이려면 비동기 코드를 사용하는 것이 권장됩니다. async 코드와 Python에 대해 더 배우려면 async + python 짧은 섹션을 추천합니다.

대화 기록 추가하기

AgentWorkflow는 이전 메시지도 기억할 수 있습니다. 이것은 AgentWorkflow의 Context 안에 포함되어 있습니다.

Context를 전달하면 에이전트가 그것을 사용해 대화를 이어갑니다.

from llama_index.core.workflow import Context


# create context
ctx = Context(agent)


# run agent with context
response = await agent.run("My name is Logan", ctx=ctx)
response = await agent.run("What is my name?", ctx=ctx)

RAG 기능 추가하기

이제 문서를 검색하는 기능을 추가해 에이전트를 향상시켜 보겠습니다. 먼저 터미널을 사용해 예제 데이터를 가져옵니다.

터미널 창

mkdir data
wget https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt -O data/paul_graham_essay.txt

디렉터리 구조는 이제 이렇게 보여야 합니다.

├── starter.py └── data    └── paul_graham_essay.txt

이제 LlamaIndex를 사용해 문서를 검색하는 도구를 만들 수 있습니다. Settings.embed_model을 구성하지 않으면 VectorStoreIndex는 OpenAIEmbedding으로 폴백하며, 기본적으로 text-embedding-ada-002 모델을 사용합니다. 새 프로젝트에는 OpenAIEmbedding(model="text-embedding-3-small")을 명시적으로 전달할 것을 권장합니다.

팁

API 키 없이 임베딩을 로컬에서 실행하고 싶나요? 호스팅 임베더를 로컬 Sentence Transformers 모델로 두 줄만 바꾸면 됩니다.

from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.core import Settings


Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

완전히 로컬인 파이프라인은 로컬 스타터 튜토리얼을 참고하세요.

수정된 starter.py는 이렇게 보여야 합니다.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI
import asyncio
import os


# Create a RAG tool using LlamaIndex
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()




def multiply(a: float, b: float) -> float:
    """Useful for multiplying two numbers."""
    return a * b




async def search_documents(query: str) -> str:
    """Useful for answering natural language questions about an personal essay written by Paul Graham."""
    response = await query_engine.aquery(query)
    return str(response)




# Create an enhanced workflow with both tools
agent = FunctionAgent(
    tools=[multiply, search_documents],
    llm=OpenAI(model="gpt-4o-mini"),
    system_prompt="""You are a helpful assistant that can perform calculations
    and search through documents to answer questions.""",
)




# Now we can ask questions about the documents or do calculations
async def main():
    response = await agent.run(
        "What did the author do in college? Also, what's 7 * 8?"
    )
    print(response)




# Run the agent
if __name__ == "__main__":
    asyncio.run(main())

이제 에이전트는 계산기를 사용하는 것과 문서를 검색해 질문에 답하는 것 사이를 자연스럽게 전환할 수 있습니다.

RAG 인덱스 저장하기

매번 문서를 다시 처리하지 않으려면 인덱스를 디스크에 저장(persist)할 수 있습니다.

# Save the index
index.storage_context.persist("storage")


# Later, load the index
from llama_index.core import StorageContext, load_index_from_storage


storage_context = StorageContext.from_defaults(persist_dir="storage")
index = load_index_from_storage(storage_context)
query_engine = index.as_query_engine()

팁

기본이 아닌 벡터 저장소 통합을 사용했다면 벡터 저장소에서 그대로 다시 불러올 수 있습니다.

index = VectorStoreIndex.from_vector_store(vector_store)

다음 단계는?

이것은 LlamaIndex 에이전트로 할 수 있는 것의 시작일 뿐입니다! 다음과 같은 것들을 할 수 있습니다.

  • 에이전트에 도구 더 추가하기
  • 다른 LLM 사용하기
  • 시스템 프롬프트로 에이전트 동작 커스터마이징하기
  • 스트리밍 기능 추가하기
  • 인간 개입(human-in-the-loop) 워크플로 구현하기
  • 여러 에이전트를 사용해 태스크 협업하기

유용한 다음 링크:

더 알아보기 (Learn more)