Add LLMCompress subsystem - sandbox for symbolic compression of LLM behavior
New subsystem fully self-contained: Components: - LLMCompress/llm_adapter.py: LLMAdapter + LLMResponse (abstract over LLM backends) - LLMCompress/compression_report.py: CompressionReport (symbolic analysis results) - LLMCompress/llm_compressor.py: compress_interaction() and compress_session() - LLMCompress/tests/test_llm_compress.py: 5 comprehensive tests Integration: - Uses GlyphOS Cognitive Kernel for symbolic analysis - Integrates with GlyphOS Event System - Emits cognition.started and cognition.completed events - Supports in-memory GX execution via execute_symbolic() Test Coverage: - LLMCompress tests: 5/5 PASS - All existing tests still pass (52/52) - Total: 57 tests passing Bug fixes in cognitive_kernel.py: - Fixed execute_symbolic() method calls to use correct function signatures - normalize_segments(manifest, segments, payload) - map_lanes(segments) - build_envelope(manifest, lanes, payload, context) - execute_with_lain(envelope) Constraints: - No modifications to gx_compiler/* - No modifications to glyphs/super_registry.py - Self-contained subsystem with proper isolation - Full backward compatibility maintained
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
"""LLMCompress
|
||||||
|
|
||||||
|
Sandbox for symbolic compression of LLM behavior using:
|
||||||
|
|
||||||
|
- GlyphOS Cognitive Kernel
|
||||||
|
- Supercharged Glyph Registry
|
||||||
|
- GlyphOS Event System
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .llm_adapter import LLMAdapter, LLMResponse
|
||||||
|
from .compression_report import CompressionReport
|
||||||
|
from .llm_compressor import (
|
||||||
|
compress_interaction,
|
||||||
|
compress_session,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"LLMAdapter",
|
||||||
|
"LLMResponse",
|
||||||
|
"CompressionReport",
|
||||||
|
"compress_interaction",
|
||||||
|
"compress_session",
|
||||||
|
]
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,39 @@
|
|||||||
|
"""Compression report structures for LLMCompress."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class CompressionReport:
|
||||||
|
"""Symbolic compression report for a single LLM interaction or session."""
|
||||||
|
|
||||||
|
# Raw interaction(s)
|
||||||
|
interactions: List[Dict[str, Any]] = field(default_factory=list)
|
||||||
|
|
||||||
|
# Symbolic outputs from LAIN / GlyphOS
|
||||||
|
fused_symbol: Optional[Dict[str, Any]] = None
|
||||||
|
diagnostics: Optional[Dict[str, Any]] = None
|
||||||
|
cognition_trace: Optional[List[Dict[str, Any]]] = None
|
||||||
|
|
||||||
|
# Glyph-related summaries
|
||||||
|
glyph_ids: List[str] = field(default_factory=list)
|
||||||
|
glyph_resonance: Optional[Dict[str, Any]] = None
|
||||||
|
|
||||||
|
# Free-form notes / tags
|
||||||
|
tags: List[str] = field(default_factory=list)
|
||||||
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"interactions": self.interactions,
|
||||||
|
"fused_symbol": self.fused_symbol,
|
||||||
|
"diagnostics": self.diagnostics,
|
||||||
|
"cognition_trace": self.cognition_trace,
|
||||||
|
"glyph_ids": self.glyph_ids,
|
||||||
|
"glyph_resonance": self.glyph_resonance,
|
||||||
|
"tags": self.tags,
|
||||||
|
"metadata": self.metadata,
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
"""LLM Adapter
|
||||||
|
|
||||||
|
Thin abstraction over a concrete LLM backend (local or remote).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import Any, Callable, Dict, Optional
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LLMResponse:
|
||||||
|
"""Container for a single LLM interaction."""
|
||||||
|
|
||||||
|
prompt: str
|
||||||
|
response: str
|
||||||
|
tokens_prompt: Optional[int] = None
|
||||||
|
tokens_response: Optional[int] = None
|
||||||
|
model_name: Optional[str] = None
|
||||||
|
metadata: Dict[str, Any] = None
|
||||||
|
|
||||||
|
def to_dict(self) -> Dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"prompt": self.prompt,
|
||||||
|
"response": self.response,
|
||||||
|
"tokens_prompt": self.tokens_prompt,
|
||||||
|
"tokens_response": self.tokens_response,
|
||||||
|
"model_name": self.model_name,
|
||||||
|
"metadata": self.metadata or {},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LLMAdapter:
|
||||||
|
"""Adapter around a concrete LLM backend.
|
||||||
|
|
||||||
|
backend: Callable that takes (prompt, **kwargs) and returns:
|
||||||
|
- str
|
||||||
|
- or dict with keys like:
|
||||||
|
- response
|
||||||
|
- tokens_prompt
|
||||||
|
- tokens_response
|
||||||
|
- model_name
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
backend: Callable[..., Any],
|
||||||
|
model_name: Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
self._backend = backend
|
||||||
|
self._model_name = model_name or "unknown"
|
||||||
|
|
||||||
|
def run(self, prompt: str, **kwargs: Any) -> LLMResponse:
|
||||||
|
"""Run the underlying LLM on a prompt and normalize the result."""
|
||||||
|
raw = self._backend(prompt, **kwargs)
|
||||||
|
|
||||||
|
if isinstance(raw, str):
|
||||||
|
return LLMResponse(
|
||||||
|
prompt=prompt,
|
||||||
|
response=raw,
|
||||||
|
model_name=self._model_name,
|
||||||
|
metadata={},
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(raw, dict):
|
||||||
|
return LLMResponse(
|
||||||
|
prompt=prompt,
|
||||||
|
response=str(raw.get("response", "")),
|
||||||
|
tokens_prompt=raw.get("tokens_prompt"),
|
||||||
|
tokens_response=raw.get("tokens_response"),
|
||||||
|
model_name=raw.get("model_name", self._model_name),
|
||||||
|
metadata={
|
||||||
|
k: v
|
||||||
|
for k, v in raw.items()
|
||||||
|
if k
|
||||||
|
not in {
|
||||||
|
"response",
|
||||||
|
"tokens_prompt",
|
||||||
|
"tokens_response",
|
||||||
|
"model_name",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fallback: best-effort stringification
|
||||||
|
return LLMResponse(
|
||||||
|
prompt=prompt,
|
||||||
|
response=str(raw),
|
||||||
|
model_name=self._model_name,
|
||||||
|
metadata={"raw_type": type(raw).__name__},
|
||||||
|
)
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
"""LLM symbolic compressor.
|
||||||
|
|
||||||
|
Feeds LLM interactions through the GlyphOS Cognitive Kernel and produces
|
||||||
|
a symbolic CompressionReport.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
from glyphos.cognitive_kernel import get_kernel
|
||||||
|
from glyphos.events import emit
|
||||||
|
|
||||||
|
from .llm_adapter import LLMAdapter, LLMResponse
|
||||||
|
from .compression_report import CompressionReport
|
||||||
|
|
||||||
|
|
||||||
|
def _interaction_to_payload(interaction: LLMResponse) -> bytes:
|
||||||
|
"""Serialize a single interaction into a payload for symbolic analysis."""
|
||||||
|
data = interaction.to_dict()
|
||||||
|
return json.dumps(data, ensure_ascii=False, sort_keys=True).encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def compress_interaction(
|
||||||
|
adapter: LLMAdapter,
|
||||||
|
prompt: str,
|
||||||
|
*,
|
||||||
|
mode: str = "analyze",
|
||||||
|
context: Optional[Dict[str, Any]] = None,
|
||||||
|
**llm_kwargs: Any,
|
||||||
|
) -> CompressionReport:
|
||||||
|
"""Run a single LLM interaction through the symbolic stack."""
|
||||||
|
interaction = adapter.run(prompt, **llm_kwargs)
|
||||||
|
|
||||||
|
emit(
|
||||||
|
"cognition.started",
|
||||||
|
{
|
||||||
|
"source": "LLMCompress",
|
||||||
|
"mode": mode,
|
||||||
|
"prompt_preview": prompt[:120],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
manifest: Dict[str, Any] = {
|
||||||
|
"type": "llm_interaction",
|
||||||
|
"source": "LLMCompress",
|
||||||
|
"model_name": interaction.model_name,
|
||||||
|
}
|
||||||
|
segments: List[Dict[str, Any]] = []
|
||||||
|
payload: bytes = _interaction_to_payload(interaction)
|
||||||
|
|
||||||
|
kernel = get_kernel()
|
||||||
|
exec_context: Dict[str, Any] = context.copy() if context else {}
|
||||||
|
exec_context.setdefault("source", "LLMCompress")
|
||||||
|
exec_context.setdefault("interaction_type", "single")
|
||||||
|
|
||||||
|
result = kernel.execute_symbolic(
|
||||||
|
manifest=manifest,
|
||||||
|
segments=segments,
|
||||||
|
payload=payload,
|
||||||
|
mode=mode,
|
||||||
|
context=exec_context,
|
||||||
|
)
|
||||||
|
|
||||||
|
fused_symbol = result.get("fused_symbol", {})
|
||||||
|
diagnostics = result.get("diagnostics", {})
|
||||||
|
cognition_trace = result.get("cognition_trace", [])
|
||||||
|
|
||||||
|
glyph_res = diagnostics.get("glyph_resonance") or {}
|
||||||
|
glyph_ids: List[str] = []
|
||||||
|
if isinstance(glyph_res, dict):
|
||||||
|
gid = glyph_res.get("glyph_id")
|
||||||
|
if isinstance(gid, str):
|
||||||
|
glyph_ids.append(gid)
|
||||||
|
|
||||||
|
report = CompressionReport(
|
||||||
|
interactions=[interaction.to_dict()],
|
||||||
|
fused_symbol=fused_symbol,
|
||||||
|
diagnostics=diagnostics,
|
||||||
|
cognition_trace=cognition_trace,
|
||||||
|
glyph_ids=glyph_ids,
|
||||||
|
glyph_resonance=glyph_res or None,
|
||||||
|
tags=["llm_compress", mode],
|
||||||
|
metadata={"model_name": interaction.model_name},
|
||||||
|
)
|
||||||
|
|
||||||
|
emit(
|
||||||
|
"cognition.completed",
|
||||||
|
{
|
||||||
|
"source": "LLMCompress",
|
||||||
|
"mode": mode,
|
||||||
|
"model_name": interaction.model_name,
|
||||||
|
"glyph_resonance": glyph_res or None,
|
||||||
|
"summary": fused_symbol.get("summary"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return report
|
||||||
|
|
||||||
|
|
||||||
|
def compress_session(
|
||||||
|
adapter: LLMAdapter,
|
||||||
|
prompts: List[str],
|
||||||
|
*,
|
||||||
|
mode: str = "analyze",
|
||||||
|
context: Optional[Dict[str, Any]] = None,
|
||||||
|
**llm_kwargs: Any,
|
||||||
|
) -> CompressionReport:
|
||||||
|
"""Compress a multi-turn LLM session into a single symbolic report."""
|
||||||
|
interactions = [adapter.run(p, **llm_kwargs) for p in prompts]
|
||||||
|
|
||||||
|
session_data = [i.to_dict() for i in interactions]
|
||||||
|
payload = json.dumps(
|
||||||
|
{"session": session_data},
|
||||||
|
ensure_ascii=False,
|
||||||
|
sort_keys=True,
|
||||||
|
).encode("utf-8")
|
||||||
|
|
||||||
|
manifest: Dict[str, Any] = {
|
||||||
|
"type": "llm_session",
|
||||||
|
"source": "LLMCompress",
|
||||||
|
"turns": len(interactions),
|
||||||
|
"model_name": interactions[0].model_name if interactions else None,
|
||||||
|
}
|
||||||
|
segments: List[Dict[str, Any]] = []
|
||||||
|
|
||||||
|
kernel = get_kernel()
|
||||||
|
exec_context: Dict[str, Any] = context.copy() if context else {}
|
||||||
|
exec_context.setdefault("source", "LLMCompress")
|
||||||
|
exec_context.setdefault("interaction_type", "session")
|
||||||
|
|
||||||
|
emit(
|
||||||
|
"cognition.started",
|
||||||
|
{
|
||||||
|
"source": "LLMCompress",
|
||||||
|
"mode": mode,
|
||||||
|
"turns": len(interactions),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
result = kernel.execute_symbolic(
|
||||||
|
manifest=manifest,
|
||||||
|
segments=segments,
|
||||||
|
payload=payload,
|
||||||
|
mode=mode,
|
||||||
|
context=exec_context,
|
||||||
|
)
|
||||||
|
|
||||||
|
fused_symbol = result.get("fused_symbol", {})
|
||||||
|
diagnostics = result.get("diagnostics", {})
|
||||||
|
cognition_trace = result.get("cognition_trace", [])
|
||||||
|
|
||||||
|
glyph_res = diagnostics.get("glyph_resonance") or {}
|
||||||
|
glyph_ids: List[str] = []
|
||||||
|
if isinstance(glyph_res, dict):
|
||||||
|
gid = glyph_res.get("glyph_id")
|
||||||
|
if isinstance(gid, str):
|
||||||
|
glyph_ids.append(gid)
|
||||||
|
|
||||||
|
report = CompressionReport(
|
||||||
|
interactions=session_data,
|
||||||
|
fused_symbol=fused_symbol,
|
||||||
|
diagnostics=diagnostics,
|
||||||
|
cognition_trace=cognition_trace,
|
||||||
|
glyph_ids=glyph_ids,
|
||||||
|
glyph_resonance=glyph_res or None,
|
||||||
|
tags=["llm_compress", "session", mode],
|
||||||
|
metadata={
|
||||||
|
"model_name": manifest.get("model_name"),
|
||||||
|
"turns": len(interactions),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
emit(
|
||||||
|
"cognition.completed",
|
||||||
|
{
|
||||||
|
"source": "LLMCompress",
|
||||||
|
"mode": mode,
|
||||||
|
"turns": len(interactions),
|
||||||
|
"glyph_resonance": glyph_res or None,
|
||||||
|
"summary": fused_symbol.get("summary"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return report
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,133 @@
|
|||||||
|
"""Tests for LLMCompress subsystem.
|
||||||
|
|
||||||
|
These tests verify:
|
||||||
|
|
||||||
|
- LLMAdapter normalization
|
||||||
|
- compress_interaction() end-to-end flow
|
||||||
|
- compress_session() multi-turn flow
|
||||||
|
- Integration with GlyphOS Cognitive Kernel
|
||||||
|
- Event emission during compression
|
||||||
|
|
||||||
|
This uses a fake LLM backend so tests run without external dependencies.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
from LLMCompress import (
|
||||||
|
LLMAdapter,
|
||||||
|
compress_interaction,
|
||||||
|
compress_session,
|
||||||
|
CompressionReport,
|
||||||
|
)
|
||||||
|
|
||||||
|
from glyphos.events import get_event_bus
|
||||||
|
from glyphos.cognitive_kernel import get_kernel # noqa: F401 # imported to ensure availability
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Fake LLM backend
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def fake_llm_backend(prompt: str, **kwargs: Any) -> Dict[str, Any]:
|
||||||
|
"""A deterministic fake LLM backend for testing."""
|
||||||
|
return {
|
||||||
|
"response": f"FAKE_RESPONSE({prompt})",
|
||||||
|
"tokens_prompt": len(prompt.split()),
|
||||||
|
"tokens_response": 3,
|
||||||
|
"model_name": "fake-llm-test",
|
||||||
|
"extra_info": "ok",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Tests
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def test_adapter_normalization():
|
||||||
|
adapter = LLMAdapter(fake_llm_backend, model_name="fake-llm-test")
|
||||||
|
out = adapter.run("hello world")
|
||||||
|
|
||||||
|
assert out.prompt == "hello world"
|
||||||
|
assert out.response.startswith("FAKE_RESPONSE")
|
||||||
|
assert out.tokens_prompt == 2
|
||||||
|
assert out.tokens_response == 3
|
||||||
|
assert out.model_name == "fake-llm-test"
|
||||||
|
assert isinstance(out.metadata, dict)
|
||||||
|
|
||||||
|
|
||||||
|
def test_compress_interaction_basic():
|
||||||
|
adapter = LLMAdapter(fake_llm_backend, model_name="fake-llm-test")
|
||||||
|
|
||||||
|
bus = get_event_bus()
|
||||||
|
bus.clear_history()
|
||||||
|
|
||||||
|
report = compress_interaction(adapter, "hello test")
|
||||||
|
|
||||||
|
# Report structure
|
||||||
|
assert isinstance(report, CompressionReport)
|
||||||
|
assert len(report.interactions) == 1
|
||||||
|
assert "prompt" in report.interactions[0]
|
||||||
|
assert "response" in report.interactions[0]
|
||||||
|
|
||||||
|
# Kernel output
|
||||||
|
assert isinstance(report.fused_symbol, dict)
|
||||||
|
assert isinstance(report.diagnostics, dict)
|
||||||
|
|
||||||
|
# Events fired
|
||||||
|
history = bus.get_history(limit=10)
|
||||||
|
types = [e["type"] for e in history]
|
||||||
|
|
||||||
|
assert "cognition.started" in types
|
||||||
|
assert "cognition.completed" in types
|
||||||
|
|
||||||
|
|
||||||
|
def test_compress_session_multi_turn():
|
||||||
|
adapter = LLMAdapter(fake_llm_backend, model_name="fake-llm-test")
|
||||||
|
|
||||||
|
bus = get_event_bus()
|
||||||
|
bus.clear_history()
|
||||||
|
|
||||||
|
prompts = ["turn one", "turn two", "turn three"]
|
||||||
|
report = compress_session(adapter, prompts)
|
||||||
|
|
||||||
|
assert isinstance(report, CompressionReport)
|
||||||
|
assert len(report.interactions) == 3
|
||||||
|
|
||||||
|
# Kernel output
|
||||||
|
assert isinstance(report.fused_symbol, dict)
|
||||||
|
assert isinstance(report.diagnostics, dict)
|
||||||
|
|
||||||
|
# Events fired
|
||||||
|
history = bus.get_history(limit=10)
|
||||||
|
types = [e["type"] for e in history]
|
||||||
|
|
||||||
|
assert "cognition.started" in types
|
||||||
|
assert "cognition.completed" in types
|
||||||
|
|
||||||
|
|
||||||
|
def test_payload_encoding_is_valid_json():
|
||||||
|
adapter = LLMAdapter(fake_llm_backend)
|
||||||
|
report = compress_interaction(adapter, "encode me")
|
||||||
|
|
||||||
|
# Ensure payload was JSON-serializable and processed by kernel
|
||||||
|
assert isinstance(report.fused_symbol, dict)
|
||||||
|
assert isinstance(report.diagnostics, dict)
|
||||||
|
|
||||||
|
|
||||||
|
def test_event_metadata_includes_source():
|
||||||
|
adapter = LLMAdapter(fake_llm_backend)
|
||||||
|
|
||||||
|
bus = get_event_bus()
|
||||||
|
bus.clear_history()
|
||||||
|
|
||||||
|
compress_interaction(adapter, "metadata test")
|
||||||
|
|
||||||
|
events = bus.get_history(limit=10)
|
||||||
|
found = False
|
||||||
|
for e in events:
|
||||||
|
if e["type"] == "cognition.started":
|
||||||
|
assert e["payload"]["source"] == "LLMCompress"
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
assert found, "Expected cognition.started event with source=LLMCompress"
|
||||||
Reference in New Issue
Block a user