C
Claude Academy
Simple Chatbot

シンプルなチャットボット

約 14 分 · クイズ 3 問 · 演習 1 問
重要キーワード (4 語)
Stateless API (ステートレスAPI) — サーバーが履歴を保持しない設計。クライアントが履歴を持つ
Streaming (ストリーミング) — 応答を逐次返す方式
Sliding Window (スライディングウィンドウ) — 履歴の古い部分を切る or 要約する技法
Compaction (圧縮) — 長い会話を要約して短くする処理

シンプルなチャットボット

最小構成のチャットボットを Flask で作ります。

設計

  • 状態は クライアント (ブラウザ) が持つ。
  • サーバーは履歴を受け取って Claude に転送するだけ。
  • Streaming で応答を逐次返す。

サーバー側

from flask import Flask, request, Response, jsonify
from anthropic import Anthropic

app = Flask(__name__)
client = Anthropic()

SYSTEM = "あなたは丁寧な日本語アシスタントです。"

@app.post("/chat")
def chat():
    history = request.json["history"]   # [{role, content}, ...]
    def gen():
        with client.messages.stream(
            model="claude-sonnet-4-6",
            max_tokens=1024,
            system=SYSTEM,
            messages=history,
        ) as s:
            for t in s.text_stream:
                yield t
    return Response(gen(), mimetype="text/plain")

クライアント側 (擬似)

async function send(userMsg) {
  history.push({role: "user", content: userMsg});
  const res = await fetch("/chat", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({history}),
  });
  const reader = res.body.getReader();
  let assistant = "";
  for (;;) {
    const {value, done} = await reader.read();
    if (done) break;
    assistant += new TextDecoder().decode(value);
    render(assistant);
  }
  history.push({role: "assistant", content: assistant});
}

履歴の長期化対策: Sliding Window + Summary

会話が長くなると input が肥大化します。次の戦略を組み合わせます:

MAX_TURNS = 20

def trim(history: list[dict]) -> list[dict]:
    if len(history) <= MAX_TURNS:
        return history
    # 古いターンを要約
    old, recent = history[:-MAX_TURNS], history[-MAX_TURNS:]
    summary = summarize(old)
    return [{"role": "user", "content": f"<会話の要約>\n{summary}"}] + recent

summarize() も Claude で実装すれば自然な要約に。

ベストプラクティス

  • システムプロンプトはキャッシュ対象に。
  • 入力検証: 極端に長い入力 / 連投 を制限。
  • ユーザー識別はハッシュ化して metadata.user_id に。
  • 失敗時は 古い応答に戻す or 再試行 UI を提供。
  • レート制限はサーバー側でクオータ実装。

Cache をかける

長い system は cache_control: ephemeral で。 ユーザーが多いほどヒット率が上がる。

system=[
    {"type": "text", "text": SYSTEM_BASE},
    {"type": "text", "text": LONG_GUIDELINES, "cache_control": {"type": "ephemeral"}},
]

Tip: ユーザーごとのカスタム system

「このユーザーは英語で答える」「あのユーザーは詳細な技術解説を好む」など、 ユーザー設定 + 共通システム のハイブリッドが理想。

この academy アプリも参考に

本講座の Playground は同じパターンで実装されています (app.pyapi_playground)。

Hands-on 演習

演習 1: ミニ Flask チャットを書く

150 行以内で、次の機能を持つ Flask チャットを書いてください。

  • / で簡単な HTML (チャット UI)
  • /chat POST: 履歴を受け取り、Streaming で応答を返す
  • 履歴 30 ターン超なら古いターンを要約に置換
  • system は cache_control 付き
▶ Playground を開いて実行
💡 ヒント

本講座アプリ (app.py) のコードが良い参考になります。SSE のフォーマットも同じパターンを流用できます。

進捗保存にはログインが必要 クイズに挑戦 (3問)

💬 このレッスンへの質問 (0)

全質問を見る →
質問の投稿には ログイン が必要です。閲覧は誰でも可能です。

まだ質問はありません。最初の 1 件を投稿してみましょう。