Repository navigation
feat(analysis): add token entropy and stagnation monitor - #783
Merged
SHAURYASANYAL3 merged 2 commits intoOct 26, 2026
Merged
SHAURYASANYAL3 merged 2 commits into
SHAURYASANYAL3 merged 2 commits into
Conversation
Keep optional OpenAI logprobs on model-invocation events and add TokenEntropyMonitor, a built-in analyzer that flags ENTROPY_COLLAPSE (sliding-window Shannon entropy) and STAGNATION_LOOP (identical completions across consecutive turns). Fixes Shinraya-Tech-Labs#760
Entropy only needs the numbers. The token strings would sit in event attributes next to the redacted artifacts, so drop them. Fixes Shinraya-Tech-Labs#760
Contributor
🧪 PR Test Results
Python 3.12 · commit 9542ffa |
SHAURYASANYAL3
marked this pull request as ready for review
October 26, 2026 06:21
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
SHAURYASANYAL3
approved these changes
Oct 26, 2026
SHAURYASANYAL3
left a comment
Collaborator
There was a problem hiding this comment.
👁️ Multi-Turn Token Entropy & Semantic Drift Review: PR #783 (TokenEntropyMonitor) — APPROVED ✅
Outstanding implementation by @Anshuu2004 on this Level 2 milestone!
Architectural Highlights:
-
Defensive Redaction-First Logprob Capture: In
agentwatch/events/normalizers/llm_api.py, captures only numerical logprobs andtop_logprobsdistributions without persisting raw token text outside the redaction path. -
Shannon Entropy Math & Re-Arming: Accurately computes Shannon entropy
$H = -\sum p \log_2 p$ over a sliding window across multi-turn completions, detectingENTROPY_COLLAPSEwith single-report re-arming semantics to avoid alert flooding. -
Stagnation Loop Fallback: Implements deterministic completion content hashing for
STAGNATION_LOOPdetection, functioning reliably even when LLM providers do not return logprob distributions. -
Clean Registry Integration: Correctly registered in
agentwatch/analysis/registry.pyunderbuiltin_analyzers(). - 100% Green CI: All 12 checks passed (3m39s test suite, 79.70% coverage, 0 regressions).
Merging into main! 🚀
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.
📌 Description
Adds
TokenEntropyMonitor, an analyzer that watches a run's model calls for two kinds of generation stagnation, and makes the OpenAI normalizer keep optional logprobs so there is something to measure. NSoC 26, level2.agentwatch/events/normalizers/llm_api.py: newtoken_logprobs()helper.OpenAINormalizer.map_iostores the first choice's per-token logprobs (logprob and top_logprobs only, the token text is deliberately not stored so it cannot sit in event attributes outside the redaction path) inattributes["logprobs"]when the provider sent them. When it did not, the event is exactly what it was before.agentwatch/analysis/entropy.py:TokenEntropyMonitor(window=32, threshold=0.05, min_repeats=3).ENTROPY_COLLAPSE: the mean Shannon entropy (bits) of the next-token distribution over a sliding window of tokens drops belowthreshold. Per token, the top-k logprobs are exponentiated and renormalized to sum to 1, then H = -sum(p log2 p). The window runs across turns of a run. It reports once per collapse and re-arms when the mean recovers.STAGNATION_LOOP: the same completion (content hash) inmin_repeatsconsecutive model calls. Needs no logprobs, so it is also the fallback when a provider sends none.agentwatch/analysis/registry.py: registered inbuiltin_analyzers(). Note this changes the engine pipeline identity (analyzer set is part of the interpretation id).record_type = "token_entropy_anomaly") withanomaly_type,turn_index,events, the measured values and an explanation. They are not legacyEventType.ANOMALY_DETECTEDevents.Not implemented (honest scope note): the issue's second requirement also mentions erratic divergence spikes (sudden uncertainty jumps during deterministic steps), and my plan comment said I would flag a jump against the window mean. I did not build that. This PR only emits the two anomaly types listed in requirement 3 (
ENTROPY_COLLAPSE,STAGNATION_LOOP). Also not covered: n-gram level repetition inside one completion, streaming responses, providers other than the OpenAI response shape. Happy to do the spike rule as a follow-up PR if you want it.Fixes #760
🏛️ Architectural Plane & Classification
🧪 Verification & Evidence of Testing
tests/v3/test_entropy.py: entropy math, window sliding, collapse and re-arm, stagnation, missing logprobs, config validation, normalizer passthrough, engine round trip)pytest tests/).🛡️ Security & Linter Quality Checklist
bandit -r agentwatchwith 0 issues found.bandit-baseline.jsonwas NOT created or edited. (the diff touches 4 files, none of them a baseline)# nosecadded.ruff format --check agentwatch/(Clean pass).ruff check agentwatch/(Clean pass).✍️ Contributor Integrity Declaration
By submitting this pull request, I certify that:
origin/main.Discord membership proof
Discord handle: @abhishekcse07