top of page

検索結果

空の検索で33件の結果が見つかりました。

  • Agent Development Kit (ADK) のエージェント評価を試してみた!

    最近話題の Google 製 AI エージェントフレームワーク「Agent Development Kit (ADK)」を触ってみました! Gemini モデルとの連携がしやすく、柔軟なエージェント開発が可能とのことで、期待が高まります。エージェントが自律的にツールを使うのは凄いですが、ちゃんと意図通り動くか、修正で壊れないかを確認する「評価」も重要ですよね。 そこで今回は、ADK のセットアップからエージェント作成、そしてそのエージェントを「評価」機能でテストするところまで、一通り試してみた記録をまとめます。 公式ドキュメント : 事前準備の参考記事 : ( 事前準備はこちらの記事を参考にしました ) 1. 環境セットアップ まずはローカル環境(Mac)でプロジェクトを準備します。パッケージマネージャーには uv を使用しました。 Bash # プロジェクトディレクトリ作成と移動 (Python 3.12.9 を指定) uv init -p 3.12.9 adk-work cd adk-work # ADK パッケージのインストール # (評価機能も使うため、[eval] 付きでインストールする) uv add "google-adk[eval]" google-adk[eval] とすることで、評価に必要な追加ライブラリ (pandasなど) も一緒にインストールされます。 2. エージェントプロジェクトの作成 参考記事に沿って、天気 (get_weather) と時刻 (get_current_time) を取得するツールを持つエージェント (multi_tool_agent) を作成します。 ディレクトリ・ファイル構成: Bash mkdir multi_tool_agent touch multi_tool_agent/{__init__.py,agent.py,.env} tree -a multi_tool_agent/ 実行結果: multi_tool_agent/ ├── .env ├── __init__.py └── agent.py ファイルの内容: multi_tool_agent/__init__.py : from . import agent multi_tool_agent/agent.py のコードを記述します。 import datetime from google.adk.agents import Agent from zoneinfo import ZoneInfo def get_weather(city: str) -> dict: """特定の都市の現在の天気情報を取得する。 Args: city (str): 天気情報を取得したい都市名。英語で。 Returns: dict: ステータスと結果またはエラーメッセージ。 """ if city.lower() == "new york": return { "status": "success", "report": ("ニューヨークの天気は晴れです。" "気温は25度(41°F)です。"), } else: return { "status": "error", "error_message": f"{city}の天気情報は利用できません。", } def get_current_time(city: str) -> dict: """特定の都市の現在時刻を取得する。 Args: city (str): 天気情報を取得したい都市名。英語で。 Returns: dict: ステータスと結果またはエラーメッセージ。 """ if city.lower() == "new york": tz_identifier = "America/New_York" else: return { "status": "error", "error_message": (f"{city}のタイムゾーン情報は利用できません。"), } tz = ZoneInfo(tz_identifier) now = datetime.datetime.now(tz) report = f'{city}の現在時刻は {now.strftime("%Y-%m-%d %H:%M:%S %Z%z")}です。' return {"status": "success", "report": report} root_agent = Agent( name="weather_time_agent", model="gemini-2.0-flash-exp", description="任意の都市の時刻と天気に関する質問に答えるエージェントです。", instruction="私は指定された都市の時刻や天気に関する質問に答えることができます。", tools=[get_weather, get_current_time], ) 3. モデル接続の設定 (.env ファイル) LLM (Gemini) への接続情報を .env ファイルに記述します。Google AI Studio か Vertex AI かで設定内容が異なります。 Google AI Studio: GOOGLE_GENAI_USE_VERTEXAI="False" GOOGLE_API_KEY="YOUR_API_KEY_HERE" Vertex AI: GOOGLE_CLOUD_PROJECT="your-gcp-project-id" GOOGLE_CLOUD_LOCATION="your-region" # 例: us-central1 GOOGLE_GENAI_USE_VERTEXAI="True" (Vertex AI 利用時は事前の API 有効化、gcloud auth login が必要) 今回は Vertex AI  を使用しました。 4. エージェントを実行してみる (Web UIでの基本動作確認) まずはエージェントがちゃんと動くか、Web UI で確認します。プロジェクトルート (adk-work) で以下を実行。 Bash uv run adk web ブラウザで http://localhost:8000  にアクセスし、エージェント multi_tool_agent を選択します。 チャットで「ニューヨークの天気は?」などと尋ねると、エージェントがツールを使って応答してくれるはずです。右側のページで詳細な動作(LLM とのやり取り、ツール実行)も確認できます。これでエージェントが基本動作することは確認できました。 5. エージェント評価の必要性 手動での動作確認も大事ですが、エージェントが複雑になったり、修正を繰り返したりすると、「毎回同じテストを手動でやるのは大変」「意図しないところで動作が変わっていないか心配」となります。ここで ADK の 評価機能 の出番です。 ADK ドキュメントによると、LLM エージェント評価では「最終出力」だけでなく、そこに至る「軌跡(ツールの使い方など)」も重要であり、これを自動でチェックできる仕組みが提供されています。 6. 評価シナリオ (評価セット) の準備 評価のために、「お手本」となるシナリオと期待される動作を定義した 評価セットファイル (.evalset.json)  を用意します。ファイル名は任意(例: multi_tool_agent_test.evalset.json)です。Web UI で対話したセッションを保存して生成することも、手動で作成することも可能です。 以下のファイルでは、期待されるツール使用と参照応答 (reference) を定義しています。 (ファイル名例: multi_tool_agent_test.evalset.json) JSON [ { "name": "test", "data": [ { "query": "おはよう!", "expected_tool_use": [], "reference": "おはようございます! お手伝いできることはありますか? " }, { "query": "ニューヨークの現在の時間は?", "expected_tool_use": [ { "tool_name": "get_current_time", "tool_input": { "city": "New York" } } ], "reference": "ニューヨークの現在時刻は...です。..." }, { "query": "ニューヨークの天気は?", "expected_tool_use": [ { "tool_name": "get_weather", "tool_input": { "city": "New York" } } ], "reference": "ニューヨークの天気は晴れです。..." } ], "initial_session": { "state": {}, "app_name": "multi_tool_agent", "user_id": "user" } } ] 7. 評価の基準 ( ADK ドキュメントより ) ADK はエージェントの実際の動作と評価セットの期待値を比較する際、以下の基準(メトリクス)とデフォルトの閾値を使用します。 tool_trajectory_avg_score : ツール使用履歴の一致度。デフォルト閾値 1.0  (完全一致)。 response_match_score : 最終応答と reference の類似度。デフォルト閾値 0.8  (ある程度似ていればOK)。 ちなみに、これらのデフォルト閾値は、必要であれば 以下のようなtest_config.json という設定ファイルを作成して各エージェントディレクトリ配下に置くことでカスタマイズすることも可能です。 { "criteria": { "tool_trajectory_avg_score": 1.0, "response_match_score": 0.8 } } 8. Web UI で評価を実行! 準備ができたので、Web UI で評価を実行します。 (もし adk web が停止していれば再起動) Web UI で multi_tool_agent を選択。 右側の「評価 (Eval)」タブを開く。 「評価セット (Eval Set)」ドロップダウンから、 自分で準備した評価セットファイル (multi_tool_agent_test)を選択。 評価ケース test が表示されるのでチェックを入れて、「Run Evaluation」ボタンをクリック! 実行後、結果が表示されます。 今回は無事「PASS」しました! また、ターミナルを見てみると詳細が出力されると思います。 ( ※注意 :応答一致 (response_match_score): 筆者が実験をしてみると、評価セットの reference に明らかに正しくない応答を設定し、さらに test_config.json で 値を明示的に指定しても、評価全体の結果は1となり「PASS」のままでした。) Agent Development Kit の評価まとめ 今回は、ADK のセットアップからエージェント作成、そして評価機能を使ったテストまでを一通り体験しました。評価セットによる自動評価は、特にエージェントのツール利用手順(軌跡)が期待通りかを確認する上で有効だと感じました (tool_trajectory_avg_score は意図通り機能しているようです)。これにより、回帰テストの一部は自動化できそうです。 一方で、 最終応答のテキスト内容 (reference) との比較 (response_match_score) については、今回試した範囲では、期待通りに最終的な評価結果 (PASS/FAIL) に影響を与えない場面がありました。  明らかに異なる応答を期待値としても、評価全体が PASS してしまうケースがあり、test_config.json で基準を明示的に設定しても結果は変わりませんでした。この挙動については、さらなる調査や ADK の今後のバージョンでの改善が必要かもしれません。 このように、現状では特に 応答内容の自動評価に関しては注意が必要 ですが、ツール利用の正確性を担保する目的など、 部分的には  ADK の評価機能は開発の助けになる可能性はあります。ADK の評価機能を利用する際は、現状の挙動をよく理解・検証した上で、目的に合わせて活用するのが良さそうです。皆さんもぜひ試してみてください!

  • Langfuse で LLM 評価を効率化!活用方法徹底解説

    1.初めに 近年、AI 技術、特に大規模言語モデル(LLM)の進化は目覚ましく、様々な分野での活用が進んでいます。しかし、LLM をビジネスに適用する上で、その品質をどのように評価するかが大きな課題となっています。 これまでの LLM の評価は、主に「出力結果の目視確認」や「ユーザーフィードバック」に頼ってきました。この従来のアプローチには、以下のような課題があります 評価基準の曖昧さ 何をもって良い評価とするのかが評価者によって異なり、客観的な評価が困難 個人の価値観や経験によって、評価結果にばらつきが生じます 評価の多面性 正確性、簡潔性、論理的構成など、複数の観点からの評価が必要で 多角的な視点での評価が必要となり、総合的な判断が難しくなります 実装の複雑さ テストデータの準備、評価項目の設定、結果の可視化など、多くの実装工程が必要 評価用データセットの作成やプロンプトの作成に多くの工数がかかります このような課題を解決し、効率的かつ効果的な LLM 評価を実現するために、注目されているのが Langfuse です。 Langfuse は、LLM システムの開発から運用までをサポートする包括的なプラットフォームです。本記事では、特に LLM の評価機能に焦点を当て、Langfuse がどのように LLM 開発を効率化するのか、具体的な活用方法を解説します。 2. Langfuseによる評価機能 Langfuse は、これらの課題を解決するために、以下の2つの主要な評価機能を備えています。※セルフホスティングの場合はPro/Enterprise版を利用する必要あり Human Annotate: 人間の手によるラベル付けを可能にします。開発者以外のドメインエキスパートが評価する場合に特に有効です。 LLM as a Judge: LLM を評価者として活用し、評価用プロンプトに基づいて自動で評価を行います。これにより、評価の客観性と効率性を高めることができます。 Langfuse の評価機能を利用することで、評価軸を明確に定義し、客観的な評価を行うことが容易になります。また、評価結果は UI 上で可視化され、トレースと紐付けられるため、問題点を特定しやすく、効率的な改善サイクルを実現できます。 3. RAGASとLangfuseの評価アプローチの違い RAGシステムの評価フレームワークとして、RAGASは広く使用されています。RAGASは汎用的な評価フレームワークとして、検索精度や応答の関連性など、RAGシステムの基本的な性能を測定するために設計されています。しかし、実際のビジネス応用においては、以下のような制約があります RAGASの制約 事前に定義された評価指標に基づく標準的な評価 ドメイン固有の要件への対応が限定的 評価基準の詳細な調整が困難 これに対し、Langfuseは実務での活用に焦点を当てた評価プラットフォームとして、以下のような特徴があります Langfuseの特徴 ドメイン固有の評価基準を柔軟に設定可能 評価プロンプトのカスタマイズと継続的な改善 具体的な評価例 金融分野での規制要件への適合性評価 医療分野での専門用語の正確性評価 このように、RAGASとLangfuseはそれぞれ異なる用途に適しています。RAGASはRAGシステムの基本性能を標準的に評価する際に有効で、Langfuseは実際のビジネス要件に応じた詳細な評価が必要な場合に適しています。               RAGASとLangfuseの主な違い RAGAS Langfuse プロンプトを作成する必要性 必要なし 必要あり 各評価用のテンプレートはある 評価用プロンプトの可視化 Githubから確認 LangfuseのUI上で確認 評価のカスタマイズ性 ほぼなし 評価基準を作成・修正が容易に可能 実装方法 ソースコードで実装 UIで設定(別途実装も可能) 日本語での評価制度 (個人的印象) 不安定 安定するように評価用プロンプトの修正が可能 Langfuse を用いた評価の実践 データセットの作成 Langfuse では、トレースデータから評価用データセットを簡単に作成できます。UI 上で必要なトレースを選択し、「Add to dataset」ボタンをクリックするだけで、データセットとして利用できます。 また、データセット用のトレースをあらかじめ作成しておけば、より柔軟なデータセット作成が可能です。ユーザの入力だけ取得をして、データセットとして保管しておきたい場合などに有用です。 方法としては以下のような、関数を1つ作成するだけです。 例:(ユーザの入力だけほしい場合) ## python @observe() async def trace_dataset(): langfuse_context.update_current_observation(input=ユーザの入力 ,output="") テストデータセットの選定と管理 Langfuse では、作成したデータセットを「Queue」という仕組みで管理します。トレースを Annotation の Queue に入れ、ドメインエキスパートが Queue を仕分けることで、適切なテストデータを選定できます。これにより、評価に必要なデータだけを効率的に管理し、テストの精度を高めることができます。            トレースからqueueに入れる画面             Human Annotateの画面(仕分け画面) LLM as a Judge の利用方法 Langfuse の LLM as a Judge 機能を利用すると、データセットの選定も効率的に行えます。あらかじめ LLM as a Judge の設定をしておけば、トレースには自動でスコアが入力されるため、怪しい値をチェックすることで、より精度の高いデータセットを選定できます。 LLM as a Judge設定画面 LLM as a Judge設定画面(トレースの設定) テスト実行と結果の可視化 選定したデータセットを用いて、Langfuse 上でテストを実行します。テストの際には、モデルやプロンプトを自由に選択でき、複数の評価基準を設定することも可能です。テスト結果は、ダッシュボードで可視化され、各データポイントの評価スコア、入出力、トレースなどの情報を一目で確認できます。これにより、システムの改善点を効率的に特定し、迅速な改善サイクルを回すことが可能です。 プロンプト実験の設定画面 Langfuseを活用した評価サイクル 以上の機能を用いることで以下のような評価・改善サイクルが実現できます。 LLMの出力結果をトレースし、Langfuseで可視化 Annotation の Queueに入れて、ドメインエキスパートの人に出力結果を判断してもらう & LLM as a Judgeで各評価項目に対してスコアを出力させる 2で悪い結果の原因追及をして、入力をデータセットに格納(オプションで期待する出力もあると良い) プロンプトを変更する プロンプト実験を行い、前回のプロンプトの出力との違いについてLangfuse上で結果を可視化し原因の追求 5. まとめ Langfuse は、LLM システムの開発から運用までをカバーする包括的なプラットフォームです。特に評価機能においては、以下のような作業を UI 上で完結させることができます。 評価の事前準備 評価用プロンプトの作成 評価基準の定義 ドメイン固有の要件への対応 テストの効率化 トレースからの自動データセット作成 Human AnnotateとLLM as a Judgeの併用 複数の評価軸でのテスト実行 結果の可視化と改善 定量的なスコア表示 トレースを活用した原因追求 プロンプト実験による継続的な改善 現状では、Langfuseはトレースやモニタリング機能の利用がメインとなっていますが、本記事で紹介した評価機能を活用することで、LLM開発のライフサイクル全体を効率的に管理することが可能です。評価から改善までのサイクルを一つのプラットフォームで完結できる点は、開発効率を大きく向上させる要因となるでしょう。 ぜひ Langfuse を導入し、効率的なLLM開発の実現を目指してみてください。

  • [LLMOps] プロンプト管理の課題

    はじめに:生成AIが抱える困難とプロンプト 生成AIアプリケーションの開発は、従来のソフトウェア開発とは異なる難しさがあります。 その一つが、 生成AIの出力の不安定さ です。そしてこの不安定さに大きく関わっているのが、 プロンプト です。生成AIは、人間が与える指示、つまりプロンプトに基づいて動作しますが、プロンプトが適切でなければ、生成AIはその能力を十分に発揮できません。 しかし、 プロンプトの重要性は認識されつつも、その管理は後回しにされがち です。多くの開発現場では、プロンプトがコードの中に直接埋め込まれ、場当たり的に修正されているのが現状ではないでしょうか。(少なくとも、筆者は多くそのような現場を見聞きしています) LLMOps のプロンプト管理とは?:なぜ必要で、何が問題なのか プロンプト管理とは、生成AIへの指示(プロンプト)を体系的に作成、テスト、改善、保存、共有するプロセス全体を指します。 プロンプト管理の目的 は、主に以下の4つです。 品質向上: 生成AIの出力の品質を向上させ、安定させる。 一貫性確保: 同じプロンプトからは常に同じ品質の出力が得られるようにする。 効率化: プロンプトの作成、テスト、改善のサイクルを効率化する。 再利用性向上: 良いプロンプトをチーム内で共有し、再利用できるようにする。 これらの目的を達成するために、プロンプトを適切に管理する必要があります。 しかし、現状では以下のような問題点があります。 問題点1:コード埋め込みプロンプトの罠 開発時には、作業を優先させることに意識がいってしまい、プロンプトはプログラムコードの中に直接埋め込まれてしまいがちで、結果として以下のような問題を引き起こします。 保守性の低下: プロンプト変更のたびにアプリケーションと一緒に テスト, デプロイのパイプラインなどを回すため、とにかく手間や時間ががかかる。 再利用性の低下: 他のアプリケーションやチームメンバーがプロンプトを再利用しにくい。 可読性の低下: コードとプロンプトが混在し、コード全体の読みやすさが下がる。 バージョン管理の困難: プロンプトの変更履歴が追跡しにくく、問題発生時の原因特定が難しい。 上記のうち特に保守性の低下は致命的であり、開発,修正,テストというサイクルに無駄な工数や待ち時間などが発生してしまいます。 Prompt をコードに埋め込むとコードと同じ工程でリリースをすることになるが、その効果は特になく時間と手間だけが発生する 問題点2:Gitやデータベースでの管理の限界 プロンプトをコードから分離するためには、Gitやデータベースで管理する方法も考えられます。それらの特徴を大まかにまとめるたものが以下の表です。 プロンプト管理:データベース vs. Git 項目 データベース Git 対象ユーザー システム開発者 システム開発者 (あるいはGit作業についてトレーニングを受けた方) 利用スキル要件 DB設計・運用、SQL、加えて何らかの管理用アプリケーションが必要になるケースがある Git操作(コミット、ブランチ、マージ等) データ形式 構造化データ(プロンプト、メタデータ) 非構造化データ(主にテキスト) バージョン管理 履歴記録可能(実装依存)、差分比較は困難 履歴記録・追跡が容易、過去バージョンへ復元可、差分比較も容易 共有・コラボ 共有可能(同時アクセス、排他制御はDBによる)、専門知識必要、リアルタイム共同編集は困難 共有容易(リモートリポジトリ)、プルリクエストでレビュー可、権限管理可、ただし非技術者には難解 テスト・評価 テスト結果保存は要開発、自動評価連携は困難、プロンプトと出力結果の紐付けについても開発が必要 テスト自動化はCI/CD連携でアプリケーションと一体で実施 (プロンプト単体の評価は不可能)、自動での評価機能なし、出力結果との紐付け困難 検索性・再利用性 属性検索可、自然言語特性の完全な表現は困難 Git機能だけでは不十分(別途プロンプトライブラリ等必要) この表からわかるように、Gitとデータベースはそれぞれプロンプト管理に活用できる側面があるものの、多くの課題が残ります。 また プロンプトは本来はシステム開発者ではなく、生成AIのアウトプットの良し悪しが分かる 業務エキスパート (ドメインエキスパート) によって修正、テスト、評価をするべき にもかかわらず、両者ともシステム開発者の手により管理されることになります。 プロンプトがコードと一体化することにより、システム開発者はプロンプトの責任を持たざるを得ないが、正解が分からない悲劇 コードにプロンプトを取り込むことにより、生成AIのシステム開発者の管理スコープはプロンプトに及びます。なぜならば、変更できるのがシステム開発者だけだからです。 しかし生成AIシステムの品質を追求するためには、組織のあるべき姿として、コード管理はシステム開発者が実施し、プロンプトは生成AIに出して欲しい期待値を知っている業務エキスパートの手に委ねるべきなのです。 まとめ:プロンプト管理の課題を克服するために 生成AIアプリケーションの品質は、プロンプトの品質に大きく左右されます。しかし、プロンプトはコードに埋め込まれたり、Gitやデータベースで十分に管理されていなかったりすることが多く、様々な問題を引き起こしています。 これらの問題を解決し、生成AIのポテンシャルを最大限に引き出すためには、 プロンプト管理の仕組みをアプリケーション開発者以外でも対応できるよう整備し、プロンプト管理とテスト - 改善のプロセスを一元的に確立させることが不可欠 です。 [ 次回の記事 ] では、これらの課題を解決するための実例を「Langfuse」と、Langfuseを活用したプロンプト管理を通して詳しく解説します。

  • Google CloudでLangfuse v3の構築手順(推奨設定/GKE)

    はじめに GAOの遠矢です。普段はLLMアプリケーションの開発を主にしております。 このガイドでは、LangfuseというLLMOpsの基盤となるツールを Google Cloud 上で セルフホスティングする手順を紹介します。 Google Cloud 上のKubernetes (GKE) でLangfuse v3を安全かつ推奨される構成でデプロイする手順を解説します。 Langfuse v2からv3への主な変更点 V3では以下のような重要な改善が行われています アーキテクチャの最適化 キューに入れられたトレースの取り込み トレースはバッチ処理され、S3に直接保存 APIキーのキャッシュング Redisを活用した高速なAPI認証 プロンプトのキャッシュ(SDK・API) リードスルーキャッシュによる応答時間の改善 OLAPデータベース(ClickHouse)の採用 分析処理の高速化 信頼性の向上 S3/Blobストレージを活用したイベントの回復可能性 バックグラウンド移行のサポート マルチモーダルトレースのサポート コンポーネント構成 アプリケーションコンテナ(Web・Worker) ストレージコンポーネント(Postgres, ClickHouse, Redis/Valkey, S3/Blob) オプショナルなLLM API/ゲートウェイ 注記: この手順はLangfuse v3のデプロイに焦点を当てています。v2のデプロイについては、v2のドキュメントを参照してください。 注意事項: 本番環境で使用する前に、セキュリティとパフォーマンスを考慮して構成を見直すことを強く推奨します。 システム要件と構成 アーキテクチャ図 推奨構成 GKE(コンテナアプリケーション) 2つのCPUと4 GB の RAM 高可用性を実現するには、Langfuse Web コンテナのインスタンスを少なくとも 2 つ Cloud SQL(PostgreSQL) 特に指定なし Redis 1GB以上 ClickHouse: 3レプリカ構成 Cloud Storage(S3) 特に指定なし 注意事項: 今回はClickhouseをGKE上に構築する場合の手順のため、GKEノード(GCE)のマシンスペックが低いとClickhouseを構築できない可能性があるためご注意ください。 構築手順 本手順では、主にターミナルを利用して構築を行います。 構築準備 まず、Google Cloudプロジェクトの設定から始めます。 以下のコマンドでプロジェクトを設定します。 gcloud config set project [YOUR_PROJECT_ID] ネットワークインフラの構築 セキュアな環境を構築するため、専用のVPCネットワークとサブネットを作成します。 これにより、リソース間の安全な通信が可能になります。 # VPCネットワークの作成 gcloud compute networks create langfuse-network --subnet-mode=custom # サブネットの作成 gcloud compute networks subnets create langfuse-subnet \ --network=langfuse-network \ --region=asia-northeast1 \ --range=10.0.0.0/20 # VPCピアリングの設定 gcloud compute addresses create google-managed-services-range \ --global \ --purpose=VPC_PEERING \ --prefix-length=16 \ --network=langfuse-network gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=google-managed-services-range \ --network=langfuse-network # 内部通信用のファイアウォールルール gcloud compute firewall-rules create langfuse-allow-internal \ --network=langfuse-network \ --allow=tcp,udp,icmp \ --source-ranges=10.0.0.0/20 Kubernetesクラスターの構築 GKEクラスターを作成します。 本番環境では可用性を考慮して、複数のノードを配置することを推奨します。 gcloud container clusters create langfuse-cluster \ --network=langfuse-network \ --subnetwork=langfuse-subnet \ --region=asia-northeast1 \ --num-nodes=1~2 \ --machine-type=e2-standard-2 \ --enable-ip-alias # 認証設定 gcloud container clusters get-credentials langfuse-cluster --region=asia-northeast1 PostgreSQLの構築 PostgreSQLデータベースをCloud SQLで構築します。本番環境では十分なリソースと冗長性を確保することが重要です。 パスワード等は本来であれば、シークレット等で管理してください。 # PostgreSQL作成 gcloud sql instances create langfuse-postgres \ --database-version=POSTGRES_15 \ --tier=db-g1-small \ --region=asia-northeast1 \ --root-password=[YOUR_ROOT_PASSWORD] \ # 今回設定する箇所は特にないので任意で --database-flags=max_connections=100 \ --network=langfuse-network \ --no-assign-ip # データベース作成 gcloud sql databases create langfuse --instance=langfuse-postgres # ユーザの作成 gcloud sql users create langfuse --instance=langfuse-postgres --password=langfuse1234 また、プライベートIPはこの後Langfuse側で設定する必要があるのでメモしておいてください。 # プライベートIPの取得 gcloud sql instances describe langfuse-postgres \ --format="get(ipAddresses[0].ipAddress) Redisの構築 Redisをマネージドサービスである、Memorystore for Redisを利用して構築を行います。 しかし、コスト等の兼ね合いがある場合マネージドサービスを利用せずコンテナ上で構築することも可能です。 # Redisインスタンスの作成 gcloud redis instances create langfuse-redis \ --size=1 \ --region=asia-northeast1 \ --redis-version=redis_7_0 \ --network=langfuse-network \ --enable-auth \ --redis-config maxmemory-policy=noeviction Redisでは、認証用の文字列(REDIS_AUTH)、ホスト(REDIS_HOST)、ポート(REDIS_PORT)をこの後Langfuse側で設定する必要があるので、メモしておいてください # Redis認証文字列の取得 gcloud redis instances get-auth-string langfuse-redis --region=asia-northeast1 # Redisホストの取得 gcloud redis instances describe langfuse-redis \ --region=asia-northeast1 \ --format="get(host)" # Redisポートの取得 gcloud redis instances describe langfuse-redis \ --region=asia-northeast1 \ --format="get(port)" Cloud Storage (S3) の 構築 # バケットの作成 gcloud storage buckets create gs://$BUCKET_NAME \ --location=asia-northeast1 HMAC キーの作成手順 Cloud Storage > 設定 > 相互運用性タブに移動 サービスアカウント or ユーザーアカウントを選択しHMACキーを作成します。 アクセスキーとシークレットを安全に保存(これらは後でLangfuseの設定で使用) ClickHouseの 構築 今回はGKE上にClickHouseをデプロイする手法で行います。 # Helmのインストール curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash # Helmリポジトリの追加 helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update 次に以下のclickhouse-values.yamlを作成します。 shards: 1 replicaCount: 3 auth: username: default password: changeme resourcesPreset: large persistence: size: 100Gi shards: シャード数(この場合は1) replicaCount: レプリカ数(本番では3以上推奨) YAML作成後、Clickhouseのデプロイを行います。 helm install clickhouse bitnami/clickhouse \ -f clickhouse-values.yaml \ --namespace default その後以下のコマンドで、正常に起動することを確認します。 # Podの状態確認 kubectl get pods | grep clickhouse # サービスの確認 kubectl get svc -l app.kubernetes.io/name=clickhouse # ログの確認 kubectl logs clickhouse-0 # デプロイされたリソース一覧の確認 kubectl get all -l app.kubernetes.io/name=clickhouse . Kubernetes(helm)でのLangfuseのデプロイ # Langfuseリポジトリのクローン git clone https://github.com/langfuse/langfuse-k8s.git cd langfuse-k8s/charts/langfuse git checkout lfe-1348-v3-chart リポジトリをクローン後、以下の内容でlangfuse-values.yamlを作成してください。 また、その際に変数等は適宜変更してください。 langfuse-values.yaml replicaCount: 1 image: repository: langfuse/langfuse pullPolicy: Always tag: 3 imagePullSecrets: [] nameOverride: "" fullnameOverride: "" langfuse: port: 3000 nodeEnv: development next: healthcheckBasePath: "" nextauth: url: "http://localhost:3000" secret: "openssl rand -base64 32で作成" salt: "openssl rand -base64 32で作成" telemetryEnabled: true nextPublicSignUpDisabled: false enableExperimentalFeatures: true extraContainers: [] extraVolumes: [] extraInitContainers: [] extraVolumeMounts: [] web: replicas: 1 worker: replicas: 1 additionalEnv: - name: "LANGFUSE_LOG_FORMAT" value: "json" # Experimental v3 feature flags - name: "LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES" value: "true" - name: "ENCRYPTION_KEY" value: "openssl rand -hex 32で作成" - name: "LANGFUSE_ASYNC_INGESTION_PROCESSING" value: "true" - name: "LANGFUSE_ASYNC_CLICKHOUSE_INGESTION_PROCESSING" value: "true" - name: "LANGFUSE_READ_DASHBOARDS_FROM_CLICKHOUSE" value: "true" - name: "LANGFUSE_READ_FROM_POSTGRES_ONLY" value: "false" - name: "LANGFUSE_RETURN_FROM_CLICKHOUSE" value: "true" # Database connections - name: DATABASE_URL value: "postgresql://langfuse:langfuse1234@[DB_IP]:5432/langfuse" - name: "REDIS_HOST" value: "[REDIS_HOST]" - name: "REDIS_PORT" value: "[REDIS_PORT]" - name: "REDIS_AUTH" value: "[REDIS_AUTH]" - name: "CLICKHOUSE_URL" value: "http://clickhouse:8123" - name: "CLICKHOUSE_MIGRATION_URL" value: "clickhouse://clickhouse:9000" - name: "CLICKHOUSE_USER" value: "default" - name: "CLICKHOUSE_PASSWORD" value: "changeme" - name: CLICKHOUSE_CLUSTER_ENABLED value: "false" # Cloud Storage settings - name: "LANGFUSE_S3_EVENT_UPLOAD_ENABLED" value: "true" - name: "LANGFUSE_S3_EVENT_UPLOAD_BUCKET" value: "[BUCKET_NAME]" - name: "LANGFUSE_S3_EVENT_UPLOAD_REGION" value: "auto" - name: "LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID" value: "[HMAC_ACCESS_KEY]" - name: "LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY" value: "[HMAC_SECRET_ACCESS_KEY]" - name: "LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT" value: "https://storage.googleapis.com" - name: "LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE" value: "true" - name: "LANGFUSE_S3_EVENT_UPLOAD_PREFIX" value: "events/" serviceAccount: create: true annotations: {} name: "" podAnnotations: {} podSecurityContext: {} securityContext: {} service: enabled: true type: NodePort port: 3000 targetPort: 3000 ingress: enabled: false # ローカル環境では無効化 resources: {} autoscaling: enabled: false nodeSelector: {} tolerations: [] affinity: {} postgresql: deploy: false # 外部PostgreSQLを使用 auth: username: "langfuse" password: "langfuse1234" database: "langfuse" clickhouse: deploy: false # 外部Clickhouseを使用 valkey: deploy: false minio: deploy: false # 外部ストレージを使用 extraManifests: [] 主に変更する箇所は以下です。 パラメータ 作成方法/説明 nextauth.secret openssl rand -base64 32で作成 salt openssl rand -base64 32で作成 ENCRYPTION_KEY openssl rand -hex 32で作成 [DB_IP] PostgreSQLデータベースのIPアドレス [REDIS_HOST] Redisサーバーのホスト名 [REDIS_PORT] Redisサーバーのポート番号 [REDIS_AUTH] Redisの認証パスワード [BUCKET_NAME] Cloud Storageのバケット名 [HMAC_ACCESS_KEY] Cloud StorageアクセスのHMACアクセスキー [HMAC_SECRET_ACCESS_KEY] Cloud StorageアクセスのHMACシークレットキー LANGFUSE_EE_LICENSE_KEY Langfuse Enterprise プランのライセンスキー(オプション) ない場合は特に追加の必要なし 以下のコマンドでhelmでLangfuseをlangfuse-values.yamlに沿って作成します。 # Langfuseのデプロイ helm dependency update helm install langfuse . -f langfuse-values.yaml デプロイができたら、以下のコマンドでログとポッドの状態を確認します。 # podの状態確認 kubectl get pods -l app.kubernetes.io/instance=langfuse # ログの確認 kubectl logs -f deployment/langfuse-web kubectl logs -f deployment/langfuse-worker どちらとも起動することを確認したら、ポートフォワーディングをして、localhost:3000でLangfuseのログイン画面が出力されることを確認します。 ポートフォワーディングのコマンド # ポートフォワーディングの設定 kubectl port-forward svc/langfuse-web 3000:3000 その後、トレースなどを行い動作に問題がないか確認したらデプロイ完了です。 応用編 (外部IP付与 GCLB) GoogleのGlobal Load Balancerを利用して、HTTPS通信を可能にします。 まずは、Google マネージドのSSL証明書を作成します。 以下のmanaged-cert.yamlを作成します。 apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: langfuse-cert spec: domains: - YOUR_DOMAIN # 実際のドメインに変更 その後マネージド証明書の適用を行います。 # マネージド証明書の適用 kubectl apply -f managed-cert.yaml 次に外部IPアドレスを予約しておきます # 静的外部IPアドレスの予約 gcloud compute addresses create langfuse-ip --global ここで予約したIPアドレスを DNS の A レコードとして設定してください。 次に、langfuse-values.yamlを更新します。 主な変更点としては環境変数の更新・追加とIngressの追加を行います。 # 主な更新箇所のみ抜粋 langfuse: nextauth: url: "https://YOUR_DOMAIN" # 外部アクセス用のドメインに更新 additionalEnv: - name: "LANGFUSE_CSP_ENFORCE_HTTPS" value: "true" # HTTPSを強制的に使用 # 新規追加のIngress設定 ingress: enabled: true annotations: kubernetes.io/ingress.global-static-ip-name: langfuse-ip networking.gke.io/managed-certificates: langfuse-cert kubernetes.io/ingress.class: "gce" kubernetes.io/ingress.allow-http: "false" hosts: - host: YOUR_DOMAIN paths: - path: / pathType: Prefix Langfuseの更新 # Langfuseの更新 helm upgrade langfuse . -f langfuse-values.yaml 確認コマンド # 証明書の状態確認 kubectl describe managedcertificate # AtiveになったらOK # ロードバランサーの確認 kubectl get ingress # HOST名が設定したドメイン名、アドレスが langfuse-ipの値になってたらOK # GUIでGCLBが作成できるかどうかも確認 以上の設定が完了したら、https://YOUR_DOMAINにアクセスして、LangfuseUIにログインできたら成功です。 トレースなどができるか確認してみてください。 できない場合は helm unistallなどをしてください また、以下の画面はenterpriseEditionのライセンスキーの有効化を行なっているため、左上がv3.2.0 EEとなっています。 EEとなっており、Playground等の機能も画面に出力されている状態になっております。 クリーンアップ 必要に応じて、以下の手順でリソースを削除します # Langfuseの削除 helm uninstall langfuse helm uninstall clickhouse # GKEクラスターの削除 gcloud container clusters delete langfuse-cluster \ --region=asia-northeast1 \ --async # Cloud SQLインスタンスの削除 gcloud sql instances delete langfuse-postgres # Redisインスタンスの削除 gcloud redis instances delete langfuse-redis \ --region=asia-northeast1 # Cloud Storageバケットの削除 gsutil rm -r gs://$BUCKET_NAME # ファイアウォールルールの削除 gcloud compute firewall-rules delete langfuse-allow-internal # VPCピアリング接続の削除 gcloud services vpc-peerings disconnect \ --service=servicenetworking.googleapis.com \ --network=langfuse-network # 予約したIPレンジの削除 gcloud compute addresses delete google-managed-services-range \ --global # サブネットの削除 gcloud compute networks subnets delete langfuse-subnet \ --region=asia-northeast1 # VPCネットワークの削除 gcloud compute networks delete langfuse-network トラブルシューティング Redis接続エラーについて "Redis connection error: ERR unknown command 'client'"という警告は、Google CloudのMemoryStoreの制限によるものです。 この警告は表示されても、Redisとの接続自体は正常に行われています。 証明書のプロビジョニング マネージド証明書のプロビジョニングには数分から数十分かかる場合があります。 kubectl describe managedcertificate で状態を確認できます。 注意事項 すべてのパスワードとシークレットは適切に管理してください。 本番環境ではより強力なセキュリティ設定と、より多くのリソースを割り当てることを検討してください。 環境変数の値は実際の値に置き換えてください。 Langfuseの公式ドキュメントも参照し、最新の情報を確認してください。 最後に このガイドが、Google Cloud上でのLangfuse v3の安全なデプロイに役立つことを願っています。 また企業向けサポートとして、 ガオ株式会社 を通じてLangfuse ProおよびEnterpriseプランを日本円で購入し、日本語でサポートを受けることが可能です。 ご興味ある方は、contact@gao-ai.comまでご連絡ください。

  • Langfuseによるプロンプト管理 (前半) - 基本 & 管理編

    [ 前回の記事 ] では、プロンプト管理の重要性にくわえて、コード埋め込みやGit または データベースによる管理の課題について解説しました。今回は、それらの問題を解決すべく「Langfuse」を活用したプロンプト管理の方法を具体的に解説します。 Langfuseとは?:LLMの開発と運用に特化したオープンプラットフォーム Langfuseは、生成AIアプリケーションの開発や運用に特化したオープンソースのプラットフォームです。可視化やテストなど生成AIアプリケーションのライフサイクル全体を管理するものですが、今回は特にプロンプト管理に焦点を当ててご紹介をしていきます。 Langfuseによるプロンプト管理の主な特徴は以下のとおりです。 使いやすいUI: 直感的なインターフェースで、プロンプトの作成、編集、比較、テストが容易に行えます。 バージョン管理: 変更履歴を自動的に記録し、過去のバージョンとの比較やコピー、修正などが簡単に行えます。 詳細な分析: プロンプトのパフォーマンス(応答時間、コスト、品質スコアなど)を詳細に分析し、改善点を見つけやすくします。 柔軟な評価: LLM as a judge などによる自動評価指標に加えて、人間による評価 (Human Annotation) も組み合わせて、多角的にプロンプトを評価できます。 チームでの共有: プロンプトをチーム内で共有し、共同で作業できます。 実践!Langfuseによるプロンプト管理の具体的なステップ 前提: Prompt はLangfuse から取ってくる Langfuseを使うと、プロンプト管理はどのように変わるのでしょうか? まず前提としてアプリケーションコードに埋め込む形とは異なり、Prompt 本体は Langfuse に格納され、それをプログラム側から fetch する形となります。 アプリケーションはLangfuse に格納されているPrompt を取りに行き、適切なものを入手します。なお本番運用した際に都度取得をする必要は必ずしも無いので、TTL を設定してキャッシュする運用が現実的だと思います (デフォルト60 sec、0で即時反映)。 以下はPython のコード例です。極めてシンプルな実装が可能です。 この場合、wweという名前で管理されているPrompt をfetch してきます。 from langfuse import Langfuse # Initialize Langfuse client langfuse = Langfuse() prompt = langfuse.get_prompt("wwe") TTLを設定する場合や、特定のラベルのPrompt を取得したい場合は以下のようになります。ラベルについては後述します。 # TTL を 300に指定 prompt = langfuse.get_prompt("wwe", cache_ttl_seconds=300) # the-rock-is-cooking というラベルの Promptを取得 prompt = langfuse.get_prompt("wwe", label="the-rock-is-cooking") その他のオプションや記述例はLangfuse の公式ドキュメントに豊富な例が用意されていますので、参考にしてみてください。 URL: https://langfuse.com/docs/prompts/get-started 余談ですが、同サイトの右上にある Search 欄から、Ask AI (Cmd + k) で日本語で質問することも可能です。日本語でも精度が高いので、ぜひ使ってみてください。 さてこれから、実際のプロンプト管理を見ていきましょう。 Prompt の作成とバージョン管理 LangfuseのUI上では、直感的にプロンプトを直接作成・編集できます。 変更を加えるたびに、自動的に新しいバージョンが作成され、変更履歴が記録されます。 以下は プロンプト管理画面のサンプルです。 これは toyidea という名前のプロンプトで、右側で各バージョンを確認することができます。現在、Production に適用されているのは Version 2 のプロンプトです。 また、latest ラベルがついている Version 3 にはコメントがついており、"独自アイディアの追加プロンプト試行" とコメントがついています。併せて作業者もそれぞれ情報として付加されており、いつ誰が何のためにバージョンを変えたのかも非常に分かりやすくなっています。 ラベルについては最新のものには自動で latest がつきますが、この画像のように自分で任意の名前をつけ、前述のサンプルのように指定したものを fetch することもできます。 Version 間での詳細を比較したい場合には、GUI 上でDiff をすることもできます。相違部分がハイライトされおり、一目で差異が分かります。 またPrompt にはConfig として、以下のように任意の情報を持たせておくことができます。 モデル名, Temperature などをPrompt と一緒に取得することで、管理を一元化し、結果の整合性を維持することが期待されます。 例えばPrompt はLangfuse から持ってきても、コードの中で別のモデルを指定していると、テストしておいた結果と実際の結果は異なってしまいますが、管理をまとめることでそのような問題を防ぐことができ、コード自体もシンプルになります。 作成したプロンプト活用して、別のアプリケーションなどのために新たなプロンプトを作りたいこともあるでしょう。その際には、Duplicate 機能で任意のVersion だけ あるいはすべてのバージョンを含んでコピーを作ることができます。新たに Prompt を作る際に、どこからか Copy and Paste したり、新規で書く必要はありません。過去に作られている資産を使って作業を効率化することが可能なのです。 まとめ:Langfuseで簡単だけど効果的な プロンプト管理 他にも便利な機能がありますが、それらの紹介は別の機会に譲るとして、今回は一旦ここまでとしたいと思います。見ていただいた通り、Git でのオペレーションもSQL も不要かつ、非常に効果的な管理ができます。 本記事では、プロンプト管理の前提としてLangfuse で管理をする構成やどのように管理をされるのかという点について、いくつかの主要機能について説明をしていきました。 ぜひ参考にしていただき、プロンプトをハードコードする構成ではなく、LLM Ops を実現される一助になれば幸いです。 次回は Langfuse における実際のプロンプトの開発と評価について紹介します。 管理に加えて非常に有意義な機能を簡単に使うことができますので、ぜひご覧ください。

  • Langfuseによるプロンプト管理 (後半) - プロンプト開発&実験編

    [ 前回の記事 ] では、「Langfuse」を活用したプロンプト管理の方法を具体的に解説しました。Prompt をハードコードすることなく、Diff 、 Commit コメント 、Duplicate (複製) 、タグ などの機能を、直感的にエンジニアから非エンジニアまで幅広く使うことができますという内容です。まだご覧になっていない方は、ぜひチェックしてみてください。 さて今回は、Langfuseでのプロンプト開発と評価について触れていきたいと思います。 Langfuseによるプロンプトの新規作成 Langfuse にログインをしたら、左側のメニューバーから [Prompts] を選択し、右上の [+ New prompt] から新規作成を始めます。 画面右側の [+ New prompt] を選択 そして以下の新規作成ページに移りますので、必要項目を埋めるだけです。 新規作成ページ 各項目の説明は以下の通りです。 Name は Prompt に対する任意の名前で、プログラム側から指定するもの Prompt に具体的に入れたいプロンプト内容を入力します。Text か Chat を選ぶことができ、Chat を指定すると、それぞれのrole (System, Assistant, Developer, User) を指定してメッセージを入れることが可能です。Prompt の中には {{variable}} の形式で変数を埋め込め、ユーザーの入力値などを受け取って処理するために使えます。 Config は前回のブログでご紹介した通り、JSONで任意の値を入れることができるパラメーターになっております。例えば以下のようにモデル名の指定などで使うことができます。 { "model": "models/gemini-2.0-flash-001" } LabelsはデフォルトでProduction ラベルをつけるかどうかの選択です。Productionになっていると、プログラムコードでラベルを指定しない場合に選択されて使用されます。後で変更可能です。 Commit message は必須ではありませんが、Version1 以降はつけておくとチームメンバーなどに意図を伝えるために有益だと思います。 Playgroundの利用 まず新規での作り方を記載しましたが、場合によっては0から考えるのが難しいことがあると思います。そんな時に使える Playground 機能をご紹介します Playground 画面 左側のメニューから [Playground] を選択すると、Playground画面に遷移します。 基本的な使い方としては、試してみたいPrompt を [Messages] に入れ、画面右側で定義した [Model] で、モデルの種類や、各種パラメータを設定するだけ* です。また変数を入れて、右下の [Variables] に値を入れます。 例えば今回のPromptには 以下の文章が LLM の動作原理を説明する文章として正しいかどうかを判定しなさい。 {{text_input}} という記載が含まれており、この変数 text_input の値として テキストボックスに LLM は、主に「Transformer」と呼ばれる深層学習 (ディープラーニング) のアーキテクチャを基盤としています。このモデルは、大量のテキストデータ (書籍、ウェブサイト、記事など) を読み込み、単語や文の間の関係性 (文脈、意味など) を学習します。また学習した知識を基に、与えられた入力 (プロンプト) に対して、最も適切と思われる出力 (文章、回答など) を生成します。 を入れます。そしてSubmit すると、 [Output] にLLM からの回答が入っています。 この内容が気に入れば、右上の [Save as prompt] を押すと先ほどの新規作成画面に遷移し、そのまま新規Prompt にすることができます。 気に入らなければ好きなだけ修正するなり、初期化したければ [Reset playground] をするだけです。 *Model自体の登録はこの画面ではなく、メニューの [Settings] から あらかじめ設定しておく必要がありますのでご注意ください。Langfuse側からLLMモデルを利用しますので、課金されることにご注意ください。 Prompt Experiment の利用 新規作成後、LLMアプリケーションの運用においてPromptの改善が必要な場面に出くわすと思います。Prompt Experiment 利用すると変更したプロンプトに対して、リリース前に過去のユーザーのTrace をDataset にするなどして挙動が改善するかを確かめることができます。 Prompt Experiment 文字通りPrompt の実験として、対象Prompt とバージョンやモデルなどを指定し、 利用するDataset を設定します。 Datasetの指定 このDataset は0から作っておくもよいですし、Trace から直接Dataset に入れることで過去正常に動いたものがデグレしないか、不具合あったInputが改善されているかを実際に確かめていただくことができるようになります。また、LLM as a judge などと連携することで、自動で定量的な評価なども付加することが可能です。LLM as a judge については、 こちらのブログ で詳しく紹介しておりますので、是非あわせてご覧ください。(当該ブログの " テスト実行と結果の可視化" に相当する部分が本項に相当します。) なお今回ご紹介したPlayground とExperiment はSelf-hosted のOSS 版には含まれません (SaaS であれば無償のHobbyプランで使えます) のでご注意ください。 まとめ:Langfuseでプロンプト新規開発とテストを簡単に。 いかがでしたでしょうか。Langfuseを活用し、Promptの新規作成 - 管理までを簡単に実施できることがご確認いただけたと思います。本記事が効率的なLLMアプリケーションの開発とオペレーションのお役に立てれば幸いです。 本機能の具体的なユースケースや使い方のデモなどにご興味がある方は、ぜひ こちらから お気軽にお問い合わせください。

  • Langfuse の Self-hosted インストールのパターンと解説

    Langfuse v3 になって、「Self-hosting は良さそうだけど、結構インストール面倒なんでしょう?」という声をよく聞きます。もちろん複雑な構成を作ることも可能ではありますが、一方でLangfuse には簡単なものもふくめて幾つかのインストール方法が用意されており、利用用途や条件に合わせた選択が可能です。 この記事では、各インストールオプションおよび公式ページのリンク、使い分けについて解説します。まず簡単なケースごとのフローチャートは以下のような形になります。当てはまりそうなオプションを中心にぜひご確認ください。 インストールオプションのパターン 実際のインストールコマンドは、各オプションのリンクから公式をご参照ください。 Langfuse のインストールオプション 1. ローカルインストール Docker と docker compose を利用したローカル環境でのセットアップ方法です。 特筆すべきものはなく、非常にシンプルな手順で利用可能なもので、個人利用や簡単なテスト環境向きです。Mac やWindows でDocker をインストールしたら、docker compose upコマンド一つで起動します。特に悩むところもないです。 使用するケース 手元のアプリ開発の可視化やテスト目的で手軽にLangfuse を試してみたい このLangfuse を本番環境に使う予定はない 2. Docker Composeを使ったインストール 公式ドキュメントとしては区別されていますが、1と基本的には一緒です。ただしAWS/Google Cloud/Azure などで仮想マシン (EC2 など) をつかうことが想定されており、公式ページにはdockerパッケージの導入手順などについても記載してあります 大規模なトラフィックがなく、可用性が許容されるのであれば本番環境にも適用可能です。また一部にマネージドサービスを使うといった方法で可用性も向上できます。 使用するケース 小〜中規模のチームでの本番やステージング環境を構築したい Trace などの欠損リスクがある程度は許容できる VM の構築や管理ができる人がいる インフラ構築をシンプルに管理したい 必要なリソース 4Core 16GiB メモリなどが推奨 (それ以下でも立ち上がりはする) 100GiB ストレージ, 外部から接続できるNW設定 (Public IPなど) 本番利用に向けて、可用性を高める応用例 Object storage はVMではなくS3 / blob /GCS などに変更 プロンプト取得の可用性を高めるため、Web server のコンテナとPostgreSQL だけをマネージドサービス利用する またdocker-compose.yml を修正することで、ディスクやデータベースの接続など各種設定を変更することもできます。langfuse ディレクトリ直下にありますので必要に応じてご確認ください。 3. Dockerを使ったインストール Docker composeではなくDocker コンテナを使ってカスタマイズした構成を作るパターンです。利点は複数のコンポーネントで構成されているLangfuse をクラウドサービス側のマネージドサービスを利用して、高い可用性を保つことができることなどにあります。 PostgreSQL, Redis, Clickhouse をマネージドサービスで起動しておいて、docker コマンドの引数として指定しましょう。 使用するケース Kubernetes は使いたくないが、VM単体よりも可用性を高く保ちたい 一方でクラウドサービスのマネージドサービスを使って、手はかけたくない クラウドサービスのネットワークなどを構築・管理できる 改善したい可用性と構成例 プロンプト取得における可用性を向上させたい Web server のコンテナをECS やCloudRun で稼働 PostgreSQL をAurora や CloudSQL で稼働 Traceデータの可用性を高めたい Object Strage にS3, GCS などを活用 Clickhouse としてClickhouse Cloud などを使う、あるいはECSや GCE container optimized OS 上で動かす Async worker のコンテナをECS やCloud Run などで稼働 RedisにElasticashe や Memorystore などを活用する 最近ではTeraform, CDK, あるいはマニュアル などで比較的簡単 (あるいはほぼ自動) で構築できるようにリソースを公開しているものもあります。ご自身のケースに当てはまるかもご確認ください。 参考リンク AWS tuboneさん ( Blog ) リソース https://github.com/tubone24/langfuse-v3-terraform   mazyu36さん ( Blog ) リソース https://github.com/mazyu36/langfuse-with-aws-cdk Google Cloud クラウドエース株式会社 高木さん ( Blog ) * マニュアルでのインストール手順 4. Kubernetes Helmを使ったインストール Kubernetes クラスタにHelm を使ってLangfuseを導入する方法です。可用性やスケーラビリティを確保しつつ、運用をKubernetesに任せたいケースに利用可能です。 使用するケース 比較的大規模なチームやエンタープライズ環境 高い可用性とスケーラビリティを求める Kubernetesクラスタを運用することができる なお、Langfuse 公式で Helm Chart がリリースされており、特に理由がなければこれを使うことが最初の入口として良いと思います。その上で、さらに可用性を向上させたい場合には以下のオプションなどが有益です。 Traceを格納するClickhouse自体の可用性や保守性などを高めたい コストや諸条件が合えばClickhouse Cloud など利用を検討する プロンプト取得における可用性を向上させたい PostgreSQL をAurora や CloudSQL などで稼働 以下の記事では、Langfuse をKubernetes + マネージドサービスの構成でデプロイをした構成について言及しています。 参考リンク Google Cloud GAO 遠矢 ( Blog ) 本記事がインストール方法の決定における参考になれば幸いです。 もし企業における導入サポートなどが必要でしたら、 お気軽にお問い合わせください。 https://www.gao-ai.com/contact

  • [前半] ゼロからスケールへ:Langfuseのインフラストラクチャの進化 (和訳)

    このBlog記事はガオ株式会社による Langfuse GmbH "From Zero to Scale: Langfuse's Infrastructure Evolution" の日本語訳 前半となります。原文は こちら をご確認ください。 ゼロからスケールへ:Langfuseの インフラストラクチャの進化 Langfuseのインフラストラクチャをシンプルなプロトタイプからスケーラブルな Observability プラットフォームへと進化させた過程を詳しくご紹介します。 Steffen Schmitz Max Deichmann オープンソースのLLM Observerbility プラットフォームであるLangfuseは、Y Combinator 2023年Winter バッチから誕生しました。 私たちは、多くのLLMアプリケーションを自分たちで構築し、デモから本番環境への移行が難しいことを実感した後、バッチメイトの数名と緊密に協力し、LLM可視化プラットフォームのv0を迅速に開発しました。 当初は、いくつかのコア機能に的を絞りました。SDKは非同期、Langfuseはトレースをベースとし、すべてのコンポーネントはオープンソースで簡単にセルフホスティングできるものでした。最初のバージョンは、NextJs、Vercel、Postgresで書かれていました。私たちは、この実験が1分あたり数万件のイベントを処理するまでに急速に進化するとは、夢にも思っていませんでした。 Langfuseがすべてのユーザーに対してスケーリングできることを確実にするという点において、私たちの最近のV3リリースは重要なマイルストーンとなりました。私たちはすでにLangfuse Cloudでこれらの変更の多くを試験的に導入しており、v3リリースではオンライン評価、非同期/キューイング取り込み、キャッシュされたプロンプトなど、セルフホスティングユーザーにもそれらを利用できるようにしました。 本記事では、Langfuseの開発中に直面したスケーリングの課題と、私たちの「仮説 - 実験 - フィードバック」のループがLangfuse v3の開発にどのように役立ったかについてご説明します。もし、私たちと一緒に同様の課題の解決に取り組みたいとお考えであれば、ベルリンで人材を募集しています! Where it all started 当初の私たちのアーキテクチャは、単一のコンテナとPostgresデータベースであり、運用とセルフホスティングは非常にシンプルでしたが、スケーリングが非常に困難な構成でした。 私たちは、アーキテクチャを再考せざるを得ないような、いくつかの重要な課題に直面しました。最も重要な課題は次の通りです。 課題 1: 耐障害性が高く、高スループットを取り込めるパイプラインの構築 目標: Ingestion API は、予測不可能な負荷パターン下でも、大量のイベントを受け入れ、一貫して低レイテンシを維持する Langfuse の可視化プラットフォームの中核は、SDK および API による効率的なイベントデータ収集に依存しています。 これらの SDK は、ユーザーのアプリケーションへのパフォーマンスへの影響を最小限に抑えるように設計されていますが、取り込みサーバーコンポーネントは、規模を拡大するにつれて、重大な課題に直面しました。 当初の課題: 2023年夏には、急激なトラフィックパターンにより、取り込みAPIのレスポンスタイムが最大50秒まで急上昇しました。 重要な要件: Ingestion API は、SDKからのイベントの円滑なフラッシングを確保するために、常に低レイテンシを維持する必要があります。そうでないと、ユーザーのアプリケーションに悪影響が及ぶ可能性があります。 課題は、大量のデータを処理することだけではありませんでした。予測不可能な負荷パターン下で信頼性を維持しながら、ユーザーのアプリケーションパフォーマンスへの影響を最小限に抑えることでした。この技術的なハードルは、トラフィックの急増をより適切に処理するための取り込みアーキテクチャを再考することを迫る、当社にとって最初の大きなスケーリングの課題となりました。 課題 2:実稼働時のワークロードに合わせたプロンプトの最適化 目標: Prompt API は常に高い可用性とパフォーマンスを維持する Langfuse の重要な機能のひとつがプロンプト管理システムであり、ユーザーは UI を通じてプロンプトを定義し、SDK を通じて取得することができます。これにより、プロンプトを変更するためにアプリケーションを再デプロイする必要がなくなります。 Trace は非同期かつノンブロッキングですが、プロンプトはLLMアプリケーションのクリティカルパスとなります。このため、一見単純な機能が複雑なパフォーマンス上の課題となりました。取り込みが集中する時間帯には、プロンプト取得の p95 レイテンシが7秒にまで上昇しました。この状況には、他の操作によるシステム負荷が重い場合でも、一貫した低レイテンシのパフォーマンスを維持できるアーキテクチャ上のソリューションが必要でした。 課題 3:高速な分析読み取り(ダッシュボード、テーブルフィルター) 目標: 大規模な観測データにも対応するダッシュボードとテーブルフィルター 当初のデータベースとしてPostgresを選択したことは、初期の段階ではうまくいきましたが、当社の最大顧客がシステムを通じてより多くのObserverbility データを送信するようになると、重大なパフォーマンスのボトルネックにぶつかりました。クエリを最適化しても、当社のダッシュボードとテーブルフィルターの操作は、企業ユーザーにとっては遅すぎました。LLMの分析データは多くの場合、大きなblobで構成されており、何百万行ものデータをスキャンする際には、行指向のストレージがディスク上で重荷となっていました。皮肉なことに、当社の分析機能を最も必要としているお客様が、最もパフォーマンスの低下を経験していました。この成長に伴う問題は、当初のアーキテクチャが迅速な開発には最適であったものの、企業規模の分析作業負荷に対応するには根本的な再考が必要であることを示していました。 課題4:簡単なセルフホスティング 目標: 簡単にセルフホスティングできるだけでなく、運用上の労力をほとんど必要とせずに拡張できること Langfuseをオープンソースプロジェクトとして構築することは、意図的な選択でした。私たちのビジョンはシンプルでした。誰もが簡単なdocker-compose upでLangfuseを利用し始めるべきであると同時に、Langfuseは同時に、毎分何百ものユーザーと何千ものLLMのやり取りがあるエンタープライズ規模の展開にも対応できなければなりません。このアプローチは、私たち自身が開発者として好むものを反映しています。私たちは、評価や展開が容易なソリューションを重視しています。 しかし、実稼働環境に耐えうるオープンソースのObserverbility プラットフォームを構築するには、特有の課題があります。 汎用性:当社のインフラは、開発者のLaptopからさまざまなクラウド事業者へのデプロイまで、多様な環境でシームレスに動作する必要があります。 オープンソースへの依存:当社はオープンソースコンポーネントのみを使用することで、無制限のセルフホスティング機能を確保することを約束しています。 ゼロタッチ操作:企業ユーザーは、メンテナンスとアップグレードの自動化を必要としています。手動操作ではエラーが発生しやすく、拡張性にも欠けます。 このシンプルさとエンタープライズ対応のバランスが、当社のアーキテクチャ上の決定を形作り、アクセスしやすく拡張性のあるソリューションの作成を後押ししました。 新しい構成要素 これらの課題に対処するために、私たちはスタックに複数のビルディングブロックを追加しました。本記事では、私たちがどのようにスタックを繰り返し改良していったかをご紹介します。 ビルディングブロック1:取り込みデータの非同期処理 同期処理から非同期処理へ 私たちは当初、APIコールごとに多数のイベントを受信し、それらを繰り返し処理し、各イベントを個別に処理するIngestionパイプラインから始めました。処理中、まず同じIDを持つ履歴行を検索し、LLMコールのプロンプトと補完をトークン化し、コストを計算し、データベース内のイベントをupsertします。しかし私たちのテレメトリを調査したところ、2つの大きなボトルネックがあることが分かりました。PostgresのIOPSの枯渇と、長い文字列をトークン化する際のCPU消費です。これらはどちらも、当社のアプリケーションの稼働時間とレイテンシに影響を及ぼすリスクです。最悪の場合、当社の取り込みAPIでEvent が失われ、HTTP 500エラーが返されることになりました。 ソリューションを検討するにあたり、単にコンテナの数を増やすだけでは効果的ではないことに気づきました。個々のユーザーが大規模なバッチジョブを実行すると、取り込みトラフィックが大幅に急増することがよくあります。その結果、ユーザーからの API トラフィックは非常に予測が難しくなり、コンテナインスタンスではこうした急増に対応するのに十分な速さでスケールすることができません。そこで最終的に、すべての取り込みトラフィックを Redis のメッセージキューにルーティングすることにしました。Kafkaとは異なり、Redisは簡単に自己ホストでき、当社の要件を満たすように拡張できます。そして次に、別のLangfuseコンテナ (Worker) が非同期でこのデータをConsumeし、レート制限を適用して、当社のデータベースの負荷とコンテナのCPU使用率を低減します。この変更により、認証と本文の形式のみを確認する軽量な取り込みエンドポイントを作成しました。このWorkerコンテナは、トークン化やデータベースへの書き込みなどのより集中的なタスクを処理します。 Clickhouseから読み込まずにClickhouseに更新を書き込む 私たちは、APIパフォーマンスを短期的に改善する必要があったため、上記のステップのみを行いました。しかし、作業はまだ終わっていませんでした。Worker コンテナがすべての処理を非同期で行っていたとしても、私たちの取り込みパイプラインのロジックを動作させるには、多くのPostgresのIOPSが引き続き必要でした。この問題についても、セルフホスティングユーザーから問い合わせがありました。同時に、私たちは読み取りクエリのAPIレイテンシを改善するという課題にも直面しており、最終的に、TraceデータをPostgresからClickhouseに移行することを決定しました。Clickhouseは、Observerbility分野において多くの新規参入者が使用しているOLAPデータベースで、Apacheライセンスが適用されており、当社の概念実証(PoC)で卓越したパフォーマンスが確認されていました。列指向のストレージレイアウトは、私たちが期待する分析クエリに適しており、大規模なバイナリ列を持つ単一行の検索でも高いパフォーマンスを発揮します。しかし、本番環境への導入は容易ではありませんでした LangfuseのSDKは、指定されたオブジェクトIDの更新をバックエンドに送信するように設計されています。Postgresにおける単一の行の読み取りと更新は高速かつ簡単ですが、 ClickHouseにおけるすべての行の更新は非常にコストのかかる操作 です。そこで私たちは更新を新しい挿入に変換し、ClickHouseのReplacingMergeTreeテーブルエンジンを使用して、最終的にバックグラウンドで行の重複を排除しています。 つまり、常に行の最新の状態を取得し、更新を適用し、それをClickhouseに書き戻す必要があるということです。 私たちはトラフィックを分析し、すべての更新の90%が10秒以内にデータベースに書き込まれることを認識しました。つまりこれは、同時実行性とデータの整合性に気を配らなければならないことを意味します。しかし、Clickhouse から行の最新の状態を取得するのは現実的ではありませんでした。Clickhouse は、クエリ結果を返す前に全てのデータが Clickhouse ノード間で同期されることを保証する、非常にコストの高い "select_sequential_consistency" 設定を使用した場合にのみ、書き込み後の読み取りの一貫性が保たれます。したがって、私たちの規模では、Clickhouse から既存のデータを読み取れる保証はありませんでした。また、同じIDに対する2つのイベントが並行して処理され、競合状態が発生する可能性もありました。 そこでこの問題を緩和するために、承認された全てのイベントを Redis にキャッシュすることにしました。そして、Worker コンテナにイベントを送信し、Worker コンテナはオブジェクト ID に関連する全てのイベントを取得して、Clickhouse から読み込む必要なしに、確実に新しい Clickhouse の行を作成します。私たちは新しい取り込みパイプラインを実装し、Postgres 取り込みパイプラインと並行してイベントの処理を開始しました。 しかし非常に大きなインスタンスを利用しても、AWS ElastiCache のネットワーク容量には限界があるという事実がすぐに判明しました。また、Redis のもう一つの欠点は、インメモリ型のアーキテクチャと、保存されたデータが一時的な性質 (ephemeral) であることです。S3 をイベントのPersistent ストレージとして導入することで、Redis には参照情報のみを保持できるようになりました。この変更により、エラーが発生した場合にイベントを再生することも可能になり、さらに驚くことに、Redis 用にイベントをシリアライズする処理が高コストだったため、Web コンテナの CPU 使用率が大幅に低下しました。Kafka の方が取り込みにはより適していたかもしれませんが、新しいマルチモーダル機能のために、Redis のキャッシュ機能と S3 を活用することで、コンポーネント数を少なく保つことを選択しました。これらの調整により、Clickhouse にデータを一貫して、かつ大規模に挿入することに成功しました。

  • [後半] ゼロからスケールへ:Langfuseのインフラストラクチャの進化 (和訳)

    このBlog記事はガオ株式会社による Langfuse GmbH "From Zero to Scale: Langfuse's Infrastructure Evolution" の日本語訳 後半となります。原文は こちら をご確認ください。 前半記事は こちら 。 ビルディングブロック2: キャッシュと分離型のインフラストラクチャ Clickhouseへのデータ取り込み問題を解決する一方で、プロンプト管理機能を利用するユーザーの状況も改善する必要がありました。Observerbility データ分析の結果、プロンプトAPIにはいくつかの問題があることが判明しました。具体的には、それらが大量の取り込みトラフィックがデータベースのIOPSやコンテナのCPUを枯渇させる可能性がありました。 最初に、プロンプトを取得するためのPostgresデータベースへの問い合わせを回避しようと試みました。ここで、Redisをキャッシュとして利用することの強力さと、それがもたらす影響を実感しました。プロンプトが更新されるタイミングは把握しているため、古い結果を返すリスクなく効率的にキャッシュを無効化できます。 次に、プロンプトや認証など、レイテンシーと可用性に敏感なインフラを専用のデプロイメントに分離しました。AWS ECSの特定のエンドポイントに対して、LoadBalancerルールと専用のTargetGroupを使用することで、取り込みトラフィックをアプリケーションの他の部分から隔離できます。さらに、専用ルートによって可観測性が向上するという追加のメリットも得られました。この構成はまだHelm Chartには含まれていませんが、必要であれば主要なクラウドプロバイダーやKubernetes全体でエミュレートできます。 これらの2つの変更により、プロンプトAPIのp99(99パーセンタイル)のレスポンスタイムを7秒から100ミリ秒に短縮することに成功しました。 3つ目に、SDKを更新して、ゼロレイテンシのプロンプトフェッチングを使用するようにしました。以前にAPIからプロンプトのバージョンが取得されている場合は、そのバージョンを次のLLM呼び出しに使用し、LangfuseのAPIへの呼び出しはバックグラウンドで実行します。これにより、プロンプトがユーザーのアプリケーションのクリティカルパスから取り除かれました。 ビルディングブロック3:OLAPデータベース+クエリ最適化 Langfuse V3への移行における最後の課題は、読み取りクエリを最適化し、すべてのユーザーに対して一貫して低いレイテンシーを実現することでした。この取り組みを開始した時点で、すでにPostgresと並行してClickhouseにデータを書き込んでいました。これにより、Clickhouseからのデータの保存方法と取得方法を実験することができました。何度も「これでうまくいった」と思ったものの、そのたびにさらに多くのデータが到着しました。 当初、過去1週間以内のデータに対するすべての呼び出し(単一レコードのルックアップを含む)はp99で1秒以内に完了し、1週間以上のデータについては4秒以内であれば許容できると考えていました。Datadogでの通常のトレーシングに加えて、PostgresとClickHouseの読み取りを同時に実行し、それらのレイテンシーの違いを測定するためのフレームワークを構築しました。一貫して改善された結果を確認することで、正しい方向に進んでいるという確信を得ました。 まず最初に正しく行う必要があったのは、テーブルスキーマ、パーティショニング、およびデータの並び順キーでした。これらを変更するには、テーブル全体の書き換えが必要となり、つまり、すべての更新に数日かかる可能性がありました。他のClickhouseユーザーとの会話やClickhouseのドキュメントを参照し、早い段階でprojectIdと日付を並び順キーの最初の2つの列にすることにしました。さらに、フィルタリングによく使用される列にスキップインデックスを設定して、アイテムIDも追加しました。Postgresとは異なり、Clickhouseでは効率的な行ルックアップのためのB-Treeインデックスを保持できません。常にディスクレイアウトに基づいてデータを検索する必要があります 次に最適化する必要があったのは結合処理 (Join) でした。Oberverbility データへの結合を行う際に、処理に数秒かかり、Clickhouseノードで使用可能なすべてのメモリを使い果たすことが頻繁に発生していました。Clickhouseは、結合の右側 (The right side of a join) を効果的にフィルタリングするのが苦手だということを学びました。そこで可能な限り結合を避け、Common Table Expressions (CTE) を使用して、できる限りフィルターを手動でプッシュダウンしました。場合によっては、単一のトレースやObserverbility データのルックアップで並び順キーをより有効に活用するために、タイムスタンプなどの追加情報をフロントエンドAPIの呼び出しに追加しました。 これらは私たちが想定していた課題でしたが、ここからはClickhouseの特異な性質について掘り下げていきます。まず、ReplacingMergeTree内でデータを重複排除する方法を見つける必要がありました。Clickhouseは最終的には行を重複排除しますが、挿入後数分から数時間以内に多くの重複が発生し、短期間のメトリクスやダッシュボードがほぼ使い物にならないことがわかりました。FINALキーワードを使用すると改善されましたが、クエリ実行中のリソース消費量が増加したり、スキップインデックスの最適化がまったく利用されなくなったりするという新たな問題が発生しました。書き込みタイムスタンプによる重複排除(order byとlimit by)、FINALキーワード、およびdistinct集計を組み合わせて、信頼性の高いメトリクス、テーブル、およびビューを作成しました。 スキーマ設計に多くの時間を費やしたことが、Clickhouseへの移行において大きな成果をもたらしました。プロセス全体を通してわずかな調整しか必要なく、PostgresからClickhouseへの1回のデータインポートで済みました。残りの最適化については、特定のユースケースで何がうまくいくかを予測できなかったため、迅速な反復が功を奏しました。優れた可観測性と堅牢な実験フレームワークは、反復と新しい仮説の形成に迅速なフィードバックを提供しました。昔から言われているように、「変更が難しいことについては時間をかけて考え、できる限り迅速に動く」ということが重要です。 これらにより、以前は大規模プロジェクトでの外れ値によって悪化していたフロントエンドおよびバックエンドAPI呼び出しにおけるパフォーマンスが向上しました。 V3 Architecture まとめ:Langfuse v3のアーキテクチャに施した主な変更点は以下の通りです。 Worker コンテナ:イベントを非同期に処理する S3/Blob store: ラージオブジェクトを保存するため Clickhouse: Trace, Observations, Scoreを保存する Redis/Valkey: Eventキューイングとデータキャッシュ V3構成 V2構成 (参考) 結論 (Conclusion) Langfuse v3のリリースに非常に満足しています。Langfuse Cloud ユーザーからのポジティブなフィードバック、最初の1週間でのセルフホストユーザーの高い導入率、そしてわずかな問題点リストは、プロジェクト全体を通して多くの正しい決断を下したことを示しています。新しいアイデアを迅速にテストし、明確なデータに基づいた強力な仮説に導かれることで、大きな進歩を遂げることができました。 しかし、プロジェクト中、しばしばスケジュールを見誤っていました。今後の取り組みについては、スコープを最大1か月に制限し、途中でより多くのマイルストーンを導入する予定です。さらに、Langfuseが急速に成長しているため、このプロジェクトの進行中、主要な担当者が継続的なインシデントやバグ修正の対応に手が取られることが多くありました。 私たちはデータ駆動型の文化、本番データのサブセットで実験を行うためのシンプルな方法、そしてスタック全体にわたる優れた可観測性を維持します。これらの要素は、費やした各時間の価値を最大化し、セルフホストとクラウドベースの両方の顧客を満足させ続けるのにとって重要な意味を持つものとなります。 原文:  Langfuse GmbH "From Zero to Scale: Langfuse's Infrastructure Evolution" 日本語: Langfuse 日本語サイト 本ブログにおけるお問い合わせは こちら まで。

bottom of page