메인 콘텐츠로 건너뛰기
Weave 는 LlamaIndex Python 라이브러리를 통해 이루어지는 모든 호출의 추적 및 로그 기록을 간소화하도록 설계되었습니다. LLM 으로 작업할 때 디버깅은 필수적입니다. 모델 호출이 실패하거나, 출력이 잘못된 형식으로 나오거나, 중첩된 모델 호출이 혼란을 야기할 때 문제의 원인을 정확히 짚어내는 것은 어려울 수 있습니다. LlamaIndex 애플리케이션은 종종 여러 단계와 LLM 호출 인보케이션으로 구성되므로, 체인과 에이전트의 내부 작동 방식을 이해하는 것이 매우 중요합니다. Weave 는 LlamaIndex 애플리케이션에 대한 트레이스(trace)를 자동으로 캡처하여 이 프로세스를 단순화합니다. 이를 통해 애플리케이션의 성능을 모니터링하고 분석할 수 있으며, 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

트레이싱 (Tracing)

LlamaIndex 는 데이터와 LLM 을 쉽게 연결해 주는 것으로 잘 알려져 있습니다. 간단한 RAG 애플리케이션에는 임베딩 단계, 리트리벌(retrieval) 단계, 그리고 응답 합성 단계가 필요합니다. 복잡성이 증가함에 따라, 개발 및 프로덕션 단계 모두에서 개별 단계의 트레이스를 중앙 데이터베이스에 저장하는 것이 중요해집니다. 이러한 트레이스는 애플리케이션을 디버깅하고 개선하는 데 필수적입니다. Weave 는 프롬프트 템플릿, LLM 호출, 툴, 에이전트 단계를 포함하여 LlamaIndex 라이브러리를 통해 이루어지는 모든 호출을 자동으로 추적합니다. Weave 웹 인터페이스에서 트레이스를 확인할 수 있습니다. 다음은 LlamaIndex 의 시작 튜토리얼 (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

원클릭 가시성 (One-click observability) 🔭

LlamaIndex 는 프로덕션 환경에서 원칙 있는 LLM 애플리케이션을 구축할 수 있도록 원클릭 가시성 🔭 기능을 제공합니다. W&B 의 인테그레이션은 LlamaIndex 의 이 기능을 활용하여 WeaveCallbackHandler()llama_index.core.global_handler에 자동으로 설정합니다. 따라서 LlamaIndex 와 Weave 사용자로서 해야 할 일은 weave.init(<name-of-project>)를 통해 Weave run 을 초기화하는 것뿐입니다.

더 쉬운 실험을 위한 Model 생성

다양한 유스 케이스를 위한 애플리케이션에서 프롬프트, 모델 설정, 추론 파라미터와 같은 여러 구성 요소가 섞여 있는 LLM 을 체계화하고 평가하는 것은 어려운 일입니다. weave.Model을 사용하면 시스템 프롬프트나 사용하는 모델과 같은 실험적인 세부 사항을 캡처하고 체계화하여 서로 다른 반복 회차(iteration)를 더 쉽게 비교할 수 있습니다. 다음 예시는 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 = """
당신은 Paul Graham에 대한 관련 정보를 제공받았습니다. 제공된 정보에만 기반하여 사용자 쿼리에 답하세요. 지어내지 마세요.

사용자 쿼리: {query_str}
컨텍스트: {context_str}
답변:
"""

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 파이프라인의 중요한 파라미터들을 체계적으로 관리합니다. predict 메소드에 @weave.op() 데코레이터를 추가하면 트레이싱이 가능해집니다. llamaindex_model.png

weave.Evaluation으로 평가 수행하기

평가(Evaluation)는 애플리케이션의 성능을 측정하는 데 도움을 줍니다. weave.Evaluation 클래스를 사용하면 모델이 특정 태스크나 Datasets 에서 얼마나 잘 수행되는지 캡처할 수 있어, 서로 다른 모델과 애플리케이션의 반복 회차를 더 쉽게 비교할 수 있습니다. 다음 예시는 우리가 만든 모델을 평가하는 방법을 보여줍니다.
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이 필요합니다. 세 가지 주요 구성 요소에 대한 몇 가지 참고 사항은 다음과 같습니다:
  • 평가 샘플 딕셔너리의 키가 스코어러 함수의 인수 및 weave.Modelpredict 메소드 인수와 일치하는지 확인하세요.
  • weave.Modelpredict, infer 또는 forward라는 이름의 메소드를 가져야 합니다. 트레이싱을 위해 이 메소드에 @weave.op()를 데코레이션하세요.
  • 스코어러 함수는 @weave.op()로 데코레이션되어야 하며 output을 이름이 지정된 인수(named argument)로 가져야 합니다.
llamaindex_evaluation.png Weave 를 LlamaIndex 와 통합함으로써, LLM 애플리케이션에 대한 포괄적인 로깅 및 모니터링을 보장하고, 평가를 통해 더 쉬운 디버깅과 성능 최적화를 진행할 수 있습니다.