From 1d0522dc33df2b21fa3c9d53b8a025a183f9f1e6 Mon Sep 17 00:00:00 2001 From: 21in7 Date: Fri, 27 Mar 2026 20:23:22 +0900 Subject: [PATCH] feat: standardize parameters for mine_resource action in AIPlanner to improve error handling and compatibility with LM Studio responses --- README.md | 1 + __pycache__/ai_planner.cpython-311.pyc | Bin 19462 -> 37255 bytes ai_planner.py | 53 +++++++++++++++++++++++++ docs/plan.md | 17 ++++++++ 4 files changed, 71 insertions(+) diff --git a/README.md b/README.md index 4713cc8..3801d1e 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ planner.set_goal( - LM Studio `input-only` 모드에서 `output[].type=reasoning` 형태로 응답이 오는 경우도 파서가 처리하며, 응답 텍스트에 JSON 앞뒤 설명이 섞이면 `{...}` 구간을 복구 추출해 파싱을 시도합니다(복구 불가 시 기존 휴리스틱 폴백). - 파싱된 계획은 `actions` 스키마와 지원 action 화이트리스트를 통과한 경우에만 채택합니다. 유효 액션이 없거나 형식이 깨지면 LLM 출력을 버리고 상태 기반 휴리스틱 폴백으로 전환해 `알 수 없는 행동` 루프를 줄입니다. - LM Studio가 표준과 다른 동의어를 반환할 때(예: `place_building`, `target_x/target_y`, `position_x/position_y`), planner가 표준 스키마(`place_entity`, `x/y`, `name`)로 자동 정규화한 뒤 검증합니다. +- 특히 `mine_resource`는 실행기 시그니처에 맞게 `ore`, `count`만 남기도록 강제 정규화합니다. `resource`/`item`은 `ore`로 매핑하고 `tile`/`target` 같은 비표준 키는 제거해 `unexpected keyword argument` 오류를 방지합니다. - `ai_planner.py`는 LLM이 move 순서를 놓쳐 `place_entity`/`insert_to_entity`/`set_recipe`가 건설 거리 제한으로 실패하는 경우를 줄이기 위해, 해당 액션 직전에 최근 `move`가 같은 좌표가 아니면 자동으로 `move`를 끼워 넣습니다 - `agent_log.jsonl`에 모든 행동과 타임스탬프가 기록됩니다 - `ai_planner.py`는 GLM 응답이 잘리거나(중괄호/대괄호 불일치) 마크다운이 섞여도 JSON 파싱을 복구하도록 `{} / []` 균형 추적과 보정 로직을 사용합니다. 또한 최상위에서 JSON 배열(`[...]`)로 답하는 경우도 `actions`로 래핑해 처리합니다. (추가) `finish_reason=length` 등으로 `message.content`가 비거나(또는 JSON 형태가 아니면) `message.reasoning_content`를 우선 사용합니다. 그리고 응답 안에 여러 개의 `{...}`가 섞여 있어도 그중 `actions`를 포함한 계획 객체를 우선 선택합니다. 또한 JSON 파싱 실패가 감지되면 다음 재시도에는 `JSON-only repair` 프롬프트를 덧붙여 모델이 스키마를 다시 따르도록 유도합니다. diff --git a/__pycache__/ai_planner.cpython-311.pyc b/__pycache__/ai_planner.cpython-311.pyc index 18bfa877fac00a69d04a2cea2ba3088cf9467649..3bfaa9b21a81904636ee8173baa352a4dfa6c0a2 100644 GIT binary patch literal 37255 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 dict: + return {k: v for k, v in params.items() if k in allowed} + + @staticmethod + def _normalize_ore_name(value: object) -> str: + if not isinstance(value, str): + return "iron-ore" + key = value.strip().lower() + return ORE_ALIASES.get(key, "iron-ore") + @staticmethod def _ensure_move_before_build_actions(actions: list[dict]) -> list[dict]: """ diff --git a/docs/plan.md b/docs/plan.md index 7122604..ff3d338 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -87,6 +87,23 @@ --- +## 2026-03-27 mine_resource 파라미터 강제 표준화 계획 + +### 문제 요약 +- LM Studio가 `mine_resource`에 `tile`, `target`, `resource` 같은 비표준 키를 보내면서 실행기(`mine_resource(ore, count)`)에서 TypeError 발생. + +### 구현 계획 +1. `ai_planner.py`에서 `mine_resource`는 `ore`, `count`만 남기도록 필터링한다. +2. `resource`/`item` 동의어를 `ore`로 매핑하고, `iron`/`copper` 같은 축약값도 정규 ore 이름으로 보정한다. +3. `count`가 없거나 비정상이면 기본값(35)으로 보정한다. +4. README에 `mine_resource` 파라미터 표준화 동작을 반영한다. + +### 검증 계획 +- `python -m py_compile ai_planner.py` +- 런타임에서 `unexpected keyword argument 'tile'/'target'`가 사라지는지 확인 + +--- + ## 채굴 시 mining_state 반복 설정 제거 (우클릭 유지) ### 문제