メッセージは LangChain におけるモデルのコンテキストの基本ユニットです。メッセージはモデルの入出力を表し、LLM とやり取りする際、会話の状態を表すのに必要なコンテンツとメタデータの両方をキャリーします。
LangChain 1.0 alpha : コアコンポーネント – メッセージ
作成 : クラスキャット・セールスインフォメーション
作成日時 : 09/23/2025
バージョン : 1.0.0a6
* 本記事は docs.langchain.com の以下のページを独自に翻訳した上で、補足説明を加えてまとめ直しています。スニペットはできる限り日本語を使用しています :
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
LangChain 1.0 alpha : コアコンポーネント – メッセージ
メッセージは LangChain におけるモデルのコンテキストの基本ユニットです。メッセージはモデルの入出力を表し、LLM とやり取りする際、会話の状態を表すのに必要なコンテンツとメタデータの両方をキャリーします。
メッセージは以下を含むオブジェクトです :
- ロール – メッセージ・タイプ (e.g., system、user) を識別します。
- コンテンツ – テキスト、画像、音声、ドキュメント 等のような、メッセージの実際の内容を表します。
- メタデータ – レスポンス情報、メッセージ ID、トークン使用量のようなオプションフィールド
LangChain は、すべてのモデルプロバイダーに渡り動作する標準的なメッセージタイプを提供し、呼び出されるモデルに関係なく一貫した動作を保証します。
基本的な使用方法
メッセージを使用する最も簡単な方法は、メッセージ・オブジェクトを作成して、モデルを呼び出すときにそれらを渡すことです。
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
model = init_chat_model("openai:gpt-5-nano")
system_msg = SystemMessage("You are a helpful assistant.")
human_msg = HumanMessage("Hello, how are you?")
# Use with chat models
messages = [system_msg, human_msg]
response = model.invoke(messages) # Returns AIMessage
出力例
Hi there! I’m here and ready to help with whatever you need. I don’t have feelings, but I’m ready to assist. What would you like help with today?
テキスト・プロンプト
テキストプロンプトは文字列です – 会話履歴を保持する必要のない、単純な生成タスクに最適です。
response = model.invoke("春について俳句を書いてください。")
出力例
もちろん。春をテーマにした俳句を3つ挙げます。 1) 春風や 桜の下で 鳥の声 2) 春雨や 蛙が跳ねる 春の風 3) 桜並木 風に散る花 春日かな
以下のような場合に、テキストプロンプトを使用します :
- 単一の、スタンドアローンなリクエストがある
- 会話履歴を必要としない
- 最小限のコードの複雑を望む
メッセージ・プロンプト
あるいは、メッセージ・オブジェクトのリストを提供することで、メッセージのリストをモデルに渡すこともできます。
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
messages = [
SystemMessage("あなたは詩の専門家です。"),
HumanMessage("春について俳句を作成してください。W"),
AIMessage("桜🌸の花が咲きました ...")
]
response = model.invoke(messages)
出力例
以下、春をテーマにした俳句を3つご提案します。 1) 春風や 桜の花びらが 川を染める 2) 春の朝 霧の中に光る 蝶ひらり 3) 雪解けて 庭の小さな芽が 風に揺れる ご希望の雰囲気や季節感があれば、別のスタイルでさらに作成します。
以下の場合、メッセージ・プロンプトを使用します :
- マルチターンの会話を管理
- マルチモーダル・コンテンツ (画像、音声、ファイル) を扱う
- システム指示を含む
辞書形式
OpenAI チャット completions 形式でメッセージを直接指定することもできます。
messages = [
{"role": "system", "content": "あなたは詩の専門家です。"},
{"role": "user", "content": "春について俳句を作成してください。"},
{"role": "assistant", "content": "桜🌸の花が咲きました .."}
]
response = model.invoke(messages)
出力例
春を題材にした俳句をいくつかご用意しました。5-7-5の定型を意識しています。 - 春風や 桜咲く頃 川の音 - 春ひらく 花びらゆらぐ 朝露や - 水辺へと 鶯の声 春来る日 どれも季語として「春」と自然の情景を取り入れています。お気に入りがあれば教えてください。別の雰囲気でも作成します。
メッセージ・タイプ
- System メッセージ – モデルに動作する方法を伝えて、インタラクションのコンテキストを提供します。
- Human メッセージ – ユーザ入力とモデルとのインタラクションを表します。
- AI メッセージ – テキストコンテンツ、ツール呼び出し、メタデータを含む、モデルにより生成されたレスポンス。
- Tool メッセージ – ツール呼び出しの出力を表します。
System メッセージ
SystemMessage は、モデルの動作を準備する指示の初期セットを表します。雰囲気 (tone) を決め、モデルの役割りを定義し、レスポンスのガイドラインを確立するために system メッセージを使用できます。
Basic instructions
system_msg = SystemMessage("あなたは役立つコーディング・アシスタントです。")
messages = [
system_msg,
HumanMessage("REST API をどのように作成しますか?")
]
response = model.invoke(messages)
Detailed persona
from langchain_core.messages import SystemMessage, HumanMessage
system_msg = SystemMessage("""
あなたは Web フレームワークの専門知識を持つ上級 Python 開発者です。
必ずコード例を提示し、その理由を説明してください。
説明は簡潔でありながら完全に行ってください。
""")
messages = [
system_msg,
HumanMessage("REST API をどのように作成しますか?")
]
response = model.invoke(messages)
出力例
REST API を作成する基本的な道筋と、実装例を FastAPI を用いて示します。最新の Python で高性能・型安全・自動ドキュメントが得られる点が魅力です。 1) 要件定義と設計 - 何をリソースとして公開するかを決める(例: items, users, orders など) - 各リソースに対して CRUD 操作を HTTP メソッドで設計する - Create: POST /items - Read: GET /items, GET /items/{id} - Update: PUT /items/{id} - Delete: DELETE /items/{id} - バージョン管理(例: /api/v1/...)と適切なステータスコードを採用 - 入力検証・エラーハンドリング・認証・認可・データ検証を整備 - ドキュメント化(OpenAPI/Swaggerは自動生成が望ましい) 2) 技術選択と理由 - FastAPI を推奨:型ヒントを活用した検証・自動生成ドキュメント、非同期処理、パフォーマンス、初心者にも扱いやすい。 - ORM は SQLAlchemy 或いは Tortoise ORM など、データベースと連携してモデルを定義。 - テストには httpx(あるいは requests)と pytest。 3) プロジェクト構成の例 - app/ - main.py : FastAPI アプリの起動・ルーティング - api/ - v1/ - items.py : アイテム関連のエンドポイント - models/ - item.py : SQLAlchemy の ORM モデル - schemas/ - item.py : Pydantic モデル(リクエスト/レスポンス用) - core/ - config.py : 設定(例: データベースURL) - db.py : DB セッション管理 - tests/ : テスト 4) 最小実装サンプル(FastAPI + in-memory store) - ファイル名: main.py ```python from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import List, Optional app = FastAPI(title="Sample API", version="1.0.0") class Item(BaseModel): id: int name: str description: Optional[str] = None price: float # インメモリストア(サンプル用) _items: dict[int, Item] = {} @app.post("/api/v1/items/", response_model=Item, status_code=201) async def create_item(item: Item): if item.id in _items: raise HTTPException(status_code=400, detail="Item already exists") _items[item.id] = item return item @app.get("/api/v1/items/", response_model=List[Item]) async def list_items(): return list(_items.values()) @app.get("/api/v1/items/{item_id}", response_model=Item) async def get_item(item_id: int): item = _items.get(item_id) if item is None: raise HTTPException(status_code=404, detail="Item not found") return item @app.put("/api/v1/items/{item_id}", response_model=Item) async def update_item(item_id: int, item: Item): if item_id != item.id: raise HTTPException(status_code=400, detail="ID mismatch") if item_id not in _items: raise HTTPException(status_code=404, detail="Item not found") _items[item_id] = item return item @app.delete("/api/v1/items/{item_id}", status_code=204) async def delete_item(item_id: int): if item_id not in _items: raise HTTPException(status_code=404, detail="Item not found") del _items[item_id] return if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) ``` 実行方法: - 環境構築 - pip install fastapi uvicorn pydantic - 起動 - uvicorn main:app --reload - ドキュメント - http://localhost:8000/api/v1/items/ で自動生成された Swagger UI/ ReDoc が利用可能 5) データベース連携の基本(SQLAlchemy 例) - 追加ファイルを用意して ORM で永続化する基本例 ファイル: db.py ```python from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, declarative_base DATABASE_URL = "sqlite:///./test.db" # 環境に合わせて変更 engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False}) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() ``` ファイル: models/item.py ```python from sqlalchemy import Column, Integer, String, Float from .base import Base # ここでは Base が db.py の Base を指す想定 class ItemModel(Base): __tablename__ = "items" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) description = Column(String, nullable=True) price = Column(Float, nullable=False) ``` ファイル: schemas/item.py ```python from pydantic import BaseModel from typing import Optional class ItemCreate(BaseModel): id: int name: str description: Optional[str] = None price: float ``` ファイル: main.py の簡易統合例(要調整) ```python from fastapi import FastAPI, Depends, HTTPException from sqlalchemy.orm import Session from db import SessionLocal, Base from models.item import ItemModel from schemas.item import ItemCreate Base.metadata.create_all(bind=engine) app = FastAPI() def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.post("/api/v1/items/", response_model=ItemCreate) def create_item(item: ItemCreate, db: Session = Depends(get_db)): db_item = ItemModel(id=item.id, name=item.name, description=item.description, price=item.price) db.add(db_item) db.commit() db.refresh(db_item) return item ``` 補足: - 実運用では、インメモリストアは避け、必ずデータベースへ永続化します。上の例は最小構成のイメージです。 - Pydantic のスキーマと SQLAlchemy のモデルを分けると、入力検証と永続化をきれいに分離できます。 6) 認証とエラーハンドリングの基本 - 認証: OAuth2 Password Flow や JWT を導入 - 実装例(簡易): JWT トークンを発行するエンドポイントと、保護されたエンドポイントの例 ```python from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import JWTError, jwt SECRET_KEY = "your-secret-key" ALGORITHM = "HS256" oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") def create_access_token(data: dict): return jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM) async def get_current_user(token: str = Depends(oauth2_scheme)): try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) return payload except JWTError: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token") @app.post("/api/v1/token") async def login(form_data: OAuth2PasswordRequestForm = Depends()): # 実際にはユーザー確認を行う access_token = create_access_token({"sub": form_data.username}) return {"access_token": access_token, "token_type": "bearer"} @app.get("/api/v1/protected") async def protected_route(user: dict = Depends(get_current_user)): return {"hello": user.get("sub")} ``` 7) ドキュメントとテスト - FastAPI は OpenAPI に基づく自動ドキュメントを提供 - http://localhost:8000/docs(Swagger UI) - http://localhost:8000/redoc(ReDoc) - テスト例(httpx + pytest) ```python # tests/test_items.py import httpx import pytest BASE = "http://localhost:8000/api/v1" @pytest.mark.asyncio async def test_create_and_get_item(): async with httpx.AsyncClient() as client: r = await client.post(f"{BASE}/items/", json={"id":1,"name":"Sample","price":9.99}) assert r.status_code == 201 r = await client.get(f"{BASE}/items/1") assert r.status_code == 200 ``` 8) デプロイと運用のヒント - ASGI サーバーで運用 - uvicornや gunicorn + uvicorn workers の組み合わせ - 例: gunicorn -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000 - Docker 化の基本 - Dockerfile: - FROM python:3.11-slim - WORKDIR /app - COPY requirements.txt . - RUN pip install -r requirements.txt - COPY . . - CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] - docker-compose で DB 連携と API を同時に起動する構成がよく用いられます。 - 監視・運用 - ログ、エラーレスポンス、レイテンシの監視を組み込み - API バージョンを使った後方互換性の維持 - セキュリティ対策として TLS、入力検証、 rate limit、認証・権限の適切な設定 要点 - FastAPI は最速で実用的な REST API を作成でき、型安全・自動ドキュメント・非同期処理を同時に得られます。 - まずは小さなエンドポイントから始め、徐々にデータベース連携・認証・エラーハンドリングを拡張するのが現実的です。 - 本番運用ではデータベース・認証・デプロイ手順を明確に分離・自動化し、テストとドキュメントを常に最新に保つことが重要です。 必要であれば、あなたの用途(データベース種別、認証要件、公開 API の規模)に合わせた具体的なコード構成とファイルテンプレを作成します。どのフレームワークがよいか(FastAPI/DRF/Flask など)も目的に合わせて提案します。
Human メッセージ
HumanMessage はユーザの入力とインタラクションを表します。テキスト、画像、音声、ファイルと、その他のマルチモーダルなコンテンツを含むことができます。
テキストコンテンツ
Message オブジェクト
human_msg = HumanMessage("What is machine learning?")
response = model.invoke([human_msg])
文字列ショートカット
# Using a string is a shortcut for a single HumanMessage
response = model.invoke("What is machine learning?")
メッセージ・メタデータ
メタデータの追加
human_msg = HumanMessage(
content="Hello!",
name="alice", # Optional: identify different users
id="msg_123", # Optional: unique identifier for tracing
)
AI メッセージ
AIMessage はモデル呼び出しの出力を表します。マルチモーダルデータ、ツール呼び出し、そして (後でアクセス可能な) プロバイダー固有のメタデータを含むことができます。
response = model.invoke("Explain AI")
print(type(response)) # <class 'langchain_core.messages.AIMessage'>
AIMessage オブジェクトはモデルを呼び出した際にモデルにより返され、これはレスポンス内の関連メタデータのすべてを含みます。けれども、これが AIMessage オブジェクトの作成/変更が可能な唯一の場所ではありません。
プロバイダーはメッセージのタイプにより異なって重み付けし、コンテキストを理解するので、新しい AIMessage オブジェクトの作成や (モデルから取得したかのように) メッセージ履歴への挿入は役立つ場合があります。
from langchain_core.messages import AIMessage, SystemMessage, HumanMessage
# Create an AI message manually (e.g., for conversation history)
ai_msg = AIMessage("その問題について喜んでお手伝いさせていただきます!")
# Add to conversation history
messages = [
SystemMessage("あなたは役に立つアシスタントです"),
HumanMessage("手伝ってもらえますか?"),
ai_msg, # Insert as if it came from the model
HumanMessage("素晴らしい!2+2 はいくつですか?")
]
response = model.invoke(messages)
出力例
4です。ほかにも計算の問題があれば教えてください。
ツール呼び出しレスポンス
モデルがツールを呼び出すとき、ツール呼び出しレスポンスは AI メッセージに (tool_calls として) 含まれます :
Tool calling
model_with_tools = model.bind_tools([GetWeather])
response = model_with_tools.invoke("What's the weather in Paris?")
for tool_call in response.tool_calls:
print(f"Tool: {tool_call['name']}")
print(f"Args: {tool_call['args']}")
print(f"ID: {tool_call['id']}")
ストリーミングとチャンク
ストリーミング中、完全なメッセージに組み合わせることができる AIMessageChunk オブジェクトを受け取ります :
chunks = []
full_message = None
for chunk in model.stream("Hi"):
chunks.append(chunk)
print(chunk.text)
full_message = chunk if full_message is None else full_message + chunk
ツールメッセージ
ツール呼び出しをサポートするモデルについては、AI メッセージはツール呼び出しを含めることができます。ツールメッセージは、単一のツール実行の結果をモデルに返すために使用されます。
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, AIMessage, ToolMessage
def get_weather(city: str) -> str:
"""Get weather for a given city."""
return f"{city} では常に晴れています!"
model = init_chat_model("openai:gpt-5-nano")
# モデルがツール呼び出しを行った後
ai_message = AIMessage(
content=[],
tool_calls=[{
"name": "get_weather",
"args": {"location": "東京"},
"id": "call_123"
}]
)
# ツールを実行して結果メッセージを作成
weather_result = "晴れ, 22度"
tool_message = ToolMessage(
content=weather_result,
tool_call_id="call_123" # Must match the call ID
)
# 会話の続行
messages = [
HumanMessage("東京の天気はどうですか?"),
ai_message, # Model's tool call
tool_message, # Tool execution result
]
response = model.invoke(messages) # Model processes the result
出力例
東京は晴れで、気温は22度です。日中は過ごしやすいですが日差しが強いので、外出時は帽子や日焼け止めをお忘れなく。 夜になると涼しくなる可能性があります。何か計画があれば、時間帯に合わせたアドバイスもします。
以上