モデルに依存しない可観測性のためのLangfuse
あらゆるLLMプロバイダーで動作するオープンソースの代替手段としてLangfuseを統合し、検索やツール呼び出し用のカスタムスパンを取得して、コスト追跡ダッシュボードを設定します。
「モデルに依存しない可観測性のためのLangfuse」はCoddyKit上の無料AI Engineering Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Engineering Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Engineering Academyコースには全4レッスンが含まれています。
Langfuse:オープンソースのLLMオブザーバビリティ
Langfuseは、あらゆるモデルプロバイダーに対応する、LLMアプリケーション向けのオープンソースオブザーバビリティプラットフォームです。OpenAI、Anthropic、Mistral、Ollama経由のローカルモデル、独自にファインチューニングしたモデルなどを利用できます。LangChainに依存するLangSmithとは異なり、LangfuseはシンプルなSDKを通じて、あらゆるPythonコードに統合できます。Langfuseは無料でセルフホストすることも、cloud.langfuse.comのマネージドクラウドを利用することもできます。
# pip install langfuse
from langfuse import Langfuse
langfuse = Langfuse(
public_key='pk-lf-...',
secret_key='sk-lf-...',
host='https://cloud.langfuse.com' # or your self-hosted URL
)
print('Langfuse connected:', langfuse.auth_check())トレース、スパン、Generation
Langfuseは、3つのレベルからなる階層型データモデルを使用します。トレースは、1件のユーザーリクエストをエンドツーエンドで表します。トレース内では、スパンが個々の処理ステップ(検索、前処理、ツール呼び出し)を表します。GenerationはLLM呼び出し専用の特殊なスパンで、モデル、プロンプトトークン、完了トークン、コストを構造化された形で記録します。これにより、コストダッシュボードや品質メトリクスを利用できます。
from langfuse import Langfuse
langfuse = Langfuse()
# Create a trace for one user request
trace = langfuse.trace(
name='rag-query',
user_id='user_123',
session_id='session_abc',
tags=['production', 'rag']
)
# Add a retrieval span
retrieval_span = trace.span(
name='vector-retrieval',
input={'query': 'What is RAG?'}
)
chunks = vector_db.search('What is RAG?')
retrieval_span.end(output={'chunks': [c['text'][:100] for c in chunks]})
# Add an LLM generation
generation = trace.generation(
name='answer-generation',
model='gpt-4o',
model_parameters={'temperature': 0.0},
input=[{'role': 'user', 'content': 'Context: ...\nQuestion: What is RAG?'}]
)
response = openai_client.chat.completions.create(model='gpt-4o', messages=[...])
generation.end(
output=response.choices[0].message.content,
usage={'input': response.usage.prompt_tokens, 'output': response.usage.completion_tokens}
)デコレーター統合パターン
Langfuseには、関数をトレーススパンで自動的にラップする関数デコレーターがあります。@observe()デコレーターは、入力と出力、実行時間、発生した例外を記録します。既存のコードを再構成せずに計測機能を追加する、最も簡潔な方法です。
from langfuse.decorators import observe, langfuse_context
# @observe wraps the function as a span automatically
@observe()
def retrieve_chunks(query: str) -> list[dict]:
return vector_db.search(query, top_k=5)
@observe()
def generate_answer(query: str, context: str) -> str:
response = openai_client.chat.completions.create(
model='gpt-4o',
messages=[
{'role': 'system', 'content': 'Answer using the context.'},
{'role': 'user', 'content': f'Context: {context}\nQuestion: {query}'}
]
)
# Attach LLM usage data to the current span
langfuse_context.update_current_observation(
usage={'input': response.usage.prompt_tokens, 'output': response.usage.completion_tokens},
model='gpt-4o'
)
return response.choices[0].message.content
@observe(name='rag-pipeline') # top-level trace
def rag_pipeline(query: str) -> str:
chunks = retrieve_chunks(query) # becomes a nested span
context = '\n'.join([c['text'] for c in chunks])
return generate_answer(query, context) # becomes another nested spanあらゆるLLMプロバイダーとの統合
LangChainと深く統合されたLangSmithとは異なり、Langfuseは同じデコレーターベースの方法であらゆるLLMプロバイダーに対応します。AnthropicのAPI、ローカルのOllamaモデル、Hugging Faceの推論エンドポイント、独自にファインチューニングしたモデルのいずれを呼び出す場合でも、Langfuseは同じ方法で呼び出しをトレースします。同じアプリケーションで複数のモデルを実行する場合、このプロバイダー中立性は不可欠です。
from langfuse.decorators import observe, langfuse_context
import anthropic
from openai import OpenAI
anthropic_client = anthropic.Anthropic()
openai_client = OpenAI()
@observe()
def call_claude(prompt: str) -> str:
response = anthropic_client.messages.create(
model='claude-3-5-sonnet-20241022',
max_tokens=1024,
messages=[{'role': 'user', 'content': prompt}]
)
langfuse_context.update_current_observation(
model='claude-3-5-sonnet-20241022',
usage={'input': response.usage.input_tokens, 'output': response.usage.output_tokens}
)
return response.content[0].text
@observe()
def call_gpt4(prompt: str) -> str:
response = openai_client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': prompt}]
)
langfuse_context.update_current_observation(model='gpt-4o',
usage={'input': response.usage.prompt_tokens, 'output': response.usage.completion_tokens})
return response.choices[0].message.contentコスト追跡ダッシュボード
Langfuseは、組み込みの料金表を使い、モデル名とトークン数からコストを自動計算します。この料金表は、OpenAI、Anthropic、Mistralなど、数十のプロバイダーに対応しています。コストダッシュボードには、期間ごとの総支出、モデル別のコスト、機能またはユーザー別のコスト(タグとメタデータを使用)、日次・週次の支出傾向が表示されます。この可視性により、予想外の高額請求を防ぎ、高コストな外れ値リクエストを特定できます。
# Cost data is automatically computed - no manual config
# Langfuse knows: gpt-4o input = $0.005/1K tokens, output = $0.015/1K tokens
# Add metadata to enable cost breakdown by feature
@observe(name='rag-query')
def handle_rag_query(query: str, feature: str, user_id: str) -> str:
langfuse_context.update_current_trace(
user_id=user_id,
tags=[feature, 'rag'],
metadata={'feature': feature, 'query_length': len(query)}
)
return rag_pipeline(query)
# In Langfuse dashboard you can now filter costs by:
# - feature: 'document_qa', 'chat', 'summarization'
# - user_id: to see which users are your most expensive
# - model: to compare gpt-4o vs gpt-4o-mini costs
# - date range: to see daily/weekly/monthly trendsユーザーフィードバックのスコアを追加する
Langfuseでは、後からトレースにユーザーフィードバックを紐付けることができます。ユーザーが回答に対して高評価または低評価をクリックしたとき、その結果を該当するトレースのスコアとして記録できます。これにより、実際のユーザー満足度シグナルとトレース全体のコンテキストを結び付け、高評価の回答と低評価の回答にどのような違いがあるのかを分析できます。
from langfuse.decorators import observe, langfuse_context
@observe()
def generate_response(query: str) -> dict:
answer = rag_pipeline(query)
# Get the current trace ID to link feedback later
trace_id = langfuse_context.get_current_trace_id()
return {'answer': answer, 'trace_id': trace_id}
# Later, when user submits feedback:
def record_user_feedback(trace_id: str, score: int, comment: str):
langfuse.score(
trace_id=trace_id,
name='user_satisfaction', # score name
value=score, # 1 (thumbs up) or 0 (thumbs down)
comment=comment,
data_type='BOOLEAN'
)
# Now in Langfuse: filter traces where user_satisfaction = 0
# to find the exact prompts and contexts that users rated negativelyLLM-as-Judgeによる自動スコアリング
ユーザーフィードバックに加えて、LangfuseはLLM-as-Judgeの評価器を使った自動スコアリングに対応しています。評価器を定義して、サンプリングしたトレースに対して非同期で実行し、関連性、忠実性、有害性、形式の正確性などの基準でスコアを付けられます。これらの自動スコアは人によるフィードバックと同じスコアダッシュボードに反映されるため、大規模な人手によるアノテーションなしで継続的な品質監視を行えます。
from langfuse import Langfuse
langfuse = Langfuse()
def auto_score_traces():
# Get recent unscored traces
traces = langfuse.fetch_traces(tags=['production'], limit=50)
for trace in traces.data:
question = trace.input.get('query', '')
answer = trace.output.get('answer', '') if trace.output else ''
if not question or not answer:
continue
# LLM-as-judge scoring
score = evaluate_relevance(question, answer) # returns 0.0-1.0
langfuse.score(
trace_id=trace.id,
name='auto_relevance',
value=score,
data_type='NUMERIC',
comment='Automated relevance score from LLM judge'
)
# Run this as a scheduled job every hourLangfuseでのプロンプト管理
Langfuseには、プロンプトをLangfuseのクラウドに保存し、実行時に取得できるプロンプト管理機能があります。これにより、プロンプトのバージョンをコードのデプロイから切り離せます。LangfuseのUIでプロンプトを更新すれば、コードをデプロイし直さなくても変更がすぐに反映されます。また、各トレースで使用されたプロンプトのバージョンも記録されるため、バージョン間で性能を比較できます。
from langfuse import Langfuse
langfuse = Langfuse()
# Fetch the current production prompt by name
# The prompt lives in Langfuse UI, not in your code
prompt = langfuse.get_prompt('rag-system-prompt', version='production')
# Use it in your pipeline
messages = [
{'role': 'system', 'content': prompt.compile(context_limit=4000)},
{'role': 'user', 'content': query}
]
response = openai_client.chat.completions.create(model='gpt-4o', messages=messages)
# The trace is automatically linked to the prompt version
# In Langfuse you can filter: show me traces using prompt v3 vs v4
# and compare their quality scoresLangfuseのセルフホスティング
Langfuseは、PostgreSQLをストレージとして使用し、1つのDocker Composeコマンドでセルフホストできます。セルフホスティングでは、トレースデータが自分のインフラストラクチャの外部に出ることがありません。これは、個人情報、医療データ、独自コンテンツを扱うアプリケーションに不可欠です。セルフホスト版はマネージドクラウドと同じ機能を備えていますが、バックアップ、スケーリング、アップグレードなどのインフラストラクチャ管理が必要です。
# Self-host Langfuse with Docker Compose
# docker-compose.yml (simplified)
# version: '3'
# services:
# langfuse:
# image: langfuse/langfuse:2
# ports:
# - '3000:3000'
# environment:
# - DATABASE_URL=postgresql://langfuse:password@postgres/langfuse
# - NEXTAUTH_SECRET=your-random-secret
# - SALT=your-random-salt
# postgres:
# image: postgres:15
# environment:
# - POSTGRES_DB=langfuse
# - POSTGRES_PASSWORD=password
# After docker-compose up, point your SDK to:
langfuse = Langfuse(
public_key='pk-lf-your-key',
secret_key='sk-lf-your-key',
host='http://localhost:3000' # your self-hosted instance
)LangfuseとLangSmith:どちらを選ぶべきか
LangChainを多用していて、設定不要の自動トレーシング、LangChainの評価機能との深い統合を求め、ベンダー依存を受け入れられる場合は、LangSmithを選びます。複数のLLMプロバイダーを使用する場合、データプライバシー規制への対応のためにセルフホスティングが必要な場合、オープンソースの透明性を重視する場合、またはLangChain以外のフレームワークで開発する場合は、Langfuseを選びます。どちらも本番環境に対応しており、無料枠も充実しています。
LLM向けOpenTelemetry統合
分散トレーシングにすでにOpenTelemetryを使用しているチーム向けに、LangfuseはOTLP(OpenTelemetry Protocol)による取り込みに対応しています。計測コードを変更せずに、既存のOTelエクスポーターからLLMトレースデータを直接Langfuseへ送信できます。これにより、LLMトレース、データベースクエリのスパン、HTTPリクエストのトレースをすべて一貫した相関IDで同じシステムに集約する、統合オブザーバビリティスタックを構築できます。
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Configure OTel to send to Langfuse OTLP endpoint
exporter = OTLPSpanExporter(
endpoint='https://cloud.langfuse.com/api/public/otel/v1/traces',
headers={
'Authorization': 'Basic ' + base64.b64encode(b'pk-lf-xxx:sk-lf-xxx').decode()
}
)
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)
# Now create spans as usual - they appear in Langfuse automatically
tracer = trace.get_tracer('my-llm-app')
with tracer.start_as_current_span('rag-query') as span:
span.set_attribute('llm.model', 'gpt-4o')
span.set_attribute('llm.prompt_tokens', 500)
result = rag_pipeline(query)クイックチェック
このレッスンで学んだ、モデルに依存しないオブザーバビリティのためのLangfuseについて、理解度を確認しましょう。
レッスンのまとめ
このレッスンでは、次のことを学びました。Langfuseは、トレース・スパン・Generationからなる階層型データモデルを使って、オープンソースでモデルに依存しないLLMオブザーバビリティを提供します。@observe()デコレーターを使うと、最小限の変更で既存コードを計測できます。また、コスト追跡、ユーザーフィードバックのスコア、自動LLM-as-Judgeスコアリングにより、Langfuseは完全な品質監視プラットフォームとして機能します。次は、レイテンシ、コスト、品質低下に対するアラートを設定します。
AI チューターと学ぶ Python — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 30
- レッスン
- 120
よくある質問
「モデルに依存しない可観測性のためのLangfuse」レッスンは無料ですか?
はい。「モデルに依存しない可観測性のためのLangfuse」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Engineering Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Engineering Academyコースには全4レッスンが含まれています。
「モデルに依存しない可観測性のためのLangfuse」で何を学びますか?
あらゆるLLMプロバイダーで動作するオープンソースの代替手段としてLangfuseを統合し、検索やツール呼び出し用のカスタムスパンを取得して、コスト追跡ダッシュボードを設定します。 ブラウザで直接実行するハンズオンコードでAI Engineering Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Engineering Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Engineering Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「モデルに依存しない可観測性のためのLangfuse」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Engineering Academyレッスンでコードを書いて実行できますか?
はい。すべてのAI Engineering Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- LLMアプリのデバッグが難しい理由
- LangSmithによるトレーシング
- モデルに依存しない可観測性のためのLangfuse
- レイテンシ、コスト、品質低下へのアラート