From c59c934ff58d01ebcb252e970a3b05e4b8c80e27 Mon Sep 17 00:00:00 2001 From: Variet Agent Date: Mon, 23 Mar 2026 20:43:41 +0900 Subject: [PATCH] fix(discord_bot): unified prompt JSON '{' parsing fallback --- .agent/references/STATUS.md | 1 + .agent/references/known-issues.md | 6 ++++++ _test_classify.py | 20 +++----------------- api/discord_bot.py | 12 ++++++++++++ docs/devlog/2026-03-23.md | 3 +++ 5 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 docs/devlog/2026-03-23.md diff --git a/.agent/references/STATUS.md b/.agent/references/STATUS.md index cb22315..47f7fac 100644 --- a/.agent/references/STATUS.md +++ b/.agent/references/STATUS.md @@ -74,6 +74,7 @@ Discord 메시지 ## 최근 마일스톤 +- **2026-03-23**: discord_bot unified prompt JSON 문법 누락 대응 로직 추가 - **2026-03-22**: debate-agent idle-state 처리 — 대기 규칙 + slug 탐색 + list-debates + handler 시그널 개선 - **2026-03-21**: debate-agent 분산 토론 시스템 — Wiki.js 기반 통신, AG 프로젝트 스캐폴딩, handler 리팩토링 - **2026-03-20**: AI Debate Room v2 — 파일 기반 자동 토론 + Flash 합의 판정 + Wiki.js 동기화 diff --git a/.agent/references/known-issues.md b/.agent/references/known-issues.md index c46a52b..882a76c 100644 --- a/.agent/references/known-issues.md +++ b/.agent/references/known-issues.md @@ -183,3 +183,9 @@ - **원인**: Gemini에게 제목 요약 요청 시 `"신용리스크를 측정하는..."` 처럼 따옴표 포함 응답 → `WikiClient.slugify()`가 따옴표 미제거 - **해결**: (1) 프롬프트를 영문 2-3단어 키워드로 변경, (2) `.strip('"\'')` + `re.sub(r'[^\w\s-]', '')` 로 특수문자 제거, (3) slug 30자 제한 - **주의**: AI 응답을 slug/경로/파일명에 사용 시 **반드시 특수문자 sanitize** 필수. 따옴표, 괄호, 마크다운 기호 등 모두 제거 + +### [2026-03-23] unified prompt — JSON 여는 중괄호 누락 +- **증상**: Gemini 응답에 `{"mode": ...}` 대신 `"mode": ...}`로 출력되어 JSON 파싱이 실패하고 chat 롤백됨 +- **원인**: 통합 프롬프트 특성상 LLM이 가끔 첫 `{`를 생략하거나 코드문법 없이 바로 출력함 +- **해결**: `api/discord_bot.py` 의 `_parse_unified_response` 에 `{` 누락 시 `{...}` 로 감싸 재파싱하는 fallback 추가 +- **주의**: LLM의 JSON 출력 포맷이 항상 완벽할 것이라 가정하지 말고 방어적 파싱 로직 적용 필수 diff --git a/_test_classify.py b/_test_classify.py index 2ae221c..c739b37 100644 --- a/_test_classify.py +++ b/_test_classify.py @@ -8,25 +8,11 @@ sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="repla sys.path.insert(0, ".") from core.gemini_caller import GeminiCaller - +from api.discord_bot import _parse_unified_response def extract_mode(raw): - start = raw.find("{") - if start == -1: - return "NO_JSON" - depth = 0 - for i in range(start, len(raw)): - if raw[i] == "{": - depth += 1 - elif raw[i] == "}": - depth -= 1 - if depth == 0: - try: - p = json.loads(raw[start : i + 1]) - return p.get("mode", "?") - except json.JSONDecodeError: - return "PARSE_ERR" - return "NO_CLOSE" + parsed = _parse_unified_response(raw) + return parsed.get("mode", "?") async def main(): diff --git a/api/discord_bot.py b/api/discord_bot.py index 6255877..c949855 100644 --- a/api/discord_bot.py +++ b/api/discord_bot.py @@ -183,6 +183,18 @@ def _parse_unified_response(raw: str) -> dict: except json.JSONDecodeError: break + # 2.5) JSON 시작 중괄호 누락 복구 + raw_s = raw.strip() + if raw_s.startswith('"mode"'): + if not raw_s.startswith("{"): + raw_s = "{" + raw_s + if not raw_s.endswith("}"): + raw_s = raw_s + "}" + try: + return json.loads(raw_s, strict=False) + except json.JSONDecodeError: + pass + # 3) 파싱 실패 → chat 모드 폴백 logger.warning(f"unified 응답 JSON 파싱 실패: {raw[:200]}") return {"mode": "chat", "response": raw} diff --git a/docs/devlog/2026-03-23.md b/docs/devlog/2026-03-23.md new file mode 100644 index 0000000..d341194 --- /dev/null +++ b/docs/devlog/2026-03-23.md @@ -0,0 +1,3 @@ +| # | 시간 | 작업 | 커밋 | 상태 | +|----|------|------|------|------| +| 001 | 20:42 | api/discord_bot.py 통함 프롬프트 JSON 파싱 '{' 누락 버그 수정 | `TBD` | ✅ |