-
fix(llm): normalize str-returns to a message in the central LLM wrapper (+ ainvoke) (#4342)
发布于
2026-05-25 14:47:11 +00:00 - fix(llm): normalize str-returns to a message in ProcessingLLMWrapper + add ainvoke
The central wrapper (returned by all get_llm paths) stripped tags but
returned a bare str when the base LLM returned a str — that inconsistent shape is
the root of the recurring "'str' object has no attribute 'content'" crashes we've
been fixing site-by-site (#3884 -> #4339).Generic fix at the choke point:
- invoke(): when the base returns a bare str, wrap it into AIMessage(content=stripped)
instead of returning a str. Message returns are unchanged (mutate .content in place,
preserving additional_kwargs/reasoning_content/tool_calls). Other types pass through. - add ainvoke(): mirrors invoke(); without it, the 7 direct .ainvoke() sites
(browsecomp_entity/modular strategies) bypassed think-stripping via getattr.
Now every get_llm LLM yields a think-free str .content on both sync and async direct
calls, so the raw .invoke().content sites are safe automatically (deferred per-site
migration cancelled). Reasoning-safe: only .content is rewritten, so DeepSeek
thinking-mode reasoning_content round-tripping (#4194) is not worsened.Limitation: the LangGraph create_agent path binds tools on the base model
(model.bind_tools via getattr), so it bypasses this wrapper — unchanged by this PR.Tests: updated the 2 tests asserting a str return; added shape, reasoning_content/
tool_calls-preservation (#4194 guard), and ainvoke regression tests.
mypy 552 clean; ruff clean; 2171 passed across 78 LLM-layer test files + citation_handlers.- refactor(llm): extract _log_llm_error helper + add type hints (review polish)
Addresses the #4342 review recommendations:
- DRY: invoke() and ainvoke() shared the same try/except error-logging verbatim;
extracted a _log_llm_error(error) static helper so they can't diverge. - Type hints: added annotations to _normalize_response/_log_llm_error/invoke/ainvoke.
No behavior change. ruff + mypy clean; 112 config tests pass.
下载附件