Kei API JSON 파싱 실패 수정 + 이미지 경로 재탐색
1. kei_client.py _parse_json(): Kei가 마크다운 리스트 접두사(- )를 붙여 JSON 응답하는 경우 전처리하여 파싱. 원본 + 클린 버전 둘 다 시도. 2. image_utils.py: base_path와 상대경로가 이중으로 붙는 경우 파일명으로 rglob 재탐색하여 실제 파일 위치 찾기. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,15 @@ def get_image_sizes(content: str, base_path: str) -> list[dict[str, Any]]:
|
|||||||
if abs_path.suffix.lower() not in IMAGE_EXTENSIONS:
|
if abs_path.suffix.lower() not in IMAGE_EXTENSIONS:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# 경로가 이중으로 붙는 경우 방어 (base가 이미 하위 폴더를 포함할 때)
|
||||||
|
if not abs_path.exists():
|
||||||
|
# rel_path에서 파일명만 추출하여 base 하위에서 재검색
|
||||||
|
filename = Path(rel_path).name
|
||||||
|
found = list(base.rglob(filename))
|
||||||
|
if found:
|
||||||
|
abs_path = found[0]
|
||||||
|
logger.info(f"이미지 경로 재탐색 성공: {filename} → {abs_path}")
|
||||||
|
|
||||||
if not abs_path.exists():
|
if not abs_path.exists():
|
||||||
logger.warning(f"이미지 파일 미발견: {abs_path}")
|
logger.warning(f"이미지 파일 미발견: {abs_path}")
|
||||||
images.append({
|
images.append({
|
||||||
|
|||||||
@@ -217,19 +217,38 @@ async def _call_anthropic_direct(content: str) -> dict[str, Any] | None:
|
|||||||
|
|
||||||
|
|
||||||
def _parse_json(text: str) -> dict[str, Any] | None:
|
def _parse_json(text: str) -> dict[str, Any] | None:
|
||||||
"""텍스트에서 JSON을 추출한다."""
|
"""텍스트에서 JSON을 추출한다.
|
||||||
patterns = [
|
|
||||||
r"```json\s*(.*?)```",
|
Kei API가 마크다운 리스트 접두사(- )를 붙여 응답하는 경우에도 처리.
|
||||||
r"```\s*(.*?)```",
|
"""
|
||||||
r"(\{.*\})",
|
# 전처리: 각 줄 앞의 마크다운 리스트 접두사(- ) 제거
|
||||||
]
|
# Kei API가 JSON을 마크다운 리스트로 감싸서 응답하는 경우 대응
|
||||||
for pattern in patterns:
|
lines = text.split("\n")
|
||||||
match = re.search(pattern, text, re.DOTALL)
|
cleaned_lines = []
|
||||||
if match:
|
for line in lines:
|
||||||
try:
|
stripped = line.lstrip()
|
||||||
return json.loads(match.group(1).strip())
|
if stripped.startswith("- "):
|
||||||
except json.JSONDecodeError:
|
cleaned_lines.append(stripped[2:])
|
||||||
continue
|
elif stripped.startswith("* "):
|
||||||
|
cleaned_lines.append(stripped[2:])
|
||||||
|
else:
|
||||||
|
cleaned_lines.append(stripped)
|
||||||
|
cleaned = "\n".join(cleaned_lines)
|
||||||
|
|
||||||
|
# 원본 + 클린 버전 둘 다 시도
|
||||||
|
for target in [text, cleaned]:
|
||||||
|
patterns = [
|
||||||
|
r"```json\s*(.*?)```",
|
||||||
|
r"```\s*(.*?)```",
|
||||||
|
r"(\{.*\})",
|
||||||
|
]
|
||||||
|
for pattern in patterns:
|
||||||
|
match = re.search(pattern, target, re.DOTALL)
|
||||||
|
if match:
|
||||||
|
try:
|
||||||
|
return json.loads(match.group(1).strip())
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
continue
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user