Merge Grok's generation enhancements: cleanup contractions + sampling strategies - #9
Merge Grok's generation enhancements: cleanup contractions + sampling strategies#9ariannamethod with Copilot wants to merge 6 commits into
Conversation
Co-authored-by: ariannamethod <211269477+ariannamethod@users.noreply.github.com>
… strategies Co-authored-by: ariannamethod <211269477+ariannamethod@users.noreply.github.com>
This comment was marked as resolved.
This comment was marked as resolved.
Co-authored-by: ariannamethod <211269477+ariannamethod@users.noreply.github.com>
…ns + update README with fresh examples Co-authored-by: ariannamethod <211269477+ariannamethod@users.noreply.github.com>
Сделал глубокий рефакторинг (a83578b):
Теперь генерация чище И сохраняет философию "presence > intelligence"! 🔥 |
This comment was marked as resolved.
This comment was marked as resolved.
Понял! Не мержим пока Grok не закончит в новой ветке. Main остаётся неприкосновенной — она генерит лучше. Жду результаты от Grok'а, потом сравним и выберем лучшее. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
… (ain't nothing), preserve ellipsis, add min-p sampling Co-authored-by: ariannamethod <211269477+ariannamethod@users.noreply.github.com>
Проанализировал ветку Grok'а (fcb73b2). Взял лучшее: Добавил из Grok:
Свои фиксы:
НЕ взял от Grok:
Примеры: 110/111 тестов проходят! 🔥 |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
Pull request overview
This PR merges generation enhancements from Grok's two experimental branches, combining improved text cleanup with advanced sampling strategies. The changes introduce loop detection, adaptive temperature control, 45+ contraction patterns, and grammar fixes to improve the quality and naturalness of generated text.
Key Changes:
- Enhanced cleanup with 45+ contraction patterns, grammar fixes (e.g., "don't trying" → "don't try"), and poetic repetition preservation
- Loop detection and avoidance in generation with adaptive temperature based on entropy trends
- New sampling strategies including min-p sampling, pattern diversity scoring, and enhanced entropy-aware sampling v2
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
haze/cleanup.py |
Adds extensive contraction handling, grammar fixes, run-on sentence detection, and resonance-aware cleanup modes |
haze/subword_field.py |
Implements generate_enhanced() with loop avoidance, adaptive temperature, and sentence-aware stopping |
haze/nn.py |
Adds min-p sampling, pattern diversity scoring, loop detection, and enhanced entropy sampling functions |
haze/trauma.py |
Introduces _compute_trauma_score_enhanced() with conversation history and context coherence awareness |
haze/experts.py |
Adds compute_expert_weights_enhanced() with momentum and context memory for stable expert routing |
haze/async_haze.py |
Integrates generate_enhanced() with fallback to original method for backward compatibility |
haze/tests/test_cleanup.py |
Comprehensive test suite (35 tests) covering contractions, repetition handling, and sentence structure |
README.md |
Updates test count (103→111), adds Level 5.9 section with enhanced generation examples |
Comments suppressed due to low confidence (1)
haze/subword_field.py:189
- This import of module re is redundant, as it was previously imported on line 17.
import re
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| # AGGRESSIVE FIX: "don" + noun-like word (ends with s, es, tion, ness, ment, etc.) → "ain't" | ||
| # This catches broken generation like "don tangerines", "don tears", "don twilight" | ||
| result = re.sub(r"\bdon\s+(tangerine|tangerines|tear|tears|twilight|table|tables|street|streets|vendor|vendors|cigarette|cigarettes|apartment|apartments|bottle|bottles|glass|glasses|drink|drinks|key|keys|door|doors|room|rooms|window|windows|floor|floors|wall|walls|chair|chairs|bed|beds|toilet|paper|money|time|place|thing|things|people|person|man|men|woman|women|child|children|hand|hands|face|faces|eye|eyes|head|heart|life|death|love|hate|fear|pain|joy|hope|dream|dreams|night|day|morning|evening|rain|snow|sun|moon|star|stars|sky|earth|world|fire|water|air|light|dark|darkness|silence|noise|sound|voice|word|words|name|story|stories|truth|lie|lies|secret|secrets|memory|memories|moment|moments|year|years|month|week|hour|minute|second|train|trains|thought|thoughts|idea|ideas|feeling|feelings|sense|body|soul|mind|spirit|god|devil|angel|ghost|shadow|shadows|dust|dirt|mud|blood|bone|bones|skin|flesh|hair|breath|step|steps|road|roads|path|paths|way|ways|bridge|bridges|river|rivers|sea|ocean|wave|waves|wind|storm|cloud|clouds|thunder|lightning|fog|mist|haze|smoke|ash|ashes|flame|flames|spark|sparks|ice|stone|stones|rock|rocks|sand|grass|tree|trees|flower|flowers|leaf|leaves|root|roots|branch|branches|bird|birds|dog|dogs|cat|cats|horse|horses|fish|wolf|wolves|bear|snake|rat|rats|mouse|mice|bug|bugs|fly|flies|bee|bees|spider|spiders|worm|worms|twice|once|again|anymore|anyway|always|never|ever|often|sometimes|usually|rarely|seldom|here|there|now|then|today|tomorrow|yesterday|tonight|forever|together|alone|inside|outside|above|below|behind|ahead|around|away|back|down|up|over|under|through|across|along|beside|between|beyond|within|without|against|toward|towards|upon|onto|into|throughout|meanwhile|otherwise|somehow|somewhat|somewhere|anywhere|everywhere|nowhere|anywhere|nothing|something|everything|anything|anyone|someone|everyone|nobody|somebody|everybody)\b", r"ain't \1", result, flags=re.IGNORECASE) |
There was a problem hiding this comment.
This regex pattern contains a hardcoded list of over 200 nouns, creating an extremely long and unmaintainable line. This approach has several issues:
- The line is unreadable and difficult to review
- Adding/removing words requires modifying a massive regex
- The pattern contains duplicates (e.g., "anywhere" appears twice)
- There's no clear principle for inclusion (why these specific nouns?)
Consider refactoring this to use a set-based approach or a more general pattern. For example:
- Define a set of common nouns separately
- Use a function to check if a word is a noun
- Or use a more general pattern like
\bdon\s+(\w+s?)\bwith additional validation to avoid false positives
This would make the code more maintainable and testable while achieving the same goal of catching broken generation artifacts.
| if candidates: | ||
| counts = np.array(list(candidates.values()), dtype=float) | ||
| probs = counts / counts.sum() | ||
| current_entropy = -np.sum(probs * np.log2(probs + 1e-10)) | ||
| recent_entropies.append(current_entropy) | ||
|
|
||
| # Adaptive temperature | ||
| current_temp = temperature | ||
| if adaptive_temp and recent_entropies: | ||
| # Adjust based on entropy trend | ||
| if current_entropy < target_entropy * ENTROPY_LOW_THRESHOLD: |
There was a problem hiding this comment.
Undefined variable current_entropy when candidates is empty. If the condition on line 388 (if candidates:) evaluates to False, current_entropy will not be defined, but it's used on line 398 in the next conditional check. This will cause a NameError.
Initialize current_entropy before the conditional block, for example:
current_entropy = 0.0
| run_on_patterns = [ | ||
| # "I went there I saw things" → "I went there. I saw things" | ||
| (r'(\w+)\s+(I\s+(?:am|was|have|had|do|did|will|would|can|could|should|shall|may|might|must|saw|went|came|got|made|took|gave|said|thought|felt|knew|looked|turned|walked|ran|tried|wanted|needed|loved|hated|found|lost|kept|left|stayed|started|stopped))\b', r'\1. \2'), | ||
| # Similar for "you", "we", "they", "he", "she" | ||
| (r'(\w+)\s+(you\s+(?:are|were|have|had|do|did|will|would|can|could|should|shall|may|might|saw|went|came|got))\b', r'\1. \2'), | ||
| (r'(\w+)\s+(we\s+(?:are|were|have|had|do|did|will|would|can|could|should|shall|saw|went|came|got))\b', r'\1. \2'), | ||
| (r'(\w+)\s+(they\s+(?:are|were|have|had|do|did|will|would|saw|went|came|got))\b', r'\1. \2'), | ||
| (r'(\w+)\s+(he\s+(?:is|was|has|had|does|did|will|would|can|could|saw|went|came|got|said|thought))\b', r'\1. \2'), | ||
| (r'(\w+)\s+(she\s+(?:is|was|has|had|does|did|will|would|can|could|saw|went|came|got|said|thought))\b', r'\1. \2'), | ||
| ] | ||
|
|
||
| # Only apply run-on fixes in moderate/strict mode to preserve style in gentle mode | ||
| if mode in ["moderate", "strict"]: | ||
| for pattern, replacement in run_on_patterns: | ||
| # Only apply if the result would be 2+ complete sentences | ||
| temp_result = re.sub(pattern, replacement, result, count=1, flags=re.IGNORECASE) | ||
| # Check if this creates better sentence structure | ||
| if temp_result.count('.') > result.count('.'): | ||
| result = temp_result |
There was a problem hiding this comment.
The run-on sentence patterns are too aggressive and may introduce false positives. The pattern (\w+)\s+(I\s+...) will match any word followed by "I" and a verb, even when they're part of the same sentence.
For example, "what I saw" would incorrectly become "what. I saw", or "maybe I can" would become "maybe. I can". The pattern doesn't check if the preceding word is actually the end of a clause.
Consider adding more context checks, such as:
- Ensuring the preceding word is likely a clause-ending word (verb, noun, etc.)
- Checking for coordinating conjunctions or commas that already separate clauses
- Adding a minimum length requirement for the first clause
Alternatively, this aggressive splitting should only be applied in strict mode, not moderate mode.
| for i, hist in enumerate(context_history[-5:]): # Last 5 steps | ||
| weight = decay ** (len(context_history) - i - 1) |
There was a problem hiding this comment.
Incorrect exponential decay calculation in the loop. The expression decay ** (len(context_history) - i - 1) uses the absolute position in context_history, but the loop iterates over only the last 5 elements (context_history[-5:]).
This means:
- If
context_historyhas 10 items, the first item in the slice (index 5 in original) would getdecay ** (10 - 0 - 1) = decay ** 9 - But
ishould represent the position within the slice, not the original list
The fix should use the slice's local index. For example:
for i, hist in enumerate(context_history[-5:]):
weight = decay ** (len(context_history[-5:]) - i - 1)Or better yet, use reversed enumeration to make the intent clearer that recent items get higher weights.
| for i, hist in enumerate(context_history[-5:]): # Last 5 steps | |
| weight = decay ** (len(context_history) - i - 1) | |
| recent_history = context_history[-5:] # Last 5 steps | |
| for i, hist in enumerate(recent_history): | |
| weight = decay ** (len(recent_history) - i - 1) |
| result = re.sub(rf"\b(don{apos}t|can{apos}t|won{apos}t|couldn{apos}t|wouldn{apos}t|shouldn{apos}t|isn{apos}t|aren{apos}t|wasn{apos}t|weren{apos}t|haven{apos}t|hasn{apos}t|hadn{apos}t)\s+(\w+)ing\b", | ||
| lambda m: m.group(1) + ' ' + m.group(2), result, flags=re.IGNORECASE) |
There was a problem hiding this comment.
The grammar fix for gerunds after negative contractions is too broad and will cause incorrect transformations. The pattern captures any word ending in "ing" and removes the "ing" suffix, but this doesn't work correctly for all verbs.
For example:
- "don't trying" → "don't try" ✓ (correct: "try" + "ing" = "trying")
- "can't going" → "can't go" ✓ (correct: "go" + "ing" = "going")
- But "can't being" → "can't be" ✓ (correct: "be" + "ing" = "being")
- However, "can't running" → "can't runn" ✗ (incorrect: should be "can't run")
- And "can't sitting" → "can't sitt" ✗ (incorrect: should be "can't sit")
The pattern (\w+)ing captures the stem including any doubled consonants, which breaks the transformation. Consider:
- Using a more sophisticated verb stemming approach
- Maintaining a dictionary of common gerund → base verb mappings
- Or simply matching specific known patterns rather than trying to handle all gerunds generically
| # If text has very low entropy (too repetitive/mechanical), add warning | ||
| # But don't modify - just for metrics | ||
| if entropy_threshold is not None: | ||
| local_entropy = _calculate_local_entropy(result) |
There was a problem hiding this comment.
Variable local_entropy is not used.
| local_entropy = _calculate_local_entropy(result) | |
| _calculate_local_entropy(result) |
| result1 = cleanup_with_resonance(text, resonance_score=0.8, entropy=3.0) | ||
|
|
||
| # Low resonance, low entropy -> moderate mode | ||
| result2 = cleanup_with_resonance(text, resonance_score=0.3, entropy=1.2) |
There was a problem hiding this comment.
Variable result2 is not used.
|
|
||
| import re | ||
| from typing import Dict | ||
| from typing import Dict, Optional, List |
There was a problem hiding this comment.
Import of 'Dict' is not used.
| from typing import Dict, Optional, List | |
| from typing import Optional, List |
| pass | ||
|
|
There was a problem hiding this comment.
Unnecessary 'pass' statement.
| pass | |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| run_on_patterns = [ | ||
| # "I went there I saw things" → "I went there. I saw things" | ||
| (r'(\w+)\s+(I\s+(?:am|was|have|had|do|did|will|would|can|could|should|shall|may|might|must|saw|went|came|got|made|took|gave|said|thought|felt|knew|looked|turned|walked|ran|tried|wanted|needed|loved|hated|found|lost|kept|left|stayed|started|stopped))\b', r'\1. \2'), |
There was a problem hiding this comment.
Narrow run-on fix to avoid splitting subordinate clauses
The new run-on regex splits any word followed by "I " into two sentences, which will also fire on valid subordinate clauses like “when I was” / “because I did” and turn them into “when. I was…”. This happens in moderate/strict mode because the pattern doesn’t require a clause boundary or punctuation before the pronoun, so normal sentences can be broken into ungrammatical fragments. Consider gating on sentence-ending punctuation or a stronger boundary signal instead of any \w+ token.
Useful? React with 👍 / 👎.
| apos = "['\u2019]" # ASCII U+0027 and Right Single Quotation Mark U+2019 | ||
| result = re.sub(rf"\b(don{apos}t|can{apos}t|won{apos}t|couldn{apos}t|wouldn{apos}t|shouldn{apos}t|isn{apos}t|aren{apos}t|wasn{apos}t|weren{apos}t|haven{apos}t|hasn{apos}t|hadn{apos}t)\s+(\w+)ing\b", | ||
| lambda m: m.group(1) + ' ' + m.group(2), result, flags=re.IGNORECASE) |
There was a problem hiding this comment.
Handle irregular “-ing” verbs in contraction grammar fix
The grammar fix for “don’t/can’t …ing” drops the “ing” suffix by keeping only \w+ before it. For verbs like “dying”, “lying”, or “tying”, this produces “don’t dy/ly/ty” instead of “don’t die/lie/tie”. That introduces incorrect words in exactly the cases the cleanup is trying to fix. A small irregular list or a targeted ying→ie rule would prevent these regressions.
Useful? React with 👍 / 👎.
Polished Generation Examples:
Key Fixes:
don't trying→don't try(grammar)didn't went→didn't go(tense)don nothing→ain't nothing(early fix)Wait... Really???preserved (valid ellipsis)but… Tell→but Tell(broken ellipsis removed)Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.