第9章 会話の文脈と状態を扱う

本章は初稿です。

9.1 この章で学ぶこと

「Windows です」「その手順でも直りませんでした」という発言だけでは、何の相談か分かりません。前のやり取りを引き継いで初めて、追加情報として意味を持ちます。

本章では、同じ Agent で会話を続ける場合と、新しい会話を始める場合を比較します。履歴、モデルへ渡す文脈、長期記憶、業務の記録を区別できるようになることを目指します。

9.2 一つの振る舞いと、複数の会話

Conversation は入出力の履歴を保持し、Response はその履歴と新しい入力を使って実行されます。Agent は複数の会話で再利用できます。[^runtime]

同じ IT 支援エージェントの定義を、社員 A の VPN 相談と社員 B の別の相談で共用する。各会話の履歴は別に保ち、次の応答には対応する会話の情報だけを引き継ぐ

図9-1 共通にするのは振る舞いであり、全員の相談履歴ではない。 枠は相談ごとの履歴の区切り、矢印は振る舞いの参照と履歴の引き継ぎを表します。図の分離を実現するには、アプリケーション側でも利用者と会話の対応を確認します。会話 ID が認可の代わりになるわけではありません。

たとえば「VPN の相談」と「経費システムの相談」を別の会話へ分ければ、話題の混同を減らせます。話題を引き継ぐ設計にする場合も、どの情報を持ち越すかを明示します。

9.3 会話を続けるコードを読む

次のコードは、第7章の client を利用できる with ブロックの内側で試す断片です。単独の実行ファイルではありません。Agent の名前や指示を変えず、会話だけを変えて比較します。SDK と Azure の接続部分は実環境未検証です。

python
conversation_a = client.conversations.create()

for message in [
    "VPN に接続できません。",
    "OS は Windows です。",
    "ここまでに伝えた情報と、まだ足りない情報を整理してください。",
]:
    response = client.responses.create(
        conversation=conversation_a.id,
        input=message,
    )
    if response.status != "completed" or not response.output_text:
        raise RuntimeError(f"Unexpected response state: {response.status}")
    print(response.output_text)

conversation_b = client.conversations.create()
response_b = client.responses.create(
    conversation=conversation_b.id,
    input="その手順でも直りませんでした。",
)
if response_b.status != "completed" or not response_b.output_text:
    raise RuntimeError(f"Unexpected response state: {response_b.status}")
print(response_b.output_text)

Conversation A では、VPN と Windows が既に伝えられています。Conversation B には、その履歴を渡していません。同じ Agent でも、前者の具体的な相談を当然には知っていません。公式の会話例も、同じ Conversation を指定して複数の応答を生成します。[^quickstart]

モデルが偶然「VPN ですか」と推測した場合も、履歴の継承を証明したことにはなりません。渡した会話 ID と入力項目を確認してください。

9.4 保存してある履歴と、今回使う文脈は違う

モデルは、今回の入力として与えられた情報を使って応答します。サービスに保存された履歴の全体と、今回モデルが扱う文脈を同一視しないようにします。実際に引き継ぐ項目や長い履歴の扱いは、利用する API とモデルの仕様で確認します。

モデルが文章などを処理する単位をトークンと呼びます。トークン数は文字数と同じではなく、一度に扱える文脈にはモデルごとの上限があります。履歴や資料を無制限に渡すことはできません。入力が増えれば費用や処理時間にも影響します。

長くなった相談では、必要な履歴を選ぶ、確認済み事項を要約する、古い話題を別の会話へ分ける、といった設計を考えます。ただし、要約にも誤りが入り得ます。「OS は Windows」と「Windows かもしれない」を同じ確定情報へ変えないことが重要です。

9.5 会話、長期記憶、業務記録を分ける

情報目的今回の例
会話の履歴相談の流れを引き継ぐ質問、追加情報、過去の回答
今回の文脈今の応答に必要な材料を渡す関係する履歴と検索結果
長期記憶別の場面でも使う情報を保持・取得する許可された利用者の設定など
業務記録操作や許可の成立を確認する承認、登録先の ID、処理結果

最初の試作品に長期記憶を必須とする必要はありません。一つの相談を適切に継続するところから始めます。

また、会話に「承認をいただきました」と出力されたことは、利用者の承認の証拠ではありません。チケット登録へ発展させる場合、承認と登録結果は別の業務記録として扱います。この違いは付録で学びます。

9.6 小さな実習と確認課題

Conversation A と B の比較表を作り、「実際に渡した情報」「回答で使われた情報」「推測された情報」を分けてください。Azure を使わない場合も、同じ入力項目の一覧を作れます。

追加課題として、A の履歴から次の要約を作ります。

VPN に接続できない。OS は Windows。エラーの内容と、既に試した手順は未確認。

この要約に「再インストール済み」を勝手に足したら、次の回答にどのような影響が出るでしょうか。履歴を短くするだけでなく、事実と未確認事項を保つことが理解のポイントです。

9.7 まとめ

Agent の振る舞いは再利用できますが、相談の履歴は適切に分けます。保存、入力、記憶、業務の証拠も別です。次章では、この会話へ検索関数の要求と結果を加えます。

9.8 参考情報

[^runtime]: Build with runtime components in Foundry Agent Service — Microsoft

[^quickstart]: Quickstart: Create a prompt agent — Microsoft


前章:第8章 指示でエージェントの振る舞いを整える · 教材の目次へ戻る · 次章:第10章 Function calling で外部の処理を呼び出す