はじめに
LLMを使ったアプリを作ろうとして、「APIの呼び出し方はわかったけど、もっと複雑なことしたいんだよな」と思ったこと、ありませんか。
例えば、複数のAIモデルを切り替えて使いたいとか、外部データを参照させたいとか、ツールを呼び出すエージェントを作りたいとか。素のAPIだけでやろうとすると、結構な量のコードを書くことになります。
そこで登場するのがLangChain.js。Python版のLangChainが有名ですが、JavaScript/TypeScript版もかなり成熟してきています。GitHubスター数は16,500を超え、コントリビューターも1,000人以上という活発なプロジェクトです。
個人的には、LLMアプリ開発で「車輪の再発明」を避けたいなら、これは押さえておくべきフレームワークだと思います。
LangChain.jsとは
LangChain.jsは、LLM(大規模言語モデル)を活用したアプリケーションを構築するためのフレームワークです。「コンポーザビリティ」をキーワードに、様々なコンポーネントを組み合わせてAIアプリを作れるのが特徴。
正直なところ、最初は「フレームワーク入れるほどか?」と思っていました。でも実際に使ってみると、AIプロバイダーの切り替えやエージェント実装の手間が劇的に減って、もう手放せなくなりました。
特徴・メリット
1. 統一されたモデルインターフェース
OpenAI、Anthropic(Claude)、Google(Gemini)など、主要なAIプロバイダーをすべて同じAPIで扱えます。
これ、意外と大きいんですよね。ベンダーロックインを防げるし、「このタスクにはGPT-4o、こっちはClaude」みたいな使い分けも簡単にできる。
2. エージェントが10行で作れる
外部ツールを呼び出して複雑なタスクをこなすエージェント。自前で実装しようとすると、ツール呼び出しのパース、実行、結果のフィードバック...とかなり面倒です。
LangChain.jsなら、ツールを定義してエージェントに渡すだけ。公式ドキュメントいわく「10行以下のコードで」作れるとのこと。
3. 豊富な環境サポート
Node.js(ESM/CommonJS)はもちろん、以下の環境でも動作します。
- Cloudflare Workers
- Vercel / Next.js
- Supabase Edge Functions
- ブラウザ
- Deno
エッジ環境でも使えるのは、最近のトレンドを考えるとポイント高いですね。
4. LangGraphとの連携
より複雑なワークフローを構築したい場合は、同じチームが開発しているLangGraph.jsと組み合わせることもできます。状態を持つエージェントや、人間のフィードバックを挟むワークフローなど、高度なユースケースに対応。
インストール方法
基本パッケージのインストールはこれだけです。
npm install langchain
pnpmやyarnを使っている場合は、それぞれのコマンドで。
pnpm install langchain
yarn add langchain
使いたいAIプロバイダーに応じて、追加パッケージもインストールします。
# OpenAIを使う場合
npm install @langchain/openai
# Claudeを使う場合
npm install @langchain/anthropic
# Geminiを使う場合
npm install @langchain/google-genai
基本的な使い方
シンプルなテキスト生成
まずは一番シンプルな使い方から。
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
modelName: "gpt-4o",
});
const response = await model.invoke("TypeScriptの利点を3つ教えてください");
console.log(response.content);
Claudeに切り替えたい場合は、インポートとクラス名を変えるだけ。
import { ChatAnthropic } from "@langchain/anthropic";
const model = new ChatAnthropic({
modelName: "claude-sonnet-4-20250514",
});
const response = await model.invoke("TypeScriptの利点を3つ教えてください");
console.log(response.content);
エージェントを作る
ツールを呼び出すエージェントを作ってみます。公式の例を参考にすると、こんな感じで書けます。
import * as z from "zod";
import { createAgent, tool } from "langchain";
// ツールの定義
const getWeather = tool(
({ city }) => `${city}の天気は晴れです!気温は22度。`,
{
name: "get_weather",
description: "指定した都市の天気を取得します",
schema: z.object({
city: z.string().describe("都市名"),
}),
},
);
// エージェントの作成
const agent = createAgent({
model: "claude-sonnet-4-20250514",
tools: [getWeather],
});
// 実行
const result = await agent.invoke({
messages: [{ role: "user", content: "東京の天気を教えて" }],
});
console.log(result);
ツールを追加したい場合は、配列に追加するだけ。シンプルですね。
プロンプトテンプレート
動的なプロンプトを作りたい場合は、テンプレートを使います。
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOpenAI } from "@langchain/openai";
const prompt = ChatPromptTemplate.fromMessages([
["system", "あなたは{role}として振る舞ってください。"],
["user", "{question}"],
]);
const model = new ChatOpenAI({ modelName: "gpt-4o" });
const chain = prompt.pipe(model);
const response = await chain.invoke({
role: "シニアエンジニア",
question: "マイクロサービスの利点を教えてください",
});
console.log(response.content);
.pipe()でチェーンを繋げていく書き方、最初は慣れが必要ですが、覚えると可読性が上がります。
実践的なユースケース
RAG(Retrieval-Augmented Generation)
外部のドキュメントを検索して、その内容をもとに回答を生成するRAG。社内ドキュメント検索とか、カスタマーサポートbotでよく使われるパターンです。
import { ChatOpenAI, OpenAIEmbeddings } from "@langchain/openai";
import { MemoryVectorStore } from "langchain/vectorstores/memory";
import { Document } from "@langchain/core/documents";
// ドキュメントの準備
const docs = [
new Document({
pageContent: "LangChain.jsはLLMアプリ開発用のフレームワークです",
metadata: { source: "docs" },
}),
new Document({
pageContent: "Node.js、Deno、ブラウザで動作します",
metadata: { source: "docs" },
}),
];
// ベクトルストアの作成
const embeddings = new OpenAIEmbeddings();
const vectorStore = await MemoryVectorStore.fromDocuments(docs, embeddings);
// 類似度検索
const results = await vectorStore.similaritySearch("対応環境は?", 2);
console.log(results);
実際のプロダクションでは、PineconeやChromaなどのベクトルDBと組み合わせることが多いですね。
ストリーミング出力
長い回答を生成する場合、ストリーミングでリアルタイムに表示するとUXが良くなります。
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({
modelName: "gpt-4o",
streaming: true,
});
const stream = await model.stream("JavaScriptの歴史を詳しく教えてください");
for await (const chunk of stream) {
process.stdout.write(chunk.content as string);
}
会話履歴の管理
チャットボットを作る場合、会話履歴を保持する必要があります。
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage, SystemMessage } from "@langchain/core/messages";
const model = new ChatOpenAI({ modelName: "gpt-4o" });
const messages = [
new SystemMessage("あなたは親切なアシスタントです。"),
new HumanMessage("私の名前は田中です"),
new AIMessage("田中さん、はじめまして!何かお手伝いできることはありますか?"),
new HumanMessage("私の名前を覚えていますか?"),
];
const response = await model.invoke(messages);
console.log(response.content);
// => "はい、田中さんですね!"
LangChainとLangGraphの使い分け
LangChainのエコシステムには、LangGraph.jsという別のフレームワークもあります。
- LangChain: シンプルなエージェントや、素早くプロトタイプを作りたい場合
- LangGraph: 複雑なワークフロー、状態管理が必要な場合、人間のフィードバックを挟みたい場合
30代になって思うのは、「シンプルに始めて必要に応じて複雑にする」というアプローチが一番効率的だということ。まずはLangChainで始めて、要件が複雑になってきたらLangGraphを検討する、という流れがおすすめです。
まとめ
LangChain.jsを使ってみて感じるのは、LLMアプリ開発の「面倒くさい部分」を上手く抽象化してくれているなということ。
- 複数プロバイダーの統一インターフェース
- エージェントの簡単な構築
- RAGやストリーミングなどの定番パターンのサポート
個人的には、AIプロバイダーを直接叩くコードを書いていた時期と比べて、開発効率が明らかに上がりました。特にプロトタイピングの速度が違う。
一方で、抽象化されている分、細かいカスタマイズをしたい場合は公式ドキュメントを読み込む必要があります。ドキュメントはかなり充実しているので、困ったときは公式を見るのが一番ですね。
LLMを使ったアプリを作るなら、一度は触っておくべきフレームワークだと思います。まずは公式のクイックスタートから始めてみてください。