Skip to content

Commit 812891d

Browse files
committed
Fix JSON parsing to handle markdown-wrapped responses from Claude/Gemini
Some LLMs (especially Claude and Gemini) wrap JSON responses in markdown code blocks: ```json {...} ``` Updated _parse_llm_response to: - Strip markdown code block markers - Handle both plain JSON and markdown-wrapped JSON - Improved error logging with both original and cleaned content This fixes the "LLM did not return valid JSON" error when using Anthropic or Gemini providers.
1 parent 74200eb commit 812891d

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

services/hrms-tools/app/services/cv_analyzer.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,23 @@ def _parse_llm_response(self, llm_content: str) -> Dict[str, Any]:
191191
CVAnalyzerError: If parsing fails
192192
"""
193193
try:
194+
# Clean the content - some LLMs wrap JSON in markdown code blocks
195+
cleaned_content = llm_content.strip()
196+
197+
# Remove markdown code block markers if present
198+
if cleaned_content.startswith('```'):
199+
# Find the first newline after opening ```
200+
first_newline = cleaned_content.find('\n')
201+
if first_newline != -1:
202+
# Remove opening ``` and language identifier
203+
cleaned_content = cleaned_content[first_newline + 1:]
204+
205+
# Remove closing ```
206+
if cleaned_content.endswith('```'):
207+
cleaned_content = cleaned_content[:-3].rstrip()
208+
194209
# Try to parse as JSON
195-
result = json.loads(llm_content)
210+
result = json.loads(cleaned_content)
196211

197212
# Validate required fields
198213
required_fields = [
@@ -208,7 +223,8 @@ def _parse_llm_response(self, llm_content: str) -> Dict[str, Any]:
208223

209224
except json.JSONDecodeError as e:
210225
logger.error(f"Failed to parse LLM response as JSON: {e}")
211-
logger.error(f"LLM response content: {llm_content[:500]}...")
226+
logger.error(f"LLM response content (first 500 chars): {llm_content[:500]}...")
227+
logger.error(f"Cleaned content (first 500 chars): {cleaned_content[:500] if 'cleaned_content' in locals() else 'N/A'}...")
212228
raise CVAnalyzerError("LLM did not return valid JSON. Please try again.")
213229

214230
def _build_response(

0 commit comments

Comments
 (0)