gemma_glm / llm_glm /hf_logits_processor.py
DigitalEuan's picture
Upload 14 files
9870a25 verified
Raw
History Blame Contribute Delete
25.5 kB
#!/usr/bin/env python3
"""
HuggingFace LogitsProcessor β€” GLM-Verified Generation
======================================================
Drop-in LogitsProcessor for any HuggingFace model.
Applies CRG veto + NRCI filtering + resonance biasing during generation.
Usage:
from llm_glm.hf_logits_processor import GLMLogitsProcessor
processor = GLMLogitsProcessor(
tokenizer=tokenizer,
crg_taxonomy=PHYSICS_TAXONOMY,
bias_strength=1.0,
)
outputs = model.generate(
input_ids,
logits_processor=[processor],
max_new_tokens=200,
)
"""
from typing import List, Dict, Optional, Set, Tuple, Any
import re
try:
import torch
from transformers import LogitsProcessor
HF_AVAILABLE = True
except (ImportError, OSError):
# Stub for when transformers/torch isn't installed
class LogitsProcessor:
def __call__(self, input_ids, scores):
return scores
HF_AVAILABLE = False
from .vector_engine import SVDVocabulary, IdeaZone, hamming, classify, get_leech
from .resonance import geometric_resonance
from .hard_veto import HardVeto
# ══════════════════════════════════════════════════════════════════════════════
# EXPANDED CRG TAXONOMY
# ══════════════════════════════════════════════════════════════════════════════
MASSIVE_CRG = {
# ── Physics particles ──
'photon': {'is_a': ['boson', 'particle'], 'related': ['energy', 'light', 'wave', 'electromagnetic', 'radiation', 'quantum', 'frequency']},
'electron': {'is_a': ['fermion', 'lepton', 'particle'], 'related': ['charge', 'mass', 'spin', 'orbital', 'energy', 'atom']},
'quark': {'is_a': ['fermion', 'particle'], 'related': ['proton', 'neutron', 'strong', 'color', 'gluon', 'hadron']},
'neutron': {'is_a': ['baryon', 'particle'], 'related': ['quark', 'nucleus', 'mass', 'proton', 'decay']},
'proton': {'is_a': ['baryon', 'particle'], 'related': ['quark', 'charge', 'nucleus', 'neutron', 'hydrogen']},
'boson': {'is_a': ['particle'], 'related': ['force', 'spin', 'carrier', 'photon', 'gluon', 'higgs', 'w_boson', 'z_boson']},
'fermion': {'is_a': ['particle'], 'related': ['spin', 'exclusion', 'electron', 'quark', 'matter']},
'lepton': {'is_a': ['fermion', 'particle'], 'related': ['electron', 'muon', 'tau', 'neutrino']},
'muon': {'is_a': ['lepton', 'fermion'], 'related': ['electron', 'mass', 'decay', 'anomaly']},
'gluon': {'is_a': ['boson'], 'related': ['strong', 'quark', 'color', 'confinement', 'fusion']},
'higgs': {'is_a': ['boson', 'scalar'], 'related': ['mass', 'field', 'symmetry', 'mechanism', 'vacuum']},
'neutrino': {'is_a': ['lepton'], 'related': ['weak', 'oscillation', 'mass', 'detection']},
'tau': {'is_a': ['lepton'], 'related': ['electron', 'muon', 'mass', 'decay']},
# ── Physics concepts ──
'energy': {'is_a': ['quantity', 'conserved'], 'related': ['mass', 'work', 'photon', 'frequency', 'wave', 'light', 'kinetic', 'potential']},
'force': {'is_a': ['interaction'], 'related': ['boson', 'carrier', 'acceleration', 'gravity', 'electromagnetic', 'strong', 'weak']},
'mass': {'is_a': ['property'], 'related': ['energy', 'higgs', 'gravity', 'particle', 'electron', 'inertia']},
'charge': {'is_a': ['property'], 'related': ['electromagnetic', 'electron', 'force', 'color', 'conservation']},
'wave': {'is_a': ['phenomenon'], 'related': ['photon', 'light', 'frequency', 'interference', 'energy', 'wavelength']},
'field': {'is_a': ['concept'], 'related': ['higgs', 'electromagnetic', 'energy', 'space', 'quantum', 'vacuum']},
'spin': {'is_a': ['property'], 'related': ['angular', 'fermion', 'boson', 'magnetic', 'electron', 'statistics']},
'light': {'is_a': ['electromagnetic', 'radiation', 'wave'], 'related': ['photon', 'wave', 'speed', 'energy', 'spectrum']},
'space': {'is_a': ['dimension'], 'related': ['time', 'spacetime', 'curvature', 'field', 'vacuum', 'expansion']},
'time': {'is_a': ['dimension'], 'related': ['space', 'spacetime', 'dilation', 'arrow', 'entropy']},
'gravity': {'is_a': ['force', 'interaction'], 'related': ['mass', 'spacetime', 'curvature', 'einstein', 'wave', 'black_hole']},
'entropy': {'is_a': ['quantity'], 'related': ['disorder', 'temperature', 'information', 'arrow', 'time', 'thermodynamics']},
'symmetry': {'is_a': ['concept'], 'related': ['group', 'gauge', 'breaking', 'invariance', 'higgs', 'conservation']},
'quantum': {'is_a': ['concept'], 'related': ['photon', 'wave', 'field', 'mechanics', 'coherence', 'entanglement', 'superposition']},
'relativity': {'is_a': ['theory'], 'related': ['einstein', 'spacetime', 'gravity', 'mass', 'energy', 'speed']},
'spacetime': {'is_a': ['concept'], 'related': ['space', 'time', 'gravity', 'curvature', 'einstein', 'relativity']},
'thermodynamics': {'is_a': ['theory'], 'related': ['energy', 'entropy', 'temperature', 'heat', 'work', 'laws']},
# ── Mathematics ──
'lattice': {'is_a': ['structure'], 'related': ['periodic', 'gauge', 'golay', 'leech', 'symmetry', 'crystal']},
'tensor': {'is_a': ['mathematical'], 'related': ['spacetime', 'curvature', 'metric', 'vector', 'index']},
'vector': {'is_a': ['mathematical'], 'related': ['direction', 'magnitude', 'space', 'tensor', 'basis']},
'matrix': {'is_a': ['mathematical'], 'related': ['linear', 'operator', 'quantum', 'tensor', 'determinant']},
'group': {'is_a': ['mathematical', 'structure'], 'related': ['symmetry', 'gauge', 'algebra', 'representation']},
'topology': {'is_a': ['mathematical'], 'related': ['invariant', 'phase', 'defect', 'lattice', 'betti']},
'algebra': {'is_a': ['mathematical'], 'related': ['group', 'ring', 'field', 'equation', 'structure']},
'calculus': {'is_a': ['mathematical'], 'related': ['derivative', 'integral', 'limit', 'continuous', 'analysis']},
'geometry': {'is_a': ['mathematical'], 'related': ['space', 'distance', 'angle', 'shape', 'curvature']},
'number': {'is_a': ['mathematical'], 'related': ['prime', 'integer', 'rational', 'real', 'complex', 'quantity']},
'prime': {'is_a': ['number', 'mathematical'], 'related': ['factor', 'divisible', 'fundamental', 'distribution']},
'equation': {'is_a': ['mathematical'], 'related': ['solve', 'variable', 'expression', 'balance', 'function']},
'function': {'is_a': ['mathematical'], 'related': ['mapping', 'domain', 'range', 'continuous', 'derivative']},
'probability': {'is_a': ['mathematical', 'quantity'], 'related': ['random', 'distribution', 'expected', 'event', 'sample']},
'statistics': {'is_a': ['mathematical'], 'related': ['data', 'mean', 'variance', 'distribution', 'sample']},
'infinity': {'is_a': ['mathematical', 'concept'], 'related': ['limit', 'series', 'uncountable', 'continuous']},
'pi': {'is_a': ['constant', 'mathematical'], 'related': ['circle', 'ratio', 'circumference', 'irrational']},
'euler': {'is_a': ['constant', 'mathematical'], 'related': ['exponential', 'logarithm', 'natural', 'growth']},
'zero': {'is_a': ['number', 'mathematical'], 'related': ['identity', 'addition', 'nothing', 'origin']},
# ── Script/screenwriting ──
'scene': {'is_a': ['unit'], 'related': ['setting', 'action', 'dialogue', 'character', 'beat']},
'character': {'is_a': ['entity'], 'related': ['motivation', 'arc', 'dialogue', 'conflict', 'development']},
'dialogue': {'is_a': ['element'], 'related': ['character', 'subtext', 'voice', 'conflict', 'revelation']},
'plot': {'is_a': ['structure'], 'related': ['conflict', 'resolution', 'arc', 'tension', 'story']},
'conflict': {'is_a': ['element'], 'related': ['protagonist', 'antagonist', 'stakes', 'tension', 'resolution']},
'protagonist': {'is_a': ['character'], 'related': ['arc', 'goal', 'conflict', 'transformation', 'agency']},
'antagonist': {'is_a': ['character'], 'related': ['opposition', 'conflict', 'stakes', 'protagonist']},
'arc': {'is_a': ['structure'], 'related': ['character', 'transformation', 'beginning', 'middle', 'end']},
'tension': {'is_a': ['element'], 'related': ['conflict', 'stakes', 'pacing', 'suspense', 'drama']},
'subtext': {'is_a': ['element'], 'related': ['dialogue', 'meaning', 'implication', 'character', 'theme']},
'theme': {'is_a': ['element'], 'related': ['meaning', 'story', 'character', 'symbol', 'message']},
'beat': {'is_a': ['unit'], 'related': ['scene', 'action', 'reaction', 'turning_point', 'rhythm']},
'exposition': {'is_a': ['element'], 'related': ['background', 'world', 'character', 'setup', 'information']},
'climax': {'is_a': ['beat', 'structure'], 'related': ['conflict', 'resolution', 'tension', 'peak', 'confrontation']},
'resolution': {'is_a': ['beat', 'structure'], 'related': ['climax', 'aftermath', 'new_normal', 'closure', 'denouement']},
'inciting': {'is_a': ['beat'], 'related': ['event', 'disruption', 'call', 'protagonist', 'ordinary_world']},
'midpoint': {'is_a': ['beat'], 'related': ['reversal', 'revelation', 'shift', 'false_victory', 'awareness']},
'pacing': {'is_a': ['element'], 'related': ['rhythm', 'scene_length', 'tension', 'breathing_room', 'tempo']},
'stake': {'is_a': ['element'], 'related': ['consequence', 'risk', 'loss', 'conflict', 'motivation']},
'motivation': {'is_a': ['element'], 'related': ['character', 'goal', 'desire', 'need', 'action']},
'transformation': {'is_a': ['element'], 'related': ['arc', 'character', 'change', 'growth', 'journey']},
'voice': {'is_a': ['element'], 'related': ['dialogue', 'character', 'style', 'tone', 'personality']},
# ── General knowledge ──
'atom': {'is_a': ['structure'], 'related': ['electron', 'proton', 'neutron', 'nucleus', 'element', 'molecule']},
'molecule': {'is_a': ['structure'], 'related': ['atom', 'bond', 'chemical', 'compound', 'reaction']},
'cell': {'is_a': ['structure', 'biology'], 'related': ['life', 'membrane', 'dna', 'division', 'organism']},
'dna': {'is_a': ['molecule', 'biology'], 'related': ['gene', 'code', 'life', 'heredity', 'protein']},
'evolution': {'is_a': ['process', 'biology'], 'related': ['natural_selection', 'adaptation', 'species', 'change']},
'planet': {'is_a': ['body', 'astronomy'], 'related': ['orbit', 'star', 'gravity', 'solar_system', 'earth']},
'star': {'is_a': ['body', 'astronomy'], 'related': ['fusion', 'light', 'gravity', 'nuclear', 'sun']},
'galaxy': {'is_a': ['structure', 'astronomy'], 'related': ['star', 'gravity', 'dark_matter', 'universe']},
'universe': {'is_a': ['concept', 'astronomy'], 'related': ['cosmos', 'big_bang', 'expansion', 'matter', 'energy']},
'brain': {'is_a': ['organ', 'biology'], 'related': ['neuron', 'thought', 'consciousness', 'mind', 'nervous']},
'consciousness': {'is_a': ['concept', 'philosophy'], 'related': ['mind', 'awareness', 'brain', 'experience', 'qualia']},
'information': {'is_a': ['concept'], 'related': ['data', 'entropy', 'bits', 'processing', 'communication']},
'language': {'is_a': ['system'], 'related': ['communication', 'grammar', 'meaning', 'symbol', 'expression']},
'truth': {'is_a': ['concept', 'philosophy'], 'related': ['fact', 'reality', 'evidence', 'knowledge', 'certainty']},
'beauty': {'is_a': ['concept', 'aesthetic'], 'related': ['harmony', 'proportion', 'form', 'pleasure', 'art']},
'justice': {'is_a': ['concept', 'ethics'], 'related': ['fairness', 'law', 'rights', 'equality', 'morality']},
'freedom': {'is_a': ['concept', 'politics'], 'related': ['liberty', 'choice', 'autonomy', 'rights', 'constraint']},
'power': {'is_a': ['concept'], 'related': ['authority', 'force', 'influence', 'control', 'energy']},
'love': {'is_a': ['emotion'], 'related': ['affection', 'attachment', 'care', 'bond', 'relationship']},
'fear': {'is_a': ['emotion'], 'related': ['danger', 'threat', 'anxiety', 'survival', 'response']},
'death': {'is_a': ['process', 'biology'], 'related': ['life', 'end', 'mortality', 'decay', 'entropy']},
'life': {'is_a': ['phenomenon', 'biology'], 'related': ['organism', 'growth', 'reproduction', 'metabolism', 'consciousness']},
'mind': {'is_a': ['concept', 'philosophy'], 'related': ['thought', 'consciousness', 'brain', 'reason', 'perception']},
'art': {'is_a': ['activity', 'culture'], 'related': ['beauty', 'expression', 'creativity', 'form', 'meaning']},
'music': {'is_a': ['art'], 'related': ['rhythm', 'melody', 'harmony', 'sound', 'emotion']},
'story': {'is_a': ['structure', 'narrative'], 'related': ['character', 'plot', 'conflict', 'theme', 'meaning']},
'history': {'is_a': ['discipline'], 'related': ['past', 'event', 'civilization', 'change', 'evidence']},
'science': {'is_a': ['discipline'], 'related': ['method', 'experiment', 'theory', 'evidence', 'knowledge']},
'technology': {'is_a': ['tool'], 'related': ['innvention', 'computer', 'engineering', 'progress', 'system']},
'computer': {'is_a': ['machine', 'technology'], 'related': ['program', 'data', 'algorithm', 'processing', 'information']},
'algorithm': {'is_a': ['procedure', 'computer'], 'related': ['step', 'computation', 'efficiency', 'logic', 'data']},
'network': {'is_a': ['structure'], 'related': ['node', 'connection', 'graph', 'communication', 'distributed']},
'system': {'is_a': ['concept'], 'related': ['component', 'interaction', 'emergence', 'feedback', 'organization']},
'pattern': {'is_a': ['concept'], 'related': ['regularity', 'repetition', 'structure', 'recognition', 'order']},
'structure': {'is_a': ['concept'], 'related': ['organization', 'form', 'component', 'relationship', 'design']},
'change': {'is_a': ['process'], 'related': ['time', 'transformation', 'difference', 'motion', 'growth']},
'balance': {'is_a': ['concept'], 'related': ['equilibrium', 'stability', 'harmony', 'force', 'tension']},
'emergence': {'is_a': ['concept'], 'related': ['system', 'complexity', 'property', 'whole', 'interaction']},
'complexity': {'is_a': ['concept'], 'related': ['system', 'emergence', 'nonlinear', 'chaos', 'organization']},
'simplicity': {'is_a': ['concept'], 'related': ['elegance', 'minimal', 'clarity', 'essence', 'reduction']},
'nature': {'is_a': ['concept'], 'related': ['environment', 'biology', 'physics', 'world', 'organic']},
'culture': {'is_a': ['system'], 'related': ['society', 'art', 'tradition', 'values', 'expression']},
'society': {'is_a': ['system'], 'related': ['people', 'institution', 'culture', 'law', 'interaction']},
'economy': {'is_a': ['system'], 'related': ['market', 'trade', 'value', 'production', 'consumption']},
}
# ══════════════════════════════════════════════════════════════════════════════
# LOGITS PROCESSOR
# ══════════════════════════════════════════════════════════════════════════════
class GLMLogitsProcessor(LogitsProcessor):
"""Drop-in HuggingFace LogitsProcessor that applies GLM geometric constraints.
Applies three layers of filtering during generation:
1. CRG veto β€” tokens with no semantic path to context get masked (-inf)
2. NRCI filter β€” tokens with very low NRCI get penalized
3. Resonance bias β€” tokens geometrically close to context zone get boosted
Usage:
processor = GLMLogitsProcessor(tokenizer=tokenizer)
outputs = model.generate(input_ids, logits_processor=[processor])
"""
def __init__(self, tokenizer=None,
vocab: Optional[SVDVocabulary] = None,
crg_taxonomy: Optional[dict] = None,
bias_strength: float = 1.0,
max_crg_dist: int = 6,
min_nrci: float = 0.55,
context_window: int = 20,
verbose: bool = False):
"""
Args:
tokenizer: HuggingFace tokenizer (for decoding token ids to words)
vocab: SVD vocabulary (auto-built if not provided)
crg_taxonomy: Semantic taxonomy dict (uses built-in if not provided)
bias_strength: How strongly to bias logits (0=off, 1=normal, 2=strong)
max_crg_dist: Max CRG graph distance before veto
min_nrci: Minimum NRCI threshold
context_window: Number of recent tokens to consider for zone
verbose: Print debug info during generation
"""
super().__init__()
self.tokenizer = tokenizer
self.vocab = vocab
self.crg = crg_taxonomy or MASSIVE_CRG
self.bias_strength = bias_strength
self.max_crg_dist = max_crg_dist
self.min_nrci = min_nrci
self.context_window = context_window
self.verbose = verbose
self.zone = IdeaZone()
self._token_cache: Dict[int, str] = {}
self._vector_cache: Dict[str, list] = {}
self._crg_cache: Dict[Tuple[str, str], int] = {}
# Stats
self.stats = {"total_tokens": 0, "vetoed": 0, "biased": 0, "passed": 0}
def __call__(self, input_ids, scores):
"""Apply GLM constraints to logits.
Args:
input_ids: (batch_size, seq_len) β€” generated token ids so far
scores: (batch_size, vocab_size) β€” logits for next token
Returns: Modified scores with GLM constraints applied
"""
import torch
batch_size = scores.shape[0]
# Update zone from recent context
self._update_zone_from_context(input_ids[0]) # use first batch item
# Get zone centroid
centroid = self.zone.get_centroid()
zone_words = self.zone.words[-5:]
# Process each token in vocabulary
for token_id in range(scores.shape[1]):
word = self._token_to_word(token_id)
if not word or len(word) < 2:
continue
# Layer 1: CRG veto
if zone_words:
# Use MIN distance (closest connection to any zone word)
min_dist = min(self._crg_distance(z, word) for z in zone_words)
# Hard veto only for words IN the CRG but too far
# Unknown words (not in CRG) get penalty but not veto
word_in_crg = word in self.crg
if min_dist > self.max_crg_dist and word_in_crg:
scores[:, token_id] = float('-inf')
self.stats["vetoed"] += 1
continue
# Soft penalty for unknown words (not in CRG taxonomy)
elif not word_in_crg and min_dist > self.max_crg_dist:
scores[:, token_id] -= 2.0 # penalty, not veto
# Layer 2: NRCI filter
vec = self._get_vector(word)
l = get_leech()
nrci = float(l.calculate_nrci(vec))
if nrci < self.min_nrci:
# Soft penalty (not hard veto)
penalty = (nrci - self.min_nrci) * 10 # scales with violation severity
scores[:, token_id] += penalty
self.stats["vetoed"] += 1
continue
# Layer 3: Resonance bias
if self.bias_strength > 0:
resonance = geometric_resonance(vec, centroid)
bias = self.bias_strength * (resonance - 0.5) * 2.0 # centered, scaled
scores[:, token_id] += bias
self.stats["biased"] += 1
self.stats["total_tokens"] += 1
self.stats["passed"] = self.stats["total_tokens"] - self.stats["vetoed"]
return scores
def _update_zone_from_context(self, token_ids):
"""Update the idea zone from recent token ids."""
if self.tokenizer is None:
return
# Decode recent tokens
recent = token_ids[-self.context_window:].tolist()
text = self.tokenizer.decode(recent, skip_special_tokens=True)
# Extract meaningful words
words = re.findall(r'[a-z]{3,}', text.lower())
# Update zone (only new words)
for word in words:
if word not in self.zone.words[-10:]: # avoid re-adding recent
self.zone.update(word, self.vocab or SVDVocabulary())
def _token_to_word(self, token_id: int) -> str:
"""Convert token id to word (cached)."""
if token_id in self._token_cache:
return self._token_cache[token_id]
if self.tokenizer is None:
self._token_cache[token_id] = ""
return ""
try:
word = self.tokenizer.decode([token_id], skip_special_tokens=True).strip().lower()
# Clean up subword tokens
word = re.sub(r'^[^\w]+|[^\w]+$', '', word)
word = re.sub(r'^##', '', word) # BERT-style subwords
self._token_cache[token_id] = word
return word
except Exception:
self._token_cache[token_id] = ""
return ""
def _get_vector(self, word: str) -> list:
"""Get 24-bit vector for a word (cached)."""
if word in self._vector_cache:
return self._vector_cache[word]
if self.vocab:
vec = self.vocab.get_vector(word)
else:
from .vector_engine import word_to_hash24, snap_to_codeword
raw = word_to_hash24(word)
vec, _ = snap_to_codeword(raw)
self._vector_cache[word] = vec
return vec
def _crg_distance(self, a: str, b: str) -> int:
"""BFS distance in CRG (cached)."""
key = (min(a, b), max(a, b))
if key in self._crg_cache:
return self._crg_cache[key]
if a == b:
self._crg_cache[key] = 0
return 0
visited = {a}
frontier = [(a, 0)]
max_d = self.max_crg_dist + 1
while frontier:
next_frontier = []
for node, cost in frontier:
entry = self.crg.get(node, {})
for neighbor in entry.get('is_a', []):
if neighbor == b:
self._crg_cache[key] = cost + 1
return cost + 1
if neighbor not in visited and cost + 1 <= max_d:
visited.add(neighbor)
next_frontier.append((neighbor, cost + 1))
for neighbor in entry.get('related', []):
if neighbor == b:
d = cost + 2
self._crg_cache[key] = d
return d
if neighbor not in visited and cost + 2 <= max_d:
visited.add(neighbor)
next_frontier.append((neighbor, cost + 2))
frontier = next_frontier
self._crg_cache[key] = max_d
return max_d
def get_stats(self) -> dict:
"""Return generation statistics."""
total = self.stats["total_tokens"] or 1
return {
"total_evaluated": self.stats["total_tokens"],
"vetoed": self.stats["vetoed"],
"veto_rate": f"{self.stats['vetoed'] / total:.1%}",
"biased": self.stats["biased"],
"bias_rate": f"{self.stats['biased'] / total:.1%}",
"zone_nrci": self.zone.get_centroid_nrci(),
"zone_words": self.zone.words[-10:],
}
def reset(self):
"""Reset state for a new generation."""
self.zone = IdeaZone()
self._token_cache.clear()
self._vector_cache.clear()
self._crg_cache.clear()
self.stats = {"total_tokens": 0, "vetoed": 0, "biased": 0, "passed": 0}
# ══════════════════════════════════════════════════════════════════════════════
# CONVENIENCE FUNCTION
# ══════════════════════════════════════════════════════════════════════════════
def create_glm_processor(tokenizer=None, bias_strength: float = 1.0,
**kwargs) -> GLMLogitsProcessor:
"""Create a GLM LogitsProcessor with sensible defaults.
Args:
tokenizer: HuggingFace tokenizer
bias_strength: 0.0 = CRG veto only, 1.0 = balanced, 2.0 = strong bias
**kwargs: Additional arguments passed to GLMLogitsProcessor
Returns:
GLMLogitsProcessor ready for model.generate()
"""
return GLMLogitsProcessor(
tokenizer=tokenizer,
bias_strength=bias_strength,
**kwargs,
)