ローカルLLMで『Slay the Spire 2』エージェントを構築:学びと未解決課題

✍️ OpenClawRadar📅 公開日: March 26, 2026🔗 Source
ローカルLLMで『Slay the Spire 2』エージェントを構築:学びと未解決課題
Ad

ある開発者が、KoboldCPP/Ollamaを介したローカルLLMを使用して『Slay the Spire 2』をプレイするエージェントを構築しました。ゲームはコミュニティ製MODを通じてREST APIとして公開されており、エージェントは中間に位置して動作します:ゲーム状態を読み取る → ツール付きでLLMを呼び出す → アクションを実行する → 繰り返す。

セットアップとパフォーマンス

セットアップでは、KoboldCPP経由でRTX 4090上でQwen3.5-27B(Q4_K_M)を使用しています。パフォーマンス指標:アクションあたり約10秒、アクション成功率約88%。最高の結果:Act 1のボスを倒すこと。プロジェクトはGitHubで公開されています:https://github.com/Alex5418/STS2-Agent

機能している点

  • 状態ベースのツールルーティング — 20以上のツールを一度に公開する代わりに、現在のゲーム状態に関連する1〜3つのツールのみを提供します。戦闘ではplay_cardend_turnuse_potionを、マップ画面ではchoose_map_nodeを提供します。これにより、幻覚的なツール呼び出しが劇的に減少しました。
  • シングルツールモード — 小規模モデルは、アクション後のゲーム状態の変化(例:カードをプレイした後のカードインデックスのシフト)を予測できません。そのため、応答ごとに最初のツール呼び出しのみを実行し、その後ゲーム状態を再取得してモデルに再度問い合わせます。遅くなりますが、はるかに信頼性が高まります。
  • テキストベースのツール呼び出しパーサー(フォールバック) — KoboldCPPは、構造化されたJSONではなくテキストとしてツール呼び出しを出力することがよくあります。複数パターンの正規表現フォールバックにより、json [{"name": "play_card", "arguments": {...}}]Made a function call ... to play_card with arguments = {...}play_card({"card_index": 1, "target": "NIBBIT_0"})、およびend_turnのような引数なしツールの単純な言及などの形式を捕捉します。これにより、本来失われるであろうアクションの約15〜20%を回復できます。
  • エネルギーガード — 残りのエネルギーをクライアント側で追跡します。モデルが支払えないカードをプレイしようとすると、API呼び出しがブロックされ、ターンが自動的に終了します。これにより、最も一般的なエアループ(モデルが同じ支払えないカードを3回以上再試行する)を防止します。
  • 敵ターン中のスマートウェイト — 敵のターン中、ゲーム状態は「Play Phase: False」と表示されます。これに対してLLM呼び出しを無駄にする代わりに、エージェントはプレイヤーのターンに戻るまで1秒ごとにポーリングします。
Ad

未解決の問題

  • モデルがシステムプロンプトのルールに一貫して従わない — システムプロンプトには「敵の意図が攻撃の場合は、まず防御カードをプレイする」などの指示があります。モデルがこれに従うのはおそらく30%の時間です。残りの70%では、関係なく攻撃をプレイします。試みられた解決策:より強い表現(「あなたはまずブロックしなければならない」)、プロンプト内の少数ショット例、計算されたヒントの注入(「警告:15の受けるダメージ」)。どれも信頼性がありません。質問:小規模モデルに条件付きルールを遵守させるためのより良いプロンプト戦略はありますか?それともこれは27Bでの根本的な制限ですか?
  • KoboldCPPでのツール呼び出しの信頼性 — テキストフォールバックパーサーを使用しても、応答の約12%は使用可能なツール呼び出しを生成しません。モデルは時々空の<think></think>ブロックに続いて不正なJSONを出力します。OllamaのOpenAI互換レイヤーも、argumentsを辞書ではなく文字列として返すことがあります。質問:14〜30B範囲でツール呼び出しに特に信頼性の高いモデルを見つけた人はいますか?開発者はPhi-4(14B)を簡単に試しましたが、適切な比較は行っていません。Mistral-SmallやCommand-Rを検討中です。
  • コンテキストウィンドウの管理 — 各ゲーム状態はマークダウンとして約800〜1500トークンです。システムプロンプト(約500トークン)と会話履歴を考慮すると、コンテキストはすぐに埋まります。現在は最後の5回のやり取りのみを保持し、状態遷移(戦闘→マップなど)で履歴をリセットしています。しかし、モデルは戦闘間で記憶を持たないため、失敗から学ぶことができません。質問:ローリングサマリーアプローチは機能しますか?例えば、最後の戦闘を「あなたはJaw Wormと戦った。ターン2にブロックしなかったため15のダメージを受けた。4ターンで勝利した」と要約する方法です。
  • ローカルモデルからのより良い構造化出力 — 核心の問題は、モデルにJSONツール呼び出しを出力させる必要があることですが、モデルが本当にやりたいことは最初に自然言語で考えることです。Qwen3.5は<think>ブロックを使用しますが、これは除去されます。ただし、思考とツール呼び出しが絡み合うことがあります。質問:2段階アプローチの方がより効果的でしょうか?ステージ1:「ゲーム状態を分析し、何をするか決定する」(自由テキスト)。ステージ2:「正確に1つのツール呼び出しを出力する」(制約付き)。これにより遅延は倍増しますが、信頼性が向上するかもしれません。このパターンを試した人はいますか?
  • モデル間でのA/Bテスト — 開発者は、比較用にアクションを記録するJSONLロギングシステムを持っています。

📖 完全なソースを読む: r/LocalLLaMA

Ad

👀 See Also

研究者が学術的スコーピングレビューにClaude Projectsを活用:強みと限界
Use Cases

研究者が学術的スコーピングレビューにClaude Projectsを活用:強みと限界

研究者は、高等教育における学生の生成AI体験に関する39の質的インタビュー研究のピアレビュー済みスコーピングレビューにおいて、Claude Projectsを支援ツールとして使用しました。このツールは、テーマの相互参照や分析カテゴリーの提案において特定の強みを示しましたが、元データに対する厳密な検証が必要でした。

OpenClawRadar
Claude エンジニアリングコンプライアンス向け:6ヶ月ワークフロー内訳
Use Cases

Claude エンジニアリングコンプライアンス向け:6ヶ月ワークフロー内訳

ある技術系企業が、ClaudeのProjects、Artifacts、制約遵守機能を活用して、顧客向け仕様書でのハルシネーションを回避する方法を紹介。

OpenClawRadar
デザイナーがClaude CLIでフルスタックプラットフォームを構築:正式なコーディング経験ゼロからの学び
Use Cases

デザイナーがClaude CLIでフルスタックプラットフォームを構築:正式なコーディング経験ゼロからの学び

WordPressの経験を持つデザイナーがClaude CLIを使用して、500件以上のイベント登録、3,500人以上の制限エリアユーザー、100以上のeラーニングコースを扱う医学雑誌管理プラットフォームを構築しました。重要な教訓には、デバッグ用に別のAIインスタンスを使用することと、すべてをGitHubでバージョン管理することが含まれます。

OpenClawRadar
Telegramトピックを使用した無制限の並列AIエージェント会話
Use Cases

Telegramトピックを使用した無制限の並列AIエージェント会話

ある開発者が、Telegramグループをフォーラムに変換することで、各トピックがAIエージェントの独立したセッションとして機能し、追加のボットやトークンを作成することなく無制限の並列会話を可能にすることを発見しました。

OpenClawRadar