From 083d09c459697012b4cdf7e921b5ff5eff4df2d9 Mon Sep 17 00:00:00 2001 From: EMRG Evolution Date: Sun, 23 Aug 2026 10:33:10 +0800 Subject: [PATCH] =?UTF-8?q?emrg:=20fix=20double-accumulated=20reasoning=20?= =?UTF-8?q?in=20llm.jsonl=20(O(n=C2=B2)=20blowup,=20rant=202026-08-23T10:1?= =?UTF-8?q?5:06)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit daemon.py appended every per-chunk cumulative reasoning snapshot and joined them, re-accumulating what llm.py already accumulates (chunk['reasoning'] = full think text so far, llm.py:366). For 47 real thinking tokens this produced a 29640-char record (630x); the worst llm.jsonl record hit ~10MB with ~190MB across 3 rotations. Take the LAST snapshot instead: it is the complete think text. --- emrg/server/daemon.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/emrg/server/daemon.py b/emrg/server/daemon.py index c274abb8..89a2094c 100644 --- a/emrg/server/daemon.py +++ b/emrg/server/daemon.py @@ -2425,7 +2425,13 @@ async def _run_tool_loop( return full_content = "".join(content_parts) - full_reasoning = "".join(reasoning_parts) or None + # llm.py yields the ACCUMULATED reasoning snapshot on every chunk + # (contract: chunk["reasoning"] = full think text so far, see + # llm.py:366). Appending every snapshot and joining would + # double-accumulate → O(n²) blowup (29640 chars for 47 real tokens, + # up to 10MB records in llm.jsonl, rant 2026-08-23T10:0x). Take the + # LAST snapshot = complete think text. + full_reasoning = reasoning_parts[-1] if reasoning_parts else None logger.debug("round %d finish: %s, tool_calls=%d, content_len=%d", round_num, final_finish, len(tc_by_index), len(full_content))