【LangChain】「Runnable」インターフェースが革命的な理由:組織もコードも規格統一が命
はじめに:Excelのフォーマットがバラバラな問題
「月次の売上報告、AさんはPDF、BさんはExcel、Cさんはメール本文…統一してくれ!」
管理職なら誰もが一度は叫びたくなる瞬間です。フォーマットが統一されていないと、集計作業(=パイプライン)が組めないんですよね。
LangChainの世界でも同じことが起きていました。以前は LLMChain や RetrievalQA
など、クラスごとに呼び出し方が微妙に違って使いづらかった。それを解決し、全てを統一規格にしたのが Runnable インターフェース
です。これのおかげで、我々はレゴブロックのように自由に処理を組み立てられるようになりました。
基礎知識:LCEL (LangChain Expression Language) の核
LangChain v0.1以降、推奨されている構文が LCEL(パイプ演算子 | で繋ぐ書き方)です。これを実現するための裏側の仕組みが
Runnable プロトコルです。
モデルも、プロンプトも、出力パーサーも、全てが Runnable
を継承しています。だからこそ、prompt | model | output_parser という直感的な記述が可能になったのです。
実装・設定:invoke, batch, stream の三種の神器
Runnable準拠のオブジェクトは、以下のメソッドを標準装備しています。これが便利すぎるんです。
- invoke: 単発実行。「これ処理しといて」という普通の依頼。
- batch: 一括実行。「この100件、まとめてお願い」という並列依頼。裏でスレッドプールを使って高速化してくれます。
- stream: ストリーミング実行。「出来たところから順次報告して」というリアルタイム報告。ChatGPTのような「文字がパラパラ出る」演出には必須です。
from langchain_core.runnables import RunnableLambda
# 普通の関数もRunnable化できる
runnable = RunnableLambda(lambda x: str(x) + "!!!")
# どれでも呼べる安心感
print(runnable.invoke("Hello"))
print(runnable.batch(["Hi", "Hey"]))
応用テクニック:RunnableParallelで並列処理を爆速化
「検索」と「要約」を同時に走らせたい時などは、RunnableParallel を使います。
chain = RunnableParallel({
"web_search": web_search_chain,
"db_search": db_search_chain
})
これを invoke すれば、両方の処理がヨーイドンで始まり、両方が終わった時点で結果が辞書形式で返ってきます。待ち時間を最小化できる、優秀なマネージャーのような機能です。
トラブルシューティング:古いChainからの移行戦略
昔のコード(DeviceChain とか)を使っていると、LCELと混ぜられなくてハマります。古いChainは徐々に非推奨になっているので、見つけ次第
| 記法のLCELに書き換えるのが吉です。
「動けばいい」は技術的負債の始まりです。定期的なリファクタリングを。
まとめ:共通言語を持つ組織は強い
Runnable
という共通インターフェースのおかげで、LangChainのエコシステムは爆発的に広がりました。誰が作ったカスタムツールでも、invoke を呼べば動くと分かっているからです。
組織運営も同じですね。「報告は必ずこのフォーマットで」というルール(インターフェース)があるからこそ、個々人が自律的に動いても全体が崩壊しない。コードから学ぶ組織論でした。
コメント
コメントを投稿