メインコンテンツへスキップ
Weave は、LlamaIndex Python library を通じて行われるすべての call のトラッキングとログすることを簡素化できるように設計されています。 LLM を扱う際、デバッグは避けられません。モデルの呼び出しが失敗した場合でも、出力の形式が正しくない場合でも、ネストされたモデル call によって混乱が生じる場合でも、問題を特定するのは簡単ではありません。LlamaIndex アプリケーションは、多くの場合、複数の step と LLM 呼び出しで構成されているため、chain や agent の内部動作を理解することが重要です。 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 への call を行うシンプルな LlamaIndex のチャットエンジンを作成しています。以下のトレースを確認してください。 simple_llamaindex.png

トレース

LlamaIndex は、データを LLM に簡単に接続できることで知られています。シンプルな RAG application には、埋め込み step、検索 step、応答生成 step が必要です。複雑さが増すにつれて、開発時と本番環境の両方で、個々の step のトレースを中央データベースに保存することが重要になります。 これらのトレースは、application のデバッグや改善に不可欠です。Weave は、プロンプトテンプレート、LLM calls、tool、agent steps を含め、LlamaIndex ライブラリを通じて行われるすべての calls を自動的にトラッキングします。トレースは Weave の Web インターフェースで確認できます。 以下は、LlamaIndex’s 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)
トレースタイムラインは、“イベント” をキャプチャするだけでなく、該当する場合は実行時間、コスト、token 数も記録します。トレースを掘り下げると、各 step の inputs と outputs を確認できます。 llamaindex_rag.png

ワンクリックでの可観測性 🔭

LlamaIndex は、本番環境で筋の通った LLM アプリケーションを構築できるように、ワンクリックでの可観測性 🔭を提供しています。 このインテグレーションでは、LlamaIndex のこの機能を活用し、WeaveCallbackHandler()llama_index.core.global_handler に自動で設定します。そのため、LlamaIndex と Weave を使用するユーザーが行う必要があるのは、Weave の run を初期化することだけです - weave.init(<name-of-project>)

実験をより簡単に行うための Model を作成する

さまざまなユースケースのアプリケーションで LLM を整理・評価するのは、プロンプト、モデルの設定、推論パラメーターなど、複数のコンポーネントが関わるため簡単ではありません。weave.Model を使用すると、system prompt や使用するモデルといった実験の詳細を記録して整理できるため、異なるイテレーションを比較しやすくなります。 次の例では、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() でデコレートすると、トレースできるようになります。 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 が必要です。以下に、この3つの主要コンポーネントに関する注意点を示します。
  • 評価サンプルの dict のキーが、scorer 関数の引数および weave.Modelpredict method の引数と一致していることを確認してください。
  • weave.Model には、predictinfer、または forward という名前の method が必要です。トレースのため、この method を weave.op() でデコレートしてください。
  • scorer 関数は weave.op() でデコレートし、output という名前付き引数を持つ必要があります。
llamaindex_evaluation.png Weave を LlamaIndex とインテグレーションすることで、LLM アプリケーションの包括的なログすることとモニタリングが可能になり、評価を活用したデバッグやパフォーマンスの最適化をより簡単に行えます.