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 からの自動計測にも対応 |
-
langwatch.login()で認証 -
dataset.get_dataset(slug)でデータフレーム取得 - 予測結果やメトリクスを
evaluation.log()で逐次記録 - 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. 良い点・悪い点・所感
👍 良い点
-
セットアップが簡単:
pip install langwatchと API トークンだけで開始。 -
Pandas 互換:
to_pandas()があるので前処理を既存コードに組み込みやすい。 - 評価ループの抽象化:進捗バー+自動ログで実装負荷が低い。
- LLM ジャッジの内包:外部スクリプト不要でも高度な一致判定を挟める。
- ダッシュボードが軽快:数万行でもスクロールが滑らか。誤差行のフィルタも高速。
👎 気になる点 / 課題
| 項目 | 内容 |
|---|---|
| ドキュメント | 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