From e317547b8b5e75eff893cbde3a2e1c74800871bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=BB=E6=B1=89=E7=86=99?= <3218485270@qq.com> Date: Mon, 24 Aug 2026 15:50:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Pinterest=20=E5=88=86?= =?UTF-8?q?=E6=9E=90=E8=8A=82=E7=82=B9=EF=BC=9A1)=20openai=20=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E5=85=BC=E5=AE=B9=20LLM=20=E8=BF=94=E5=9B=9E=E8=A3=B8?= =?UTF-8?q?=E6=95=B0=E7=BB=84=EF=BC=88[...]=EF=BC=89=E8=80=8C=E9=9D=9E=20{?= =?UTF-8?q?designs:[...]}=EF=BC=8C=E9=81=BF=E5=85=8D=20'list'=20object=20h?= =?UTF-8?q?as=20no=20attribute=20'get'=20=E5=B4=A9=E6=BA=83=EF=BC=9B2)=20m?= =?UTF-8?q?ock=20=E5=85=9C=E5=BA=95=E6=94=B9=E4=B8=BA=E7=9C=9F=E6=AD=A3?= =?UTF-8?q?=E8=B0=83=E7=94=A8=20mock=20=E5=90=8E=E7=AB=AF=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E9=87=8D=E5=A4=8D=E8=B0=83=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84=20openai=20=E5=90=8E=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graph/llms/openai_compat_backend.py | 9 ++++++++- graph/nodes/pinterest_analyze_node.py | 8 +++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/graph/llms/openai_compat_backend.py b/graph/llms/openai_compat_backend.py index 3e590d5..17300e0 100644 --- a/graph/llms/openai_compat_backend.py +++ b/graph/llms/openai_compat_backend.py @@ -593,7 +593,14 @@ class OpenAICompatBackend(LLMBackend): print(f"[pinterest_analyze] 解析失败: {e}") return [] designs = [] - for i, d in enumerate(parsed.get("designs") or []): + # 兼容 LLM 返回裸数组([...])或 {designs: [...]} 两种结构 + if isinstance(parsed, dict): + designs_raw = parsed.get("designs") or [] + elif isinstance(parsed, list): + designs_raw = parsed + else: + designs_raw = [] + for i, d in enumerate(designs_raw): if not isinstance(d, dict): continue designs.append({ diff --git a/graph/nodes/pinterest_analyze_node.py b/graph/nodes/pinterest_analyze_node.py index 4e3c05a..0740d0f 100644 --- a/graph/nodes/pinterest_analyze_node.py +++ b/graph/nodes/pinterest_analyze_node.py @@ -104,13 +104,15 @@ def pinterest_analyze_node(state: Dict[str, Any]) -> Dict[str, Any]: "message": f"term[{term}]: {e}", "trace": ""}) print(f"[pinterest_analyze] 「{term}」分析失败: {e}") - # 3) 兜底:LLM 无结果 → mock 规则简报(零 API 成本,保证有设计可生成) - if not raw_briefs and llm is not None: + # 3) 兜底:LLM 无结果 → mock 规则简报(零 API 成本,保证有设计可生成)。 + # 注意必须切到 mock 后端,不能再调回失败的 llm(否则同样报错)。 + if not raw_briefs: try: + mock = get_backend("mock") for term, paths in images.items(): sample = list(paths)[:analyze_per_term] if sample: - raw_briefs.extend(llm.analyze_pinterest_images(sample, term, country) or []) + raw_briefs.extend(mock.analyze_pinterest_images(sample, term, country) or []) print(f"[pinterest_analyze] 兜底:mock 规则简报 {len(raw_briefs)} 条") except Exception as e: # noqa: BLE001 print(f"[pinterest_analyze] mock 兜底失败: {e}")