fix: AIPlanner에서 GLM 모델 버전 변경 및 JSON 응답 처리 개선
- GLM 모델 버전을 "GLM-4.7"에서 "GLM-4.5-Air"로 변경 - JSON 응답 처리 시, 재시도 시 max_tokens 및 temperature 조정 로직 추가하여 JSON 포맷 준수율 향상 - README.md에 변경 사항 반영
This commit is contained in:
@@ -146,6 +146,7 @@ planner.set_goal(
|
||||
- `agent_log.jsonl`에 모든 행동과 타임스탬프가 기록됩니다
|
||||
- `ai_planner.py`는 GLM 응답이 잘리거나(중괄호/대괄호 불일치) 마크다운이 섞여도 JSON 파싱을 복구하도록 `{} / []` 균형 추적과 보정 로직을 사용합니다. 또한 최상위에서 JSON 배열(`[...]`)로 답하는 경우도 `actions`로 래핑해 처리합니다. (추가) `finish_reason=length` 등으로 `message.content`가 비거나(또는 JSON 형태가 아니면) `message.reasoning_content`를 우선 사용합니다. 그리고 응답 안에 여러 개의 `{...}`가 섞여 있어도 그중 `actions`를 포함한 계획 객체를 우선 선택합니다. 또한 JSON 파싱 실패가 감지되면 다음 재시도에는 `JSON-only repair` 프롬프트를 덧붙여 모델이 스키마를 다시 따르도록 유도합니다.
|
||||
- 재시도(attempt>0)에서는 `max_tokens`를 줄여(기본 `900`) 분석 텍스트가 길어져 JSON이 잘리는 패턴을 줄입니다.
|
||||
- `JSON-only repair` 프롬프트가 붙는 경우에는 `max_tokens`를 더 낮추고(기본 `600`) `temperature`도 더 낮춰(JSON 포맷 준수율을 올리려) 요청합니다.
|
||||
- `ai_planner.py`의 `AIPlanner.decide()`는 `TimeoutError`/`ConnectionError`/`urllib.error.URLError` 같은 GLM HTTP 지연/연결 오류도 3회 재시도한 뒤, **상태 요약에 나온 광맥(앵커) 좌표가 있으면 `mine_resource`(먼 경우 `move` 후 채굴)로 폴백**하고, 광맥 정보가 없을 때만 `explore` 방향을 순환하며 탐색합니다(동일 방향 탐색 루프 완화).
|
||||
- GLM이 `HTTP 429 (Rate limit)`에 걸리면 `Retry-After`가 있으면 그만큼 기다렸다가(없으면 기본 백오프) 재시도하도록 처리합니다.
|
||||
- GLM HTTP 읽기 제한 시간은 기본 120초이며, `GLM_HTTP_TIMEOUT_SECONDS`로 조정할 수 있습니다. 광맥은 플레이어와 200타일 이상 떨어진 경우에만 폴백에서 `move`를 끼우며, 임계값은 `GLM_FALLBACK_MOVE_THRESHOLD`(기본 200)로 바꿀 수 있습니다.
|
||||
|
||||
@@ -22,7 +22,7 @@ import traceback
|
||||
|
||||
|
||||
GLM_API_URL = "https://api.z.ai/api/coding/paas/v4/chat/completions"
|
||||
GLM_MODEL = "GLM-4.7"
|
||||
GLM_MODEL = "GLM-4.5-Air"
|
||||
|
||||
|
||||
SYSTEM_PROMPT = """당신은 팩토리오 게임을 순수하게 플레이하는 AI 에이전트입니다.
|
||||
@@ -355,9 +355,21 @@ class AIPlanner:
|
||||
def _call_glm(self, user_message: str, attempt: int) -> str:
|
||||
# attempt가 올라갈수록 "분석 텍스트"가 길어지면서 JSON이 잘리는 패턴이 있어
|
||||
# retry에서는 출력 길이를 줄인다.
|
||||
repair_mode = "JSON 요구사항을 위반했습니다" in user_message or "응답의 첫 비공백 문자는 반드시" in user_message
|
||||
|
||||
base_max_tokens = int(os.environ.get("GLM_MAX_TOKENS", "2000"))
|
||||
retry_max_tokens = int(os.environ.get("GLM_RETRY_MAX_TOKENS", "900"))
|
||||
max_tokens = base_max_tokens if attempt == 0 else min(base_max_tokens, retry_max_tokens)
|
||||
repair_max_tokens = int(os.environ.get("GLM_REPAIR_MAX_TOKENS", "600"))
|
||||
|
||||
if repair_mode:
|
||||
max_tokens = repair_max_tokens
|
||||
else:
|
||||
max_tokens = base_max_tokens if attempt == 0 else min(base_max_tokens, retry_max_tokens)
|
||||
|
||||
temperature = 0.3
|
||||
if repair_mode:
|
||||
# JSON 포맷 준수율을 높이기 위해 변동성을 낮춘다.
|
||||
temperature = float(os.environ.get("GLM_REPAIR_TEMPERATURE", "0.1"))
|
||||
|
||||
payload = json.dumps({
|
||||
"model": GLM_MODEL,
|
||||
@@ -365,7 +377,7 @@ class AIPlanner:
|
||||
{"role": "system", "content": SYSTEM_PROMPT},
|
||||
{"role": "user", "content": user_message},
|
||||
],
|
||||
"temperature": 0.3,
|
||||
"temperature": temperature,
|
||||
"max_tokens": max_tokens,
|
||||
}).encode("utf-8")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user