{"record":{"id":"3222be80058260cc","repo":"datawhalechina/hello-agents","slug":"json-3222be","errorCode":null,"errorMessage":"响应中未找到JSON数据","messagePattern":"响应中未找到JSON数据","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"code/chapter13/helloagents-trip-planner/backend/app/agents/trip_planner_agent.py","lineNumber":356,"sourceCode":"        \"\"\"\n        try:\n            # 尝试从响应中提取JSON\n            # 查找JSON代码块\n            if \"```json\" in response:\n                json_start = response.find(\"```json\") + 7\n                json_end = response.find(\"```\", json_start)\n                json_str = response[json_start:json_end].strip()\n            elif \"```\" in response:\n                json_start = response.find(\"```\") + 3\n                json_end = response.find(\"```\", json_start)\n                json_str = response[json_start:json_end].strip()\n            elif \"{\" in response and \"}\" in response:\n                # 直接查找JSON对象\n                json_start = response.find(\"{\")\n                json_end = response.rfind(\"}\") + 1\n                json_str = response[json_start:json_end]\n            else:\n                raise ValueError(\"响应中未找到JSON数据\")\n            \n            # 解析JSON\n            data = json.loads(json_str)\n            \n            # 转换为TripPlan对象\n            trip_plan = TripPlan(**data)\n            \n            return trip_plan\n            \n        except Exception as e:\n            print(f\"⚠️  解析响应失败: {str(e)}\")\n            print(f\"   将使用备用方案生成计划\")\n            return self._create_fallback_plan(request)\n    \n    def _create_fallback_plan(self, request: TripRequest) -> TripPlan:\n        \"\"\"创建备用计划(当Agent失败时)\"\"\"\n        from datetime import datetime, timedelta\n        ","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/code/chapter13/helloagents-trip-planner/backend/app/agents/trip_planner_agent.py#L338-L374","documentation":"ValueError raised by the trip planner's response parser when the LLM reply contains none of the expected JSON carriers: no ```json fence, no bare ``` fence, and no { ... } braces. It is the terminal branch of a three-way extraction strategy; the outer except then logs '解析响应失败' and falls back to a template-based plan.","triggerScenarios":"The model answers entirely in prose ('I cannot plan this trip...'); refusal or safety preamble with no braces; response truncated before any JSON object appeared; model outputting a JSON array only ([...]) which contains no braces.","commonSituations":"Weak base model ignoring the structured-output instruction; context overflow truncating the reply; API error text captured as the 'response'; non-English reply with no structured section.","solutions":["Check what the model actually returned (print the raw response) — this decides everything","Make the prompt demand pure JSON with no prose and include a schema/few-shot example; consider response_format={'type':'json_object'} if the provider supports it","Retry once with the failed output quoted back and 'respond ONLY with JSON' instruction","If fallbacks are acceptable, rely on the existing fallback path but log the raw response for diagnosis"],"exampleFix":"# before\nsystem = '你是旅行规划助手'  # vague -> prose replies -> ValueError\n\n# after\nsystem = '你是旅行规划助手。你必须只输出一个JSON对象,不要输出任何其他文字,顶层键为: title, days, budget, itinerary.'","handlingStrategy":"fallback","validationCode":"import json, re\n\ndef try_extract_json(text: str):\n    m = re.search(r'\\{.*\\}', text, re.S)\n    if not m:\n        return None\n    try:\n        return json.loads(m.group(0))\n    except json.JSONDecodeError:\n        return None","typeGuard":null,"tryCatchPattern":"try:\n    plan = parse_trip_plan(response)\nexcept (ValueError, json.JSONDecodeError, TypeError):\n    print('falling back to template plan')\n    plan = template_plan(request)  # existing fallback path","preventionTips":["Demand JSON-only output in the system prompt with a concrete schema","Use response_format={'type':'json_object'} where the provider supports it","Keep the fallback path, but log raw responses so fallback frequency is observable"],"tags":["llm","json-parsing","fallback","agent"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}