로컬 LLM으로 'Slay the Spire 2' 에이전트 구축하기: 교훈과 미해결 과제

✍️ OpenClawRadar📅 게시일: March 26, 2026🔗 Source
로컬 LLM으로 'Slay the Spire 2' 에이전트 구축하기: 교훈과 미해결 과제
Ad

개발자가 KoboldCPP/Ollama를 통해 로컬 LLM을 사용하여 Slay the Spire 2를 플레이하는 에이전트를 구축했습니다. 게임은 커뮤니티 모드를 통해 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_card, end_turn, use_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> 블록을 사용하지만, 때로는 생각과 도구 호출이 뒤섞입니다. 질문: 두 단계 접근 방식이 더 잘 작동할까요? 1단계: "게임 상태를 분석하고 무엇을 할지 결정하세요"(자유 텍스트). 2단계: "이제 정확히 하나의 도구 호출을 출력하세요"(제약됨). 이는 지연 시간을 두 배로 늘리지만 신뢰성을 향상시킬 수 있습니다. 이 패턴을 시도한 사람이 있을까요?
  • 모델 간 A/B 테스트 — 개발자는 비교를 위해 액션을 기록하는 JSONL 로깅 시스템을 가지고 있습니다.

📖 전체 소스 읽기: r/LocalLLaMA

Ad

👀 See Also

솔로 SaaS 창업자가 클로드의 프로젝트 지식을 활용해 매일 20~30분을 절약하는 방법
Use Cases

솔로 SaaS 창업자가 클로드의 프로젝트 지식을 활용해 매일 20~30분을 절약하는 방법

인도 중소기업을 위한 CRM을 운영하는 솔로 창업자($11.2K MRR)가 Claude의 프로젝트 지식 기능을 통해 매일 반복되던 컨텍스트 설정을 제품, 고객, 성장 도메인에 걸친 지속적이고 선별된 지식으로 대체한 방법을 공유합니다.

OpenClawRadar
개발자가 디자인 도구 없이 Claude AI로 앱 아이콘 디자인
Use Cases

개발자가 디자인 도구 없이 Claude AI로 앱 아이콘 디자인

한 개발자가 macOS 프로세스 관리자 'PIDKill'을 만들고, 그 앱 아이콘을 Claude AI, 특히 Claude Code와 Claude 웹만을 사용해 디자인했습니다. 최종 디자인은 프로세스 종료를 나타내기 위해 SF Mono 폰트에 글리치 효과와 빨간색 취소선을 사용합니다.

OpenClawRadar
개발자가 보고한 AI 코딩 과제: 설계 결정과 실제 사용자 디버깅
Use Cases

개발자가 보고한 AI 코딩 과제: 설계 결정과 실제 사용자 디버깅

iOS 앱을 Claude Code로 5개월간 개발한 한 개발자는 AI가 기능적인 코드를 쉽게 생성할 수 있지만, 디자인 결정과 실제 사용자에게만 나타나는 문제 디버깅이 가장 어려운 부분이라고 보고했습니다. 앱은 22만 줄의 코드를 보유하고 있으며 실제 사용자들이 테스트 중입니다.

OpenClawRadar
LLMs는 테라바이트 규모의 CI 로그를 분석하기 위해 SQL 쿼리를 몇 초 만에 생성합니다
Use Cases

LLMs는 테라바이트 규모의 CI 로그를 분석하기 위해 SQL 쿼리를 몇 초 만에 생성합니다

Mendral의 AI 에이전트가 자체 SQL 쿼리를 작성하여 불안정한 테스트를 3주 전의 의존성 업데이트로 추적했습니다. 수억 개의 로그 라인을 수십 개의 쿼리로 몇 초 만에 스캔했습니다. 이 시스템은 매주 15억 개의 CI 로그 라인을 처리하며, ClickHouse에서 35:1로 압축됩니다.

OpenClawRadar