修仙ゲームにおけるDeepseek APIを活用した戦術アシスト機能の実装

実装概要

修仙テーマのボス戦において、プレイヤーが/adviceコマンドを実行した際に、現在のカード状況に基づいた戦術アドバイスを提供する機能を実装します。Deepseek APIを介した言語モデル呼び出しを経て、自然言語のアドバイスを生成する処理を構築します。

プロジェクト構成

必要なファイル構造と依存関係を設定します。

game_root/
├── .env
├── prompts/
│   └── strategy_template.txt
└── src/
    └── core/
        └── tactics/
            └── advisor.py

依存パッケージ (requirements.txt)

langchain-core==1.0.10
langchain-openai==1.0.10
python-dotenv==1.0.0

テンプレートファイルの設計

prompts/strategy_template.txtにゲーム状況を反映するプロンプトを定義します。

修仙の達人として、心魔との戦いに臨む道友を助ける立場です。
戦闘ルール:
- 善/悪/中立のカードを1~3枚伏せて出し、宣言します。万能カードは任意の属性を偽装可能です
- 相手は検証・追随・放棄のいずれかを選択
- 手札を先に無くした方が勝利

現在の戦況:
- 自分の手札:善{zenshin}枚、悪{akushin}枚、中立{chuuryoku}枚、万能{tensei}枚
- 相手の残り手札:{enemy_count}枚
- テーブル上のカード:{table_count}枚
- 直前の相手宣言:{previous_claim}
- 現在のターン:{current_phase}

状況を分析し、簡潔なアドバイスを1文で出力してください。例:「相手は虚勢を張っている可能性、検証を推奨」

実装コード

src/core/tactics/advisor.pyに以下の処理を実装します。

import logging
from pathlib import Path
from typing import Dict, Optional
from dotenv import load_dotenv
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

# 環境設定の読み込み
load_dotenv()

# テンプレートファイルの取得
TEMPLATE_FILE = Path(__file__).parent.parent.parent.parent / "prompts" / "strategy_template.txt"
PROMPT_TEMPLATE = TEMPLATE_FILE.read_text(encoding="utf-8")

def generate_tactical_advice(
    self_hand: Dict[str, int],
    enemy_hand: int,
    table_cards: int,
    last_declaration: Optional[str],
    is_my_turn: bool
) -> Optional[str]:
    """
    戦況データを基にDeepseek APIを呼び出し、戦術アドバイスを生成
    エラー発生時はNoneを返す
    """
    try:
        # モデルの初期化(スコープを関数内に限定)
        model = ChatOpenAI(
            model_name="deepseek-chat",
            temperature=0.15,
            base_url="https://api.deepseek.com/v1",
            api_key=os.getenv("DEEPSEEK_API_KEY"),
            request_timeout=25
        )
        
        # プロンプトの動的生成
        phase = "行動" if is_my_turn else "対応"
        prompt = PromptTemplate.from_template(PROMPT_TEMPLATE).format(
            zenshin=self_hand.get("good", 0),
            akushin=self_hand.get("evil", 0),
            chuuryoku=self_hand.get("neutral", 0),
            tensei=self_hand.get("wild", 0),
            enemy_count=enemy_hand,
            table_count=table_cards,
            previous_claim=last_declaration or "なし",
            current_phase=phase
        )
        
        # API呼び出しと結果処理
        result = model.invoke(prompt)
        return result.content.strip() if result.content else None
        
    except Exception as error:
        logging.getLogger("tactics").exception("アドバイス生成に失敗: %s", error)
        return None

実装のポイント

  • パス管理:pathlibを活用した相対パスの安全な取得
  • スコープ制限:LLMインスタンスを関数内に限定し、不要なリソース保持を防止
  • 安全なフォーマット:辞書のgetメソッドでデフォルト値を指定
  • タイムアウト設定:25秒でリクエストを中断し、ゲームフローを阻害しない設計

実行テスト

デバッグ用に簡易テストを追加可能:

if __name__ == "__main__":
    sample_hand = {"good": 4, "evil": 2, "neutral": 3, "wild": 1}
    advice = generate_tactical_advice(
        self_hand=sample_hand,
        enemy_hand=8,
        table_cards=5,
        last_declaration="neutral",
        is_my_turn=True
    )
    print(f"戦術アドバイス: {advice}")

タグ: deepseek-api LangChain python-dotenv game-ai template-engine

8月6日 17:37 投稿