fix(cognitive-load): serialize weight tuning to stop concurrent update loss#81
Open
tongshu2023 wants to merge 1 commit into
Open
fix(cognitive-load): serialize weight tuning to stop concurrent update loss#81tongshu2023 wants to merge 1 commit into
tongshu2023 wants to merge 1 commit into
Conversation
…e loss (zijinz456#37) The auto-tuner is reached from FastAPI threadpool workers by concurrent chat sessions, but its in-memory store had no synchronization: - the read-modify-write on each signal multiplier (read current, apply decay/recovery factor, write back) could interleave across threads, silently dropping tuning steps - the data-loss race from zijinz456#37; - the eviction scan (min() over the store) could iterate while another thread inserted/deleted users, raising RuntimeError dict-changed- during-iteration, and parallel inserts could overshoot the 200-user cache cap. A module-level threading.Lock now serializes update_and_get_multipliers, get_multipliers, and reset_multipliers. Critical sections are pure in-memory arithmetic (microseconds), so contention is negligible. Note: the issue text references an AgentKV read-modify-write at lines 65-176; the tuner has since been rewritten as this in-memory module, so the fix targets the current implementation (same race class). First test coverage for the module (tests/test_cognitive_load_tuning.py, 10 tests): decay/floor/recovery/reset/non-numeric behavior, plus three concurrency tests - 2 threads sharing one signal must produce exactly the sequential number of decay steps, 8 threads with distinct signals must all survive, and 480 users crossing the eviction cap from 8 threads must neither crash nor overflow the cap. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #37.
The cognitive-load weight auto-tuner is reached from FastAPI threadpool workers by concurrent chat sessions, but its in-memory store had no synchronization, producing exactly the data-loss class described in the issue:
min()scan over the store; with another thread inserting/deleting users mid-scan this raisesRuntimeError: dictionary changed size during iteration, and parallel inserts could overshoot the 200-user cap.Note on the issue text
The issue references an AgentKV read-modify-write in
cognitive_load_tuning.pylines 65–176 withSELECT ... FOR UPDATEas a candidate fix. The tuner has since been rewritten as a pure in-memory module (sliding window + multipliers dict), so there is no DB row to lock anymore — but the same race class moved into the process-local store. The fix targets the current implementation.Fix
A module-level
threading.Lockserializesupdate_and_get_multipliers,get_multipliers, andreset_multipliers. The critical sections are pure in-memory arithmetic over small dicts (microseconds), so contention is negligible; no lock is held across any I/O.Tests
First test coverage for this module —
tests/test_cognitive_load_tuning.py(10 tests):Sequential behavior: no adjustment below 5 samples; exactly 2 decay steps after 6 persistently-high samples (
0.9²); decay floor at 0.40; recovery after the signal drops; reset; non-numeric signals ignored.Concurrent safety (the issue's acceptance criterion):
0.9instead of0.81and failsLocal run:
test_cognitive_load_tuning.py + test_cognitive_load.py + test_cognitive_load_calibrator.py→ 42 passed.Acceptance criteria
🤖 Generated with Claude Code