👌

LangWatch 触ってみた

に公開

こんにちは、DAIJOBU 技術部の Nozawa です!

生成 AI を使ったサービス開発が当たり前になったいま、「作ったモデルが本当に期待どおり動いているのか?」「どの改善案が一番効いているのか?」を 定量的に、かつ素早く 検証できる環境づくりがますます重要になっています。

そこで今回は、LLM アプリの評価・監視をワンストップで支える LangWatch を使ってみました。
データセットのバージョン管理から実験の可視化、メトリクスのダッシュボード化まで――「これ一つで全部できるのは本当なのか?」を確かめるべく、実際に RAG ワークフローで検証した手順と所感をまとめています。

本記事では
・LangWatch の基本機能と使い方
・サンプルコード付きの評価ループ実装ポイント
・触ってわかった良い点・気になる点
・今後の活用アイデア

を順番にご紹介します。

LLM 開発・運用で「もっと楽に評価したい!」と感じている方は、ぜひ最後までチェックしてみてください。それでは、本題に入りましょう!

1. LangWatch 概要

LangWatch は LLM アプリの観測・評価基盤 です。データセットの保管から実験の管理、メトリクスの可視化までをワンストップで提供し、次のようなユースケースに向いています。

機能領域 主な目的
Dataset 管理 CSV / JSON などでアップロードした QA ペアやチャンクをバージョン管理し、API で取得可能にする
Experiment 追跡 evaluation.init() で実験を作成し、メトリクスをストリームで記録。複数ランの比較も容易
Metric ダッシュボード Precision・Recall などの集計を UI で確認。フィルタや行単位の差分ビューも可能
API & SDK langwatch Python SDK と REST API の両方を提供。CI からの自動計測にも対応
  1. langwatch.login() で認証
  2. dataset.get_dataset(slug) でデータフレーム取得
  3. 予測結果やメトリクスを evaluation.log() で逐次記録
  4. Web UI でスカラー値・テーブル・履歴を確認

2. 主な機能紹介

  • データセットのバージョン管理:Studio から GUI でアップロード/エクスポートが可能。API からもエントリを追加・更新。



  • 実験テンプレートevaluation.loop(df.iterrows()) が tqdm 風に進捗を表⽰しながら行単位で評価関数を適用。

  • メトリクス多様化:独自関数の数値も同列に可視化。

  • 行レベル diff:行をクリックすると、モデル出力と Gold を確認。


3. 実装コード(要点抜粋)

# --- 前処理 & 補助関数 -----------------------------------------
from dotenv import load_dotenv; load_dotenv()
import os, langwatch, pandas as pd
from openai import OpenAI

client = OpenAI()  # OPENAI_API_KEY 必須

# 2‑gram 40% 以上の重複でマッチと判定
def has_bigram_overlap(a: str, b: str, thr: float = .4) -> bool:
    ngram = lambda s: [''.join(p) for p in zip(s, s[1:])]
    g1, g2 = set(ngram(a)), set(ngram(b))
    return g1 and g2 and len(g1 & g2) / len(g2) >= thr

# LLM で最終ジャッジ
def llm_semantic_match(a: str, b: str) -> bool:
    prompt = ("次の2文が同じ意味か判断して下さい。同じなら 'YES'、違うなら 'NO':\n\n"
              f"文1: {a}\n文2: {b}")
    resp = client.chat.completions.create(
        model="gpt-4o-mini", messages=[{"role":"user","content":prompt}], temperature=0
    )
    return resp.choices[0].message.content.strip().upper().startswith("Y")

# Precision / Recall / F1 の算出
def score_cosine_precision_recall_f1(predicted: list[str], gold: list[str]):
    tp = fp = 0; matched = set()
    for p in predicted:
        for gi, g in enumerate(gold):
            if gi in matched: continue
            if p.strip()==g.strip() or has_bigram_overlap(p,g) or llm_semantic_match(p,g):
                tp += 1; matched.add(gi); break
    fp = len(predicted)-tp; fn = len(gold)-tp
    prec = tp/(tp+fp) if tp+fp else 0
    rec  = tp/(tp+fn) if tp+fn else 0
    f1   = 2*prec*rec/(prec+rec) if prec+rec else 0
    return prec, rec, f1

# --- LangWatch ワークフロー ------------------------------------
SLUG = "ssssss"
langwatch.login()                         # .env のトークンで認証

# データセット取得
raw_df = langwatch.dataset.get_dataset(SLUG).to_pandas()

# ▼▼ ここだけ自分の検索ロジックに置き換える ▼▼
def rag(question: str, k: int = 3):
    return [f"{question}_chunk{i+1}" for i in range(k)]

raw_df["retrievedchunk"] = raw_df["question"].apply(lambda q: ";".join(rag(q)))

# 実験の開始
exp = langwatch.evaluation.init("my-experiment")
for idx, row in exp.loop(raw_df.iterrows()):
    pred = row["retrievedchunk"].split(";")
    gold = row["参照先"].split(";")
    p,r,f1 = score_cosine_precision_recall_f1(pred, gold)
    exp.log("CosinePrecision", index=idx, score=p)
    exp.log("CosineRecall",    index=idx, score=r)
    exp.log("CosineF1",        index=idx, score=f1)

ポイント

  • evaluation.loop() は行ごとの try/except 包囲が不要で、途中失敗しても UI にログを残します。
  • RAG 検索部分(rag())だけ差し替えれば、Retrieval ロジックの A/B 比較が可能。

4. 良い点・悪い点・所感

👍 良い点

  1. セットアップが簡単pip install langwatch と API トークンだけで開始。
  2. Pandas 互換to_pandas() があるので前処理を既存コードに組み込みやすい。
  3. 評価ループの抽象化:進捗バー+自動ログで実装負荷が低い。
  4. LLM ジャッジの内包:外部スクリプト不要でも高度な一致判定を挟める。
  5. ダッシュボードが軽快:数万行でもスクロールが滑らか。誤差行のフィルタも高速。

👎 気になる点 / 課題

項目 内容
ドキュメント SDK / REST の仕様が微妙に食い違う箇所があり、エラーハンドリングに詰まることがある
Python 3.12 以降の互換 一部依存パッケージの pin が緩く、langwatch が 3.13 で ImportError になる例を確認
UI への Export 実験結果を PDF/PNG で出力する機能が未実装(現状は CSV ダウンロードのみ)
並列処理 ドキュメント記載の並列処理とtraceを組み合わせるとエラーが発生する。並列処理を実装する必要あり

💭 所感

  • 評価テンプレが秀逸:単体テストを書くよりも高速に指標比較でき、生産性は高い。
  • LLM 評価の可視化 は解釈しやすく、ビジネスサイドへの説明も楽。
  • 並列処理かつtraceを組み合わせるとエラーになるのはもったいない。
  • SDK がオープンソースになったことで PR を送りやすい。公式の Issue も 2025 年現在は 48h 以内に応答が来るため安心感。

次のステップ案

  • rag() を FAISS + sentence-transformers に置き換え、本格的な A/B テストを実施
  • メトリクス閾値を Triggers 機能で設定し、Slack 連携でデグレを即時検知
  • 大規模データ向けに langwatch dataset push --batch の CLI 提案をフィードバックとして送付

まとめ

LangWatch は “評価・監視まわりを丸ごと肩代わりしてくれる基盤”。データセットのバージョン管理、実験のトラッキング、メトリクスの可視化がワンストップで完結します。

●pip install langwatch と API トークンだけですぐに使い始められ、Pandas 互換データフレーム+進捗つき evaluation.loop() により、従来よりはるかに少ないコードで再現性の高い実験を回せました。

●行レベル diff ビュー や 任意指標の可視化 により、モデル出力の “どこがズレたか” を秒で把握できるのも大きな魅力です。

一方で、ドキュメントの細かな齟齬や Python 3.12 以降の依存関係、エクスポート機能の不足など 改善余地もいくつか確認 しました。

次のステップとしては FAISS+sentence-transformers で Retrieval をリプレイス した A/B テストや、Trigger 機能+Slack 連携による自動デグレ検知 を仕込むことで、より実戦的な LLM 運用フローを構築できそうです。

DAIJOBUではLLMの品質向上サービス「AI Agent品質担保くん」に力を入れており、QAエンジニアやLLMエンジニアを絶賛募集中です。

ご興味ある方はぜひこちらからお問い合わせください!

https://daijobuinc.notion.site/DAIJOBU-b37f8f71542e4b0996a4dbe8f005e6ee?pvs=143

Discussion