{"record":{"id":"6532324d3e3c2e1e","repo":"datawhalechina/hello-agents","slug":"llm","errorCode":null,"errorMessage":"LLM思考超时","messagePattern":"LLM思考超时","errorType":"exception","errorClass":"TimeoutException","httpStatus":500,"severity":"error","filePath":"Co-creation-projects/Apricity-InnocoreAI/agents/base.py","lineNumber":116,"sourceCode":"            if self.history:\n                history_str = \"\\n\".join(self.history[-10:])  # 只保留最近10条\n                full_prompt += f\"\\n\\n历史记录:\\n{history_str}\"\n            \n            # 调用 HelloAgent LLM\n            response = await asyncio.wait_for(\n                self.llm.ainvoke(full_prompt),\n                timeout=self.timeout\n            )\n            \n            response_text = response.content if hasattr(response, 'content') else str(response)\n            \n            self._add_to_history(f\"LLM prompt: {prompt}\")\n            self._add_to_history(f\"LLM response: {response_text}\")\n            \n            return response_text\n            \n        except asyncio.TimeoutError:\n            raise TimeoutException(\"LLM思考超时\")\n        except Exception as e:\n            raise AgentException(f\"LLM思考失败: {str(e)}\")\n    \n    def _add_to_history(self, message: str):\n        \"\"\"添加到历史记录\"\"\"\n        timestamp = datetime.now().isoformat()\n        self.history.append(f\"[{timestamp}] {message}\")\n        \n        # 限制历史记录长度\n        if len(self.history) > 100:\n            self.history = self.history[-50:]\n    \n    def get_history(self, limit: int = 10) -> List[str]:\n        \"\"\"获取历史记录\"\"\"\n        return self.history[-limit:]\n    \n    def clear_history(self):\n        \"\"\"清空历史记录\"\"\"","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/Apricity-InnocoreAI/agents/base.py#L98-L134","documentation":"TimeoutException from BaseAgent.think: asyncio.wait_for around self.llm.ainvoke(full_prompt) exceeded self.timeout seconds and cancelled the LangChain LLM call. LLM inference latency (especially long prompts producing long outputs) routinely exceeds default agent timeouts tuned for tools, so thinking is the most common place this fires.","triggerScenarios":"Calling think() with a large prompt (full paper abstracts / JSON context appended) against a slow model endpoint (self-hosted vLLM under load, rate-limited OpenAI tier); streaming disabled so the full completion must finish within one deadline; network stall between client and inference provider.","commonSituations":"Default timeout (often 30-60s) too short for reasoning models or 4K-token outputs; provider 429 retries inside langchain silently extending wall time; context dict serialized with indent=2 bloating prompt size; shared timeout attribute used for both tools and LLM though their latency profiles differ.","solutions":["Use a separate, larger LLM timeout (e.g. llm_timeout=180) in wait_for rather than reusing self.timeout.","Trim the context passed to think() — summarize history instead of json.dumps of full records.","Configure the provider client's own max_retries/timeout so provider-side throttling surfaces as its own typed error quickly.","Enable streaming in ainvoke and accumulate chunks, resetting an idle timer per token instead of one total deadline.","Retry think() once on timeout with a shortened prompt before failing the agent step."],"exampleFix":"# before\nresponse = await asyncio.wait_for(\n    self.llm.ainvoke(full_prompt),\n    timeout=self.timeout,\n)\n\n# after — dedicated, longer LLM deadline + single retry\nasync def _invoke():\n    return await self.llm.ainvoke(full_prompt)\ntry:\n    response = await asyncio.wait_for(_invoke(), timeout=self.llm_timeout)\nexcept asyncio.TimeoutError:\n    response = await asyncio.wait_for(_invoke(), timeout=self.llm_timeout)\n    # second TimeoutError propagates as TimeoutException('LLM思考超时')","handlingStrategy":"retry","validationCode":"# Sanity-check prompt size before invoking — huge prompts are the usual timeout cause\npayload_chars = len(full_prompt)\nif payload_chars > 50_000:\n    full_prompt = full_prompt[:50_000]  # or summarize history","typeGuard":null,"tryCatchPattern":"try:\n    answer = await agent.think(prompt, context)\nexcept TimeoutException:\n    await asyncio.sleep(2)\n    answer = await agent.think(shorten(prompt), context)  # one bounded retry","preventionTips":["Use a dedicated llm_timeout larger than the tool timeout.","Trim/summarize context passed to think(); avoid json.dumps(..., indent=2) of large histories.","Configure provider-client retries so 429s resolve before your outer deadline."],"tags":["python","llm","timeout","asyncio","langchain"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}