스타터 튜토리얼

스타터 튜토리얼 (로컬 LLM 사용하기)

Ollama와 HuggingFace 임베딩 같은 로컬 모델만으로 LlamaIndex 에이전트를 구축하는 방법을 배워요. API 키 없이 계산기 도구와 RAG 기능을 갖춘 에이전트를 만들어 봅시다.

출처: 문서

본문

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

임베딩 모델로 BAAI/bge-base-en-v1.5를 사용하고, Ollama로 서빙되는 llama3.1 8B를 사용하겠습니다.

팁

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

설정

Ollama는 최소한의 설정으로 LLM을 로컬에서 실행할 수 있게 해주는 도구입니다.

README를 따라 설치 방법을 배우세요.

Llama3 모델을 다운로드하려면 ollama pull llama3.1을 실행하면 됩니다.

참고: 최소 ~32GB RAM이 있는 머신이 필요합니다.

설치 가이드에서 설명한 대로 llama-index는 실제로 패키지 모음입니다. Ollama와 Huggingface를 실행하려면 해당 통합들을 설치해야 합니다.

터미널 창

pip install llama-index-llms-ollama llama-index-embeddings-huggingface

패키지 이름이 import를 그대로 풀어낸 형태라서, 어떻게 import하거나 설치해야 할지 기억하기 아주 좋습니다.

from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

더 많은 통합은 integrations 페이지에 나와 있습니다.

기본 에이전트 예제

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

import asyncio
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.ollama import Ollama




# 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=Ollama(
        model="llama3.1",
        request_timeout=360.0,
        # Manually set the context window to limit memory usage
        context_window=8000,
    ),
    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 answer to 1234 * 4567 is 5635678.

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

  • 에이전트에 질문이 주어졌습니다: 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를 사용해 문서를 검색하는 도구를 만들 수 있습니다. 호스팅 API 기본값에 의존하는 대신, Settings.embed_model을 HuggingFaceEmbedding(model_name="BAAI/bge-base-en-v1.5")로 구성해서 인덱싱과 검색 모두 API 키 없이 로컬 Sentence Transformers 모델을 사용하도록 하겠습니다.

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

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.core.agent.workflow import AgentWorkflow
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
import asyncio
import os


# Settings control global defaults
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-base-en-v1.5")
Settings.llm = Ollama(
    model="llama3.1",
    request_timeout=360.0,
    # Manually set the context window to limit memory usage
    context_window=8000,
)


# Create a RAG tool using LlamaIndex
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(
    documents,
    # we can optionally override the embed_model here
    # embed_model=Settings.embed_model,
)
query_engine = index.as_query_engine(
    # we can optionally override the llm here
    # llm=Settings.llm,
)




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 = AgentWorkflow.from_tools_or_functions(
    [multiply, search_documents],
    llm=Settings.llm,
    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,
    # we can optionally override the embed_model here
    # it's important to use the same embed_model as the one used to build the index
    # embed_model=Settings.embed_model,
)
query_engine = index.as_query_engine(
    # we can optionally override the llm here
    # llm=Settings.llm,
)

팁

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

index = VectorStoreIndex.from_vector_store(
    vector_store,
    # it's important to use the same embed_model as the one used to build the index
    # embed_model=Settings.embed_model,
)

다음 단계는?

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

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

유용한 다음 링크:

더 알아보기 (Learn more)