메인 콘텐츠로 건너뛰기
Weave는 LlamaIndex Python 라이브러리를 통해 이루어지는 모든 호출의 추적 및 로깅을 단순화하도록 설계되었습니다. LLM을 사용할 때 디버깅은 피할 수 없습니다. 모델 호출이 실패하거나 출력 형식이 잘못되었거나 중첩된 모델 호출로 인해 혼란이 생기는 등, 문제 지점을 정확히 찾는 것은 어려울 수 있습니다. LlamaIndex 애플리케이션은 종종 여러 단계와 LLM 호출로 구성되므로, 체인과 에이전트의 내부 동작을 이해하는 것이 매우 중요합니다. Weave는 LlamaIndex 애플리케이션에 대한 트레이스를 자동으로 캡처하여 이러한 작업을 단순화합니다. 이를 통해 애플리케이션 성능을 모니터링하고 분석할 수 있어 LLM 워크플로를 더 쉽게 디버그하고 최적화할 수 있습니다. 또한 Weave는 평가 워크플로에도 유용합니다.

시작하기

시작하려면 스크립트의 시작 부분에서 weave.init()을 호출하면 됩니다. weave.init()에 전달하는 인수는 추적을 정리하는 데 도움이 되는 프로젝트 이름입니다.
import weave
from llama_index.core.chat_engine import SimpleChatEngine

# 프로젝트 이름으로 Weave 초기화
weave.init("llamaindex_demo")

chat_engine = SimpleChatEngine.from_defaults()
response = chat_engine.chat(
    "Say something profound and romantic about fourth of July"
)
print(response)
위 예제에서는 내부적으로 OpenAI 호출을 수행하는 간단한 LlamaIndex 챗 엔진을 생성합니다. 아래 트레이스를 살펴보세요: simple_llamaindex.png

트레이싱

LlamaIndex는 데이터와 LLM을 손쉽게 연결할 수 있는 것으로 잘 알려져 있습니다. 간단한 RAG 애플리케이션에는 임베딩 단계, 검색 단계, 응답 합성 단계가 필요합니다. 애플리케이션이 복잡해질수록 개발과 프로덕션 환경 모두에서 각 단계를 중앙 데이터베이스에 트레이스(추적 기록)로 저장하는 것이 중요해집니다. 이러한 트레이스는 애플리케이션을 디버깅하고 개선하는 데 필수적입니다. Weave는 LlamaIndex 라이브러리를 통해 이루어지는 모든 호출(프롬프트 템플릿, LLM 호출, 도구, 에이전트 단계 포함)을 자동으로 추적합니다. Weave 웹 인터페이스에서 이러한 트레이스를 확인할 수 있습니다. 아래는 LlamaIndex의 Starter Tutorial (OpenAI)에 나오는 간단한 RAG 파이프라인 예시입니다.
import weave
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

# 프로젝트 이름으로 Weave 초기화
weave.init("llamaindex_demo")

# `data` 디렉토리에 `.txt` 파일이 있다고 가정
documents = SimpleDirectoryReader("data").load_data()
index = VectorStoreIndex.from_documents(documents)

query_engine = index.as_query_engine()
response = query_engine.query("What did the author do growing up?")
print(response)
트레이스 타임라인에는 “이벤트”뿐 아니라 실행 시간, 비용, 그리고 해당하는 경우 토큰 수까지 함께 기록됩니다. 트레이스를 확장해 각 단계의 입력과 출력을 확인하세요. llamaindex_rag.png

원클릭 Observability 🔭

LlamaIndex는 프로덕션 환경에서 원칙에 기반한 LLM 애플리케이션을 구축할 수 있도록 원클릭 Observability 🔭 기능을 제공합니다. 본 통합 기능은 LlamaIndex의 이 기능을 활용하여 WeaveCallbackHandler()llama_index.core.global_handler로 자동 설정합니다. 따라서 사용자는 LlamaIndex와 Weave를 사용할 때 weave.init(<name-of-project>)로 Weave 실행만 초기화하면 됩니다.

실험을 더 쉽게 하기 위한 Model 만들기

프롬프트, 모델 구성, 추론 파라미터 등 여러 구성 요소 때문에 다양한 사용 사례에 맞춰 애플리케이션 내 LLM을 구성하고 평가하는 일은 까다롭습니다. weave.Model을 사용하면 시스템 프롬프트나 사용한 모델과 같은 실험 세부 정보를 기록·정리할 수 있어, 서로 다른 실험 버전을 더 쉽게 비교할 수 있습니다. 다음 예시는 weave/data 폴더에서 제공되는 데이터를 사용해, WeaveModel 안에서 LlamaIndex 쿼리 엔진을 구성하는 방법을 보여줍니다:
import weave

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.openai import OpenAI
from llama_index.core import PromptTemplate


PROMPT_TEMPLATE = """
You are given with relevant information about Paul Graham. Answer the user query only based on the information provided. Don't make up stuff.

User Query: {query_str}
Context: {context_str}
Answer:
"""

class SimpleRAGPipeline(weave.Model):
    chat_llm: str = "gpt-4"
    temperature: float = 0.1
    similarity_top_k: int = 2
    chunk_size: int = 256
    chunk_overlap: int = 20
    prompt_template: str = PROMPT_TEMPLATE

    def get_llm(self):
        return OpenAI(temperature=self.temperature, model=self.chat_llm)

    def get_template(self):
        return PromptTemplate(self.prompt_template)

    def load_documents_and_chunk(self, data):
        documents = SimpleDirectoryReader(data).load_data()
        splitter = SentenceSplitter(
            chunk_size=self.chunk_size,
            chunk_overlap=self.chunk_overlap,
        )
        nodes = splitter.get_nodes_from_documents(documents)
        return nodes

    def get_query_engine(self, data):
        nodes = self.load_documents_and_chunk(data)
        index = VectorStoreIndex(nodes)

        llm = self.get_llm()
        prompt_template = self.get_template()

        return index.as_query_engine(
            similarity_top_k=self.similarity_top_k,
            llm=llm,
            text_qa_template=prompt_template,
        )

    @weave.op()
    def predict(self, query: str):
        query_engine = self.get_query_engine(
            # 이 데이터는 weave 저장소의 data/paul_graham 경로에서 찾을 수 있습니다
            "data/paul_graham",
        )
        response = query_engine.query(query)
        return {"response": response.response}

weave.init("test-llamaindex-weave")

rag_pipeline = SimpleRAGPipeline()
response = rag_pipeline.predict("What did the author do growing up?")
print(response)
weave.Model을 상속한 이 SimpleRAGPipeline 클래스는 이 RAG 파이프라인의 주요 매개변수를 구성합니다. query 메서드를 weave.op()으로 데코레이팅하면 추적(tracing)이 가능해집니다. llamaindex_model.png

weave.Evaluation으로 평가 수행하기

평가는 애플리케이션의 성능을 측정하는 데 도움이 됩니다. weave.Evaluation 클래스를 사용하면, 모델이 특정 작업이나 데이터셋에서 얼마나 잘 동작하는지 기록할 수 있어 서로 다른 모델과 애플리케이션의 여러 버전을 더 쉽게 비교할 수 있습니다. 아래 예시는 우리가 생성한 모델을 어떻게 평가하는지 보여줍니다:
import asyncio
from llama_index.core.evaluation import CorrectnessEvaluator

eval_examples = [
    {
        "id": "0",
        "query": "What programming language did Paul Graham learn to teach himself AI when he was in college?",
        "ground_truth": "Paul Graham learned Lisp to teach himself AI when he was in college.",
    },
    {
        "id": "1",
        "query": "What was the name of the startup Paul Graham co-founded that was eventually acquired by Yahoo?",
        "ground_truth": "The startup Paul Graham co-founded that was eventually acquired by Yahoo was called Viaweb.",
    },
    {
        "id": "2",
        "query": "What is the capital city of France?",
        "ground_truth": "I cannot answer this question because no information was provided in the text.",
    },
]

llm_judge = OpenAI(model="gpt-4", temperature=0.0)
evaluator = CorrectnessEvaluator(llm=llm_judge)

@weave.op()
def correctness_evaluator(query: str, ground_truth: str, output: dict):
    result = evaluator.evaluate(
        query=query, reference=ground_truth, response=output["response"]
    )
    return {"correctness": float(result.score)}

evaluation = weave.Evaluation(dataset=eval_examples, scorers=[correctness_evaluator])

rag_pipeline = SimpleRAGPipeline()

asyncio.run(evaluation.evaluate(rag_pipeline))
이 평가는 앞선 섹션의 예제를 기반으로 합니다. weave.Evaluation을 사용해 평가하려면 평가 데이터셋, scorer 함수, 그리고 weave.Model이 필요합니다. 아래는 이 세 가지 핵심 구성 요소에 대한 몇 가지 유의사항입니다:
  • 평가 샘플 딕셔너리의 키가 scorer 함수의 인자 및 weave.Modelpredict 메서드 인자와 일치하는지 확인하세요.
  • weave.Model에는 predict 또는 infer 또는 forward라는 이름의 메서드가 있어야 합니다. 이 메서드에 추적을 위해 weave.op() 데코레이터를 적용하세요.
  • scorer 함수는 weave.op()으로 데코레이션해야 하며, output이라는 이름의 인자를 가져야 합니다.
llamaindex_evaluation.png Weave를 LlamaIndex와 통합하면 평가를 활용해 LLM 애플리케이션에 대한 포괄적인 로깅과 모니터링을 수행할 수 있어, 디버깅과 성능 최적화를 더 쉽게 진행할 수 있습니다.