Add native audio/image efferent surfaces + projector proof-of-shape
audio-surface.el / image-surface.el: own-core additive-synthesis WAV and
raster-PNG renderers (integer-only DSP, since EL has no floats), rendered
from learned engram signatures via a pluggable surface-profile
abstraction (surface-profile.el). audio-demo.el / image-demo.el are
drivers. NOTE: demo files hardcode absolute paths to this worktree's own
directory — will need a path fixup before landing.
elp/projector/ is a Python package the author's own README marks as
"STAGING/PROOF-OF-SHAPE — not the deliverable", superseded by the native
.el surface-profile work above; kept as a validated architecture proof.
Generated output (elp/faculty/{out,sig}, elp/projector/out,
__pycache__) intentionally excluded.
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
> **STATUS: STAGING / PROOF-OF-SHAPE — not the deliverable.** This Python package
|
||||
> proved the architecture end-to-end against the proven realizer faculty (faithful
|
||||
> md/docx/midi from real geometry: 0 ungrounded claims, SACRED polarity). Per Will's
|
||||
> steer, the DELIVERABLE is NATIVE: the seam lives on the existing EL realizer as
|
||||
> **surface-as-profile** — see `../src/surface-profile.el` and
|
||||
> `../tests/examples/surface-profile-demo.el` (compiles + runs through elc → C →
|
||||
> binary). The concepts below (one geometry-carrying frame; surface = a pluggable
|
||||
> profile; plan/realize; deterministic-from-meaning) are exactly what the native
|
||||
> module implements. Keep this package as the validated proof; build native.
|
||||
|
||||
# Efferent Multimodal Projector
|
||||
|
||||
**geometry → any surface, faithfully.** Neuron's own document-generation faculty:
|
||||
the efferent twin of the ingest organ. Ingest is afferent (world → geometry);
|
||||
this is efferent (geometry → an arbitrary-format document / any modality).
|
||||
|
||||
Built against the **proven** realizer faculty (neuron-talk sidecar `:8756`,
|
||||
artifact `art-7affa557`). The live soul (`:8742` / `:7770`) is contacted **only**
|
||||
through the read-only, GET-only `engram_client` — never mutated.
|
||||
|
||||
## The pipeline (surface-agnostic)
|
||||
|
||||
```
|
||||
geometry region + surface/format spec
|
||||
→ PLAN (manifold → document skeleton/DAG; the geometry IS the outline) plan.py
|
||||
→ REALIZE (proven realizer, scaled sentence → passage, each section faithful) realize.py
|
||||
→ COHERE (document-level flow / transitions, not stitched sentences) cohere.py
|
||||
→ EMIT (pluggable SurfaceProjector → the target surface) projectors/
|
||||
```
|
||||
|
||||
**The surface is a PARAMETER.** `pipeline.build_ir(...)` builds ONE
|
||||
surface-neutral `DocumentIR` (`document_ir.py`); `pipeline.emit(doc, surface)`
|
||||
projects it to whichever surface you name. Markdown, docx, and MIDI are the same
|
||||
IR emitted three ways.
|
||||
|
||||
## The pivot: a geometry-carrying IR
|
||||
|
||||
`DocumentIR` is **not** a text tree. Every `Block` carries BOTH:
|
||||
- `.sentences` — realized faithful text (what **text** projectors read),
|
||||
- `.provenance` — the source geometry: `subj_id / relation / obj / polarity /
|
||||
confidence / importance / salience / node_id` (what **music / image / video**
|
||||
projectors read).
|
||||
|
||||
That single decision is what makes the projector multimodal: text renders the
|
||||
words; music/image decode the geometry. A claim with no provenance cannot exist
|
||||
in the IR — faithfulness is structural.
|
||||
|
||||
## The one shared seam
|
||||
|
||||
`projectors/base.py` — `SurfaceProjector.project(frame: DocumentIR) -> bytes`
|
||||
(+ `surface / media_type / ext / modality / profile`). Register with
|
||||
`register()`. Adding a surface changes nothing upstream.
|
||||
|
||||
`TwoStageProjector` blesses the peer plan/realize decomposition:
|
||||
`spec = plan(frame)`, `bytes = realize(spec)`, `project = realize∘plan`; the
|
||||
`profile` is the pluggable per-surface knob (text lang-profile, music
|
||||
instr/mode-profile). `projectors/midi.py` is the reference two-stage impl.
|
||||
|
||||
## Surfaces
|
||||
|
||||
| surface | modality | status | emitter |
|
||||
|---|---|---|---|
|
||||
| `markdown` | text | landed | own (str) |
|
||||
| `docx` | text | landed | own minimal OOXML (stdlib `zipfile`+XML, no lib) |
|
||||
| `midi` | audio | landed (symbolic-music proof) | own minimal SMF (stdlib `struct`, no lib) |
|
||||
| `audio` (WAV) | audio | peer agent (additive synth) | conforms to `TwoStageProjector` |
|
||||
| `image` | image | documented seam | `projectors/seams.py` |
|
||||
| `video` | video | documented seam (image×sound×time) | `projectors/seams.py` |
|
||||
|
||||
Music maps: relation → scale degree (same relation → same pitch), **polarity →
|
||||
major/minor third (SACRED negation is audible)**, confidence → duration,
|
||||
importance → velocity, section → register. Deterministic projection from meaning
|
||||
— nothing invented.
|
||||
|
||||
## Faithfulness
|
||||
|
||||
`provenance.py` audits the IR: **zero** ungrounded claims, SACRED polarity
|
||||
preserved (negations reported, never dropped), COHERE introduces no new geometry
|
||||
(connectives are marked). `trace_table()` emits the geometry → section → claim
|
||||
table.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
PY=~/Desktop/lang-realizers/venv/bin/python
|
||||
PYTHONPATH=~/Desktop/neuron-talk:~/Desktop/lang-realizers $PY generate.py
|
||||
# writes ./out/{neuron-self,engram-temporal}.{md,docx,mid} + *.audit.json + *.provenance.md
|
||||
```
|
||||
|
||||
Requires the proven realizer env (spaCy + the neuron-talk/lang-realizers engine)
|
||||
and the read-only engram at `:8742`.
|
||||
@@ -0,0 +1,79 @@
|
||||
"""cohere.py — COHERE stage: document-level flow, not stitched sentences.
|
||||
|
||||
Fidelity is REALIZE's job; FLOW is this stage's. The hard part beyond sentence
|
||||
fidelity is that a document must read as one thing. We add connective tissue at
|
||||
the passage level:
|
||||
|
||||
* an opening abstract that names what the document covers (built ONLY from the
|
||||
section headings that already exist — it introduces no new claim),
|
||||
* a short transition lead into each section after the first, drawn from a
|
||||
fixed set of discourse connectives ("Beyond that,", "Relatedly,", ...) that
|
||||
carry no propositional content,
|
||||
* ordering so the highest-grounded section leads.
|
||||
|
||||
CRITICAL: every connective is marked ``kind="connective"`` in its provenance, so
|
||||
the faithfulness audit can prove COHERE introduced ZERO new geometry claims. A
|
||||
transition is discourse glue, never a fact.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from document_ir import Block, DocumentIR, Provenance
|
||||
|
||||
# discourse connectives — pure flow, no propositional content
|
||||
_TRANSITIONS = [
|
||||
"Beyond that,", "Relatedly,", "In the same region,", "From there,",
|
||||
"Alongside this,", "Further,", "Turning to the next facet,",
|
||||
]
|
||||
|
||||
|
||||
def _connective_prov() -> Provenance:
|
||||
return Provenance(subj_id=None, subject=None, relation="", obj=None,
|
||||
polarity="aff", confidence=1.0, node_id=None,
|
||||
kind="connective")
|
||||
|
||||
|
||||
def _abstract_block(doc: DocumentIR) -> Block:
|
||||
"""A grounded opening: names the sections, asserts nothing new."""
|
||||
headings = [s.heading for s in doc.sections]
|
||||
if not headings:
|
||||
return Block(role="lead")
|
||||
if len(headings) == 1:
|
||||
body = f"This document, generated from Neuron's geometry, covers {headings[0]}."
|
||||
else:
|
||||
listed = ", ".join(headings[:-1]) + f", and {headings[-1]}"
|
||||
body = ("This document is projected directly from Neuron's meaning-geometry. "
|
||||
f"It traces {listed}.")
|
||||
b = Block(role="lead")
|
||||
b.sentences.append(body)
|
||||
b.provenance.append(_connective_prov())
|
||||
return b
|
||||
|
||||
|
||||
def cohere_document(doc: DocumentIR, *, add_abstract: bool = True,
|
||||
add_transitions: bool = True) -> DocumentIR:
|
||||
"""Order sections by grounding, add abstract + transitions (flow only)."""
|
||||
# order: strongest-grounded section (mean confidence x #claims) first,
|
||||
# but keep an explicitly-first section if the plan pinned one via level 1.
|
||||
def _score(sec):
|
||||
provs = [p for p in sec.all_provenance() if p.kind == "fact"]
|
||||
if not provs:
|
||||
return 0.0
|
||||
mean_conf = sum(p.confidence for p in provs) / len(provs)
|
||||
return mean_conf * len(provs)
|
||||
|
||||
doc.sections.sort(key=_score, reverse=True)
|
||||
|
||||
if add_transitions:
|
||||
for i, sec in enumerate(doc.sections):
|
||||
if i == 0 or not sec.blocks:
|
||||
continue
|
||||
lead = _TRANSITIONS[(i - 1) % len(_TRANSITIONS)]
|
||||
first = sec.blocks[0]
|
||||
if first.sentences:
|
||||
# prepend the connective to the first sentence (flow, no new claim)
|
||||
first.sentences[0] = f"{lead} {first.sentences[0][0].lower()}{first.sentences[0][1:]}"
|
||||
|
||||
if add_abstract:
|
||||
doc.meta["abstract"] = _abstract_block(doc)
|
||||
|
||||
return doc
|
||||
@@ -0,0 +1,111 @@
|
||||
"""document_ir.py — the surface-neutral, GEOMETRY-CARRYING document intermediate.
|
||||
|
||||
This is the pivot of the whole efferent projector. A DocumentIR is NOT a text
|
||||
tree. It is a projection of a meaning-geometry region that carries, at every
|
||||
leaf, BOTH:
|
||||
|
||||
* the realized surface text (``Block.sentences``) — what a TEXT projector reads,
|
||||
* the source geometry (``Block.provenance``) — what a MUSIC / IMAGE /
|
||||
VIDEO projector reads.
|
||||
|
||||
Because the IR holds the geometry, not just the words, the SAME
|
||||
plan -> realize -> cohere pipeline drives every surface. A markdown projector
|
||||
renders the sentences; a music projector reads the provenance edges (salience,
|
||||
importance, polarity, relation) and maps them onto a symbolic-music surface;
|
||||
an image/video projector (documented seam) would read the same geometry.
|
||||
|
||||
Nothing in this module invents content. Every :class:`Provenance` points at a
|
||||
real engram node id and a real relation. That is the faithfulness contract made
|
||||
structural: a claim with no provenance cannot exist in the IR.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Provenance — the geometry an emitted claim traces to. FAITHFULNESS is here.
|
||||
# --------------------------------------------------------------------------- #
|
||||
@dataclass
|
||||
class Provenance:
|
||||
"""One geometry edge behind one realized claim.
|
||||
|
||||
``kind`` distinguishes a FACT (a structural edge asserted by the geometry,
|
||||
spoken as fact) from an INTERPRETATION (something attributed, spoken with
|
||||
attribution) — the facts-as-facts + interpretations-attributed discipline
|
||||
(memory 80927e26). ``polarity`` is SACRED: a negated edge stays negated.
|
||||
"""
|
||||
subj_id: str | None # source engram node id of the subject
|
||||
subject: str | None # normalized subject surface
|
||||
relation: str # predicate lemma (e.g. "use", "contain", "be")
|
||||
obj: str | None # normalized object / complement surface
|
||||
polarity: str = "aff" # "aff" | "neg" (SACRED — never silently flipped)
|
||||
confidence: float = 0.0 # extraction confidence in [0,1]
|
||||
node_id: str | None = None # engram node the claim was extracted from
|
||||
kind: str = "fact" # "fact" | "interpretation"
|
||||
importance: float = 0.0 # source node importance (drives music/emphasis)
|
||||
salience: float = 0.0 # source node salience
|
||||
|
||||
def trace(self) -> str:
|
||||
arrow = "-->" if self.polarity == "aff" else "--NOT-->"
|
||||
return (f"[{(self.node_id or '?')[:8]}] {self.subject!r} {arrow}"
|
||||
f"{self.relation} {self.obj!r} (conf {self.confidence:.2f})")
|
||||
|
||||
|
||||
@dataclass
|
||||
class Block:
|
||||
"""A passage: one or more faithful sentences + the geometry they trace to.
|
||||
|
||||
``sentences`` and ``provenance`` are index-aligned where possible: sentence
|
||||
``i`` was realized from ``provenance[i]``. A COHERE transition sentence with
|
||||
no new geometry carries a provenance whose ``kind == "connective"`` so the
|
||||
audit can see it introduced no new claim.
|
||||
"""
|
||||
sentences: list[str] = field(default_factory=list)
|
||||
provenance: list[Provenance] = field(default_factory=list)
|
||||
role: str = "body" # "body" | "lead" | "transition"
|
||||
|
||||
def text(self) -> str:
|
||||
return " ".join(s.rstrip(". ") + "." for s in self.sentences if s.strip())
|
||||
|
||||
|
||||
@dataclass
|
||||
class Section:
|
||||
heading: str
|
||||
level: int = 2 # markdown heading level / outline depth
|
||||
blocks: list[Block] = field(default_factory=list)
|
||||
seed_ids: list[str] = field(default_factory=list) # geometry nodes of section
|
||||
summary: str = "" # one-line grounded gloss (for pptx bullets / TOC)
|
||||
|
||||
def all_provenance(self) -> list[Provenance]:
|
||||
out: list[Provenance] = []
|
||||
for b in self.blocks:
|
||||
out.extend(b.provenance)
|
||||
return out
|
||||
|
||||
|
||||
@dataclass
|
||||
class DocumentIR:
|
||||
"""The surface-neutral document. Built ONCE, projected to ANY surface."""
|
||||
title: str
|
||||
subtitle: str = ""
|
||||
sections: list[Section] = field(default_factory=list)
|
||||
seed_id: str | None = None # the geometry region root
|
||||
format_spec: dict[str, Any] = field(default_factory=dict) # requested shape
|
||||
meta: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
# -- geometry facets (what non-text projectors consume) ----------------- #
|
||||
def all_provenance(self) -> list[Provenance]:
|
||||
out: list[Provenance] = []
|
||||
for s in self.sections:
|
||||
out.extend(s.all_provenance())
|
||||
return out
|
||||
|
||||
def claim_count(self) -> int:
|
||||
return sum(1 for p in self.all_provenance() if p.kind in ("fact", "interpretation"))
|
||||
|
||||
def ungrounded_count(self) -> int:
|
||||
"""Claims with no traceable node — MUST be zero for a faithful doc."""
|
||||
return sum(1 for p in self.all_provenance()
|
||||
if p.kind in ("fact", "interpretation") and not p.node_id)
|
||||
@@ -0,0 +1,81 @@
|
||||
"""generate.py — drive the projector: one geometry region -> many surfaces.
|
||||
|
||||
Proves the thesis with REAL output: builds ONE surface-neutral DocumentIR from
|
||||
Neuron's OWN self-geometry (read-only against the live soul via the proven
|
||||
faculty), then EMITS it to Markdown, docx, and MIDI — the same plan/realize/
|
||||
cohere, three surfaces. Writes the files + the faithfulness audit to ./out/.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
_HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, _HERE)
|
||||
|
||||
import pipeline # noqa: E402
|
||||
import provenance # noqa: E402
|
||||
from geometry import load_self_region # noqa: E402
|
||||
|
||||
OUT = os.path.join(_HERE, "out")
|
||||
|
||||
|
||||
def _emit_all(doc, stem):
|
||||
"""Emit one IR to every text/audio surface + audit + provenance."""
|
||||
for surface in ("markdown", "docx", "midi"):
|
||||
data = pipeline.emit(doc, surface)
|
||||
proj = pipeline.get_projector(surface)
|
||||
path = os.path.join(OUT, f"{stem}.{proj.ext}")
|
||||
with open(path, "wb") as f:
|
||||
f.write(data)
|
||||
print(f" emitted {surface:9s} -> {os.path.basename(path)} ({len(data)} bytes)")
|
||||
a = provenance.audit(doc)
|
||||
with open(os.path.join(OUT, f"{stem}.audit.json"), "w") as f:
|
||||
json.dump(a, f, indent=2)
|
||||
with open(os.path.join(OUT, f"{stem}.provenance.md"), "w") as f:
|
||||
f.write(provenance.trace_table(doc))
|
||||
print(" audit:", {k: a[k] for k in ("claims", "ungrounded_claims",
|
||||
"negations_preserved", "distinct_source_nodes", "faithful")})
|
||||
return a
|
||||
|
||||
|
||||
def main():
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
print("surfaces registered:", pipeline.available_surfaces())
|
||||
|
||||
# ---- Document 1: Neuron's self-description (marquee) ------------------- #
|
||||
print("\n[1] Neuron self-description")
|
||||
region = load_self_region(max_nodes=9)
|
||||
print(" self region:", region)
|
||||
doc1 = pipeline.build_ir(
|
||||
None, region=region,
|
||||
title="Neuron: A Self-Description from Its Own Geometry",
|
||||
subtitle="Projected efferently from the engram — every claim traces a node.",
|
||||
format_spec={"genre": "self-description", "register": "expository"},
|
||||
max_sections=5, conf_floor=0.6)
|
||||
print(f" IR: {len(doc1.sections)} sections, {doc1.claim_count()} claims, "
|
||||
f"ungrounded={doc1.ungrounded_count()}")
|
||||
_emit_all(doc1, "neuron-self")
|
||||
|
||||
# ---- Document 2: a coherent, clean whitepaper-style section ------------ #
|
||||
print("\n[2] Whitepaper-style section (coherent clean region)")
|
||||
doc2, _ = pipeline.project(
|
||||
["chronoception", "time", "awareness", "engram", "temporal"],
|
||||
surface="markdown",
|
||||
title="Temporal Awareness in the Engram",
|
||||
subtitle="A section projected from the geometry of chronoception.",
|
||||
format_spec={"genre": "whitepaper-section", "register": "technical"},
|
||||
max_sections=4)
|
||||
print(f" IR: {len(doc2.sections)} sections, {doc2.claim_count()} claims, "
|
||||
f"ungrounded={doc2.ungrounded_count()}")
|
||||
_emit_all(doc2, "engram-temporal")
|
||||
|
||||
# echo both markdowns so they are visible in the run log
|
||||
for stem, doc in (("neuron-self", doc1), ("engram-temporal", doc2)):
|
||||
print(f"\n===== GENERATED MARKDOWN — {stem} =====\n")
|
||||
print(pipeline.emit(doc, "markdown").decode())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,129 @@
|
||||
"""geometry.py — READ-ONLY loader for a meaning-geometry region.
|
||||
|
||||
The efferent projector never writes to the soul. This module reaches the
|
||||
geometry through the PROVEN, read-only neuron-talk faculty (``engram_client``,
|
||||
GET-only, which physically refuses non-GET methods) against the running sidecar
|
||||
soul. The live daemon :8742 / :7770 is contacted ONLY through that read-only
|
||||
client — never mutated.
|
||||
|
||||
A "region" is a seed node plus a bounded neighborhood: the manifold that will
|
||||
become the document's skeleton. We pool a few single-term lexical searches
|
||||
(the engram search is a single-term matcher) and, when available, walk one hop
|
||||
of reified neighbors, then rank by self/importance signal.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Wire in the proven faculty (own-the-core: we reuse it, we do not fork it).
|
||||
_NT = os.path.expanduser("~/Desktop/neuron-talk")
|
||||
_LR = os.path.expanduser("~/Desktop/lang-realizers")
|
||||
for _p in (_NT, _LR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from engram_client import ReadOnlyEngramClient # noqa: E402
|
||||
|
||||
|
||||
class Region:
|
||||
"""A geometry region: ranked nodes + the reified edges among them."""
|
||||
|
||||
def __init__(self, seed: str, nodes: list[dict], edges: list[dict]):
|
||||
self.seed = seed
|
||||
self.nodes = nodes # ranked engram node dicts
|
||||
self.edges = edges # [{src, dst, edge, ...}]
|
||||
self.by_id = {n["id"]: n for n in nodes if n.get("id")}
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Region seed={self.seed!r} nodes={len(self.nodes)} edges={len(self.edges)}>"
|
||||
|
||||
|
||||
def _prose_quality(content: str) -> float:
|
||||
"""Reward clean expository prose; penalize shouty banner-dense nodes.
|
||||
|
||||
A high ALLCAPS-word ratio or very short content signals a banner/telegraphic
|
||||
memory node that extracts into garbage. Clean declarative prose scores high.
|
||||
"""
|
||||
if not content or not content.strip():
|
||||
return 0.0
|
||||
words = content.split()
|
||||
if len(words) < 8:
|
||||
return 0.1
|
||||
caps = sum(1 for w in words if len(w) > 2 and w.strip(".,:;'\"-").isupper())
|
||||
caps_ratio = caps / max(1, len(words))
|
||||
# sentences with lowercase interior words read as prose
|
||||
lower = sum(1 for w in words if w[:1].islower())
|
||||
lower_ratio = lower / max(1, len(words))
|
||||
return max(0.0, 1.2 * lower_ratio - 2.0 * caps_ratio)
|
||||
|
||||
|
||||
def _relevance(content: str, terms: list[str]) -> float:
|
||||
"""Topical relevance to the seed terms — keeps a region ON-THEME so a clean
|
||||
but off-topic node cannot hijack the document."""
|
||||
if not terms:
|
||||
return 0.0
|
||||
low = (content or "").lower()
|
||||
hits = sum(1 for t in terms if t.lower() in low)
|
||||
return hits / max(1, len(terms))
|
||||
|
||||
|
||||
def _node_rank(n: dict, terms: list[str] | None = None) -> float:
|
||||
return (float(n.get("importance") or 0.0) * 2.0
|
||||
+ float(n.get("salience") or 0.0)
|
||||
+ 1.5 * _prose_quality(n.get("content") or "")
|
||||
+ 2.0 * _relevance(n.get("content") or "", terms or [])
|
||||
+ (0.5 if (n.get("content") or "").strip() else 0.0))
|
||||
|
||||
|
||||
def load_region(seed_terms: list[str] | str, *, client: ReadOnlyEngramClient | None = None,
|
||||
max_nodes: int = 10, per_term: int = 20, hop: bool = True) -> Region:
|
||||
"""Pull a bounded geometry region around ``seed_terms`` (read-only).
|
||||
|
||||
``seed_terms`` may be a single string or several probe terms; results are
|
||||
pooled and de-duplicated. When ``hop`` and the reified neighbor endpoint is
|
||||
live, one hop of neighbors is folded in so the region is a real
|
||||
neighborhood, not just a keyword hit list.
|
||||
"""
|
||||
client = client or ReadOnlyEngramClient()
|
||||
if isinstance(seed_terms, str):
|
||||
seed_terms = [seed_terms]
|
||||
|
||||
pool: dict[str, dict] = {}
|
||||
for term in seed_terms:
|
||||
for n in client.search(term, limit=per_term):
|
||||
if isinstance(n, dict) and n.get("id"):
|
||||
pool.setdefault(n["id"], n)
|
||||
|
||||
ranked = sorted(pool.values(), key=lambda n: _node_rank(n, seed_terms),
|
||||
reverse=True)
|
||||
nodes = ranked[:max_nodes]
|
||||
|
||||
edges: list[dict] = []
|
||||
if hop and nodes:
|
||||
present = {n["id"] for n in nodes}
|
||||
for n in list(nodes):
|
||||
try:
|
||||
for nb in client.neighbors(n["id"]):
|
||||
node = nb.get("node") if isinstance(nb, dict) else None
|
||||
edge = nb.get("edge") if isinstance(nb, dict) else None
|
||||
if node and node.get("id"):
|
||||
edges.append({"src": n["id"], "dst": node["id"],
|
||||
"edge": edge})
|
||||
# fold a strong neighbor into the region (bounded)
|
||||
if (node["id"] not in present and len(nodes) < max_nodes + 6
|
||||
and _node_rank(node, seed_terms) > 0.4):
|
||||
present.add(node["id"])
|
||||
nodes.append(node)
|
||||
except Exception: # noqa: BLE001 — read-only best-effort; never fatal
|
||||
continue
|
||||
|
||||
return Region(seed=", ".join(seed_terms), nodes=nodes, edges=edges)
|
||||
|
||||
|
||||
def load_self_region(client: ReadOnlyEngramClient | None = None,
|
||||
max_nodes: int = 10) -> Region:
|
||||
"""The self/identity region — Neuron's own geometry, for self-description."""
|
||||
return load_region(["self", "identity", "Neuron", "values", "memory",
|
||||
"imprint", "consciousness"],
|
||||
client=client, max_nodes=max_nodes)
|
||||
@@ -0,0 +1,67 @@
|
||||
"""pipeline.py — the Efferent Multimodal Projector, top level.
|
||||
|
||||
geometry region + surface/format spec
|
||||
-> PLAN (manifold -> document skeleton/DAG)
|
||||
-> REALIZE (proven realizer, sentence -> passage, each section faithful)
|
||||
-> COHERE (document-level flow / transitions, not stitched sentences)
|
||||
-> EMIT (pluggable SurfaceProjector -> the target surface)
|
||||
|
||||
THE SURFACE IS A PARAMETER. ``project(...)`` builds the geometry-carrying
|
||||
DocumentIR once, then hands it to whichever surface projector the caller named.
|
||||
Markdown, docx, and midi (music) are all the SAME IR emitted differently. That
|
||||
is the efferent multimodal projector: geometry -> any surface.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
_HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, _HERE)
|
||||
sys.path.insert(0, os.path.join(_HERE, "projectors"))
|
||||
|
||||
from cohere import cohere_document # noqa: E402
|
||||
from document_ir import DocumentIR # noqa: E402
|
||||
from geometry import Region, load_region # noqa: E402
|
||||
from plan import plan_document # noqa: E402
|
||||
from realize import realize_document # noqa: E402
|
||||
|
||||
# registering the projectors (import for side-effect: each self-registers)
|
||||
import projectors.markdown # noqa: E402,F401
|
||||
import projectors.docx # noqa: E402,F401
|
||||
import projectors.midi # noqa: E402,F401
|
||||
import projectors.seams # noqa: E402,F401
|
||||
from projectors.base import available_surfaces, get_projector # noqa: E402
|
||||
|
||||
|
||||
def build_ir(seed_terms, *, title: str, subtitle: str = "",
|
||||
format_spec: dict | None = None,
|
||||
region: Region | None = None,
|
||||
max_sections: int = 8, conf_floor: float = 0.55) -> DocumentIR:
|
||||
"""geometry -> PLAN -> REALIZE -> COHERE = the surface-neutral DocumentIR."""
|
||||
region = region or load_region(seed_terms)
|
||||
doc = plan_document(region, title=title, subtitle=subtitle,
|
||||
format_spec=format_spec or {},
|
||||
conf_floor=conf_floor, max_sections=max_sections)
|
||||
doc = realize_document(doc)
|
||||
doc = cohere_document(doc)
|
||||
return doc
|
||||
|
||||
|
||||
def emit(doc: DocumentIR, surface: str) -> bytes:
|
||||
"""EMIT: project the built IR onto one surface (surface = a parameter)."""
|
||||
return get_projector(surface).project(doc)
|
||||
|
||||
|
||||
def project(seed_terms, *, surface: str, title: str, subtitle: str = "",
|
||||
format_spec: dict | None = None, region: Region | None = None,
|
||||
max_sections: int = 8) -> tuple[DocumentIR, bytes]:
|
||||
"""The full efferent projection: geometry + surface -> (IR, bytes)."""
|
||||
doc = build_ir(seed_terms, title=title, subtitle=subtitle,
|
||||
format_spec=format_spec, region=region,
|
||||
max_sections=max_sections)
|
||||
return doc, emit(doc, surface)
|
||||
|
||||
|
||||
__all__ = ["build_ir", "emit", "project", "available_surfaces",
|
||||
"get_projector", "load_region", "DocumentIR"]
|
||||
@@ -0,0 +1,192 @@
|
||||
"""plan.py — PLAN stage: geometry region -> document skeleton (a DAG/outline).
|
||||
|
||||
The manifold becomes the skeleton. We extract faithful propositions from the
|
||||
region's nodes (the proven neuron-talk extractor, SACRED polarity preserved),
|
||||
apply a quality floor, then GROUP them into sections. Grouping is by source
|
||||
node — each engram node is one coherent topic, so one salient node becomes one
|
||||
section. The section ORDER is the node ranking (importance/salience): the
|
||||
geometry decides the outline, not a template.
|
||||
|
||||
Output: a DocumentIR whose sections carry seed node ids and empty blocks. REALIZE
|
||||
fills the blocks; the plan owns the structure.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
_NT = os.path.expanduser("~/Desktop/neuron-talk")
|
||||
_LR = os.path.expanduser("~/Desktop/lang-realizers")
|
||||
for _p in (_NT, _LR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
import propositions # noqa: E402 (the proven, faithful extractor)
|
||||
|
||||
from document_ir import DocumentIR, Section # noqa: E402
|
||||
from geometry import Region # noqa: E402
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Proposition quality — keep only clean, well-grounded claims.
|
||||
# --------------------------------------------------------------------------- #
|
||||
_JUNK_RE = re.compile(r"[.][a-z]{1,3}\b|[^A-Za-z0-9 '\-]") # ".o", stray symbols
|
||||
|
||||
|
||||
def _has_banner_token(s: str) -> bool:
|
||||
"""True if any word is an ALLCAPS banner token (DHARMA, ENGRAM, MEASURED)."""
|
||||
for w in (s or "").split():
|
||||
core = w.strip(".,:;'\"-")
|
||||
if len(core) > 2 and core.isupper():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _clean_prop(p, floor: float) -> bool:
|
||||
if p.confidence < floor:
|
||||
return False
|
||||
if not p.subject or not (p.object or (p.obj_np is not None)):
|
||||
return False
|
||||
subj = (p.subject or "").strip()
|
||||
obj = (p.object or "").strip()
|
||||
if len(subj) < 2:
|
||||
return False
|
||||
# banner-derived shouty fragments read as garbage in prose
|
||||
if _has_banner_token(subj) or _has_banner_token(obj):
|
||||
return False
|
||||
if propositions._is_shouty(p.sentence or ""):
|
||||
return False
|
||||
# junk tokens: file-extension fragments (".o"), stray non-word symbols
|
||||
if _JUNK_RE.search(subj) or _JUNK_RE.search(obj):
|
||||
return False
|
||||
# a proposition whose object repeats the subject is usually a parse artifact
|
||||
if obj and subj.lower() == obj.lower():
|
||||
return False
|
||||
# a bare copula with no real complement ("X is it") reads as noise
|
||||
if p.predicate == "be" and obj.lower() in ("it", "no", "nothing", "empty", ""):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _dedup(props):
|
||||
"""Drop duplicate claims. Two axes: (a) identical (pred,obj,polarity), and
|
||||
(b) same (subject,predicate) — which collapses a mis-split compound like
|
||||
"detection is post-hoc eval" -> "Detection is post/hoc/eval" into one claim
|
||||
(keep the highest-confidence surface)."""
|
||||
props = sorted(props, key=lambda p: p.confidence, reverse=True)
|
||||
seen_po, seen_sp, out = set(), set(), []
|
||||
for p in props:
|
||||
subj = (p.subject or "").lower()
|
||||
po = (p.predicate, (p.object or "").lower(), p.polarity)
|
||||
sp = (subj, p.predicate, p.polarity)
|
||||
if po in seen_po or sp in seen_sp:
|
||||
continue
|
||||
seen_po.add(po)
|
||||
seen_sp.add(sp)
|
||||
out.append(p)
|
||||
return out
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Heading derivation — a clean human heading from a node.
|
||||
# --------------------------------------------------------------------------- #
|
||||
_HEADING_RE = re.compile(r"^\s*#{1,4}\s+(.{2,70})\s*$", re.M)
|
||||
# node-type / system labels that are NOT topical headings
|
||||
_NONTOPIC_LABEL = re.compile(r"^(memory|node|knowledge|doc|session)[:/]", re.I)
|
||||
|
||||
|
||||
def _titlecase_banner(s: str) -> str:
|
||||
"""A shouty banner ("CHRONOCEPTION — SCALE-INVARIANCE") makes a fine title
|
||||
once Title-cased. Keep short acronyms uppercase."""
|
||||
def fix(w):
|
||||
core = w.strip("—-:,.")
|
||||
if len(core) <= 3 and core.isupper():
|
||||
return w # acronym
|
||||
return w.capitalize()
|
||||
return " ".join(fix(w) for w in s.split())
|
||||
|
||||
|
||||
def _clean_heading(text: str) -> str | None:
|
||||
"""First line only, no markdown, capped, banner Title-cased. None if unusable."""
|
||||
if not text:
|
||||
return None
|
||||
line = text.strip().splitlines()[0]
|
||||
line = re.sub(r"^#+\s*", "", line).strip().strip("#").strip()
|
||||
# cut at a natural break so a long banner heading stays a heading, not a para
|
||||
for sep in (" — ", " – ", ": ", ". "):
|
||||
if sep in line and len(line) > 48:
|
||||
line = line.split(sep)[0].strip()
|
||||
break
|
||||
if not (3 <= len(line) <= 64):
|
||||
return None
|
||||
if propositions._is_shouty(line):
|
||||
line = _titlecase_banner(line)
|
||||
return line or None
|
||||
|
||||
|
||||
def _heading_for(node: dict, fallback: str) -> str:
|
||||
label = (node.get("label") or "").strip()
|
||||
content = node.get("content") or ""
|
||||
candidates: list[str] = []
|
||||
# a node-type label ("memory:remembered") is never a topic — skip it
|
||||
if label and not _NONTOPIC_LABEL.match(label):
|
||||
candidates.append(label)
|
||||
m = _HEADING_RE.search(content)
|
||||
if m:
|
||||
candidates.append(m.group(1))
|
||||
# the leading banner/first sentence of the content is often the real title
|
||||
first = re.split(r"(?<=[.\n])", content.strip(), maxsplit=1)[0] if content.strip() else ""
|
||||
candidates.append(first)
|
||||
for c in candidates:
|
||||
h = _clean_heading(c)
|
||||
if h:
|
||||
return h
|
||||
return fallback
|
||||
|
||||
|
||||
def plan_document(region: Region, *, title: str, subtitle: str = "",
|
||||
format_spec: dict | None = None,
|
||||
conf_floor: float = 0.55,
|
||||
max_sections: int = 8,
|
||||
max_claims_per_section: int = 6) -> DocumentIR:
|
||||
"""Region -> DocumentIR skeleton. The geometry dictates the outline."""
|
||||
format_spec = format_spec or {}
|
||||
doc = DocumentIR(title=title, subtitle=subtitle,
|
||||
seed_id=region.nodes[0]["id"] if region.nodes else None,
|
||||
format_spec=format_spec)
|
||||
|
||||
made = 0
|
||||
seen_headings: set[str] = set()
|
||||
for node in region.nodes:
|
||||
if made >= max_sections:
|
||||
break
|
||||
props = propositions.extract(node.get("content") or "",
|
||||
node_id=node.get("id"),
|
||||
node_importance=float(node.get("importance") or 0.0),
|
||||
max_sentences=10)
|
||||
props = [p for p in props if _clean_prop(p, conf_floor)]
|
||||
props = _dedup(props)
|
||||
props.sort(key=lambda p: p.confidence, reverse=True)
|
||||
props = props[:max_claims_per_section]
|
||||
if not props:
|
||||
continue
|
||||
heading = _heading_for(node, fallback=f"Region {made + 1}")
|
||||
# cross-section dedup: a topic appears once. Distinguish by top claim
|
||||
# subject, else drop the collision so the outline stays clean.
|
||||
if heading.lower() in seen_headings:
|
||||
subj = (props[0].subject or "").strip().title()
|
||||
alt = f"{heading}: {subj}" if subj and subj.lower() not in heading.lower() else None
|
||||
if alt and alt.lower() not in seen_headings and len(alt) <= 64:
|
||||
heading = alt
|
||||
else:
|
||||
continue
|
||||
seen_headings.add(heading.lower())
|
||||
sec = Section(heading=heading, level=2, seed_ids=[node["id"]])
|
||||
# stash the planned propositions on the section for REALIZE
|
||||
sec.__dict__["_planned_props"] = props
|
||||
sec.__dict__["_node"] = node
|
||||
doc.sections.append(sec)
|
||||
made += 1
|
||||
|
||||
return doc
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,106 @@
|
||||
"""base.py — the SurfaceProjector interface + registry.
|
||||
|
||||
THE key abstraction of the efferent projector: a projector is a pure function
|
||||
from the surface-neutral, geometry-carrying DocumentIR to bytes on a target
|
||||
SURFACE. The surface is a PARAMETER. Adding a surface = registering one more
|
||||
projector; nothing upstream (plan/realize/cohere) changes.
|
||||
|
||||
DocumentIR --project--> bytes (per surface)
|
||||
|
||||
A TEXT projector reads ``block.sentences``. A NON-TEXT projector (music, image,
|
||||
video) reads ``block.provenance`` — the geometry the IR carries — and decodes it
|
||||
onto its surface. Both consume the SAME IR. That symmetry is the whole design:
|
||||
the realizer generalizes into a multimodal projector, geometry -> any surface.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Protocol, runtime_checkable
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from document_ir import DocumentIR # noqa: E402
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class SurfaceProjector(Protocol):
|
||||
"""Geometry-document -> one surface. Implementations MUST be pure & faithful.
|
||||
|
||||
THE ONE SHARED SEAM. Every surface — text, music, image, video — conforms to
|
||||
this single contract:
|
||||
|
||||
project(frame: DocumentIR) -> bytes
|
||||
|
||||
where ``frame`` is the geometry-carrying meaning-geometry (the SemFrame at
|
||||
document scale; a single utterance is the degenerate one-section frame).
|
||||
|
||||
RECOMMENDED INTERNAL SHAPE (the peer music/text decomposition, blessed here
|
||||
so all surfaces share it): a projector may split ``project`` into
|
||||
|
||||
spec = self.plan(frame) # meaning-geometry -> surface-specific spec
|
||||
bytes = self.realize(spec) # spec -> surface, via this projector's PROFILE
|
||||
|
||||
``project`` is then ``realize(plan(frame))``. The PROFILE (a text lang-profile,
|
||||
a music instr/mode-profile, an image layout-profile) is a property of the
|
||||
projector instance — the pluggable knob. See :class:`TwoStageProjector`.
|
||||
|
||||
A TEXT projector's plan reads ``frame`` sentences; a MUSIC/IMAGE projector's
|
||||
plan reads ``frame.all_provenance()`` — the geometry — and derives its spec
|
||||
(pitch/harmony/rhythm, or layout) FROM the meaning, deterministically. Same
|
||||
frame, different profile.
|
||||
"""
|
||||
|
||||
surface: str # "markdown" | "docx" | "midi" | "audio" | "image" | "video"
|
||||
media_type: str # MIME type of the emitted bytes
|
||||
ext: str # file extension (no dot)
|
||||
modality: str # "text" | "audio" | "image" | "video"
|
||||
profile: object # the pluggable per-surface profile (may be None)
|
||||
|
||||
def project(self, doc: DocumentIR) -> bytes:
|
||||
"""Emit the document on this surface. Returns raw bytes."""
|
||||
...
|
||||
|
||||
|
||||
class TwoStageProjector:
|
||||
"""Optional base for the peer plan()/realize() decomposition.
|
||||
|
||||
Subclasses implement ``plan(frame) -> spec`` and ``realize(spec) -> bytes``;
|
||||
``project`` is their composition. This is exactly the peer music interface
|
||||
(spec = plan(frame, profile); surface = realize(spec, profile)) expressed so
|
||||
that it still satisfies the single ``SurfaceProjector.project`` seam. Text,
|
||||
music, and image projectors can all subclass this and remain interchangeable.
|
||||
"""
|
||||
|
||||
surface: str = ""
|
||||
media_type: str = ""
|
||||
ext: str = ""
|
||||
modality: str = ""
|
||||
profile: object = None
|
||||
|
||||
def plan(self, doc: DocumentIR): # -> spec
|
||||
raise NotImplementedError
|
||||
|
||||
def realize(self, spec) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
||||
def project(self, doc: DocumentIR) -> bytes:
|
||||
return self.realize(self.plan(doc))
|
||||
|
||||
|
||||
_REGISTRY: dict[str, SurfaceProjector] = {}
|
||||
|
||||
|
||||
def register(projector: SurfaceProjector) -> SurfaceProjector:
|
||||
_REGISTRY[projector.surface] = projector
|
||||
return projector
|
||||
|
||||
|
||||
def get_projector(surface: str) -> SurfaceProjector:
|
||||
if surface not in _REGISTRY:
|
||||
raise KeyError(f"no projector registered for surface {surface!r}; "
|
||||
f"have {sorted(_REGISTRY)}")
|
||||
return _REGISTRY[surface]
|
||||
|
||||
|
||||
def available_surfaces() -> list[str]:
|
||||
return sorted(_REGISTRY)
|
||||
@@ -0,0 +1,113 @@
|
||||
"""docx.py — the .docx surface projector: an OWN minimal OOXML emitter.
|
||||
|
||||
Own-the-core: a .docx is just a ZIP of a few XML parts (WordprocessingML). We
|
||||
emit it with the standard library only — ``zipfile`` + string XML — no
|
||||
python-docx, no external dependency. This proves a "richer structured format"
|
||||
surface without importing anyone else's toolkit.
|
||||
|
||||
Parts emitted (the minimal valid set + a styles part for real headings):
|
||||
[Content_Types].xml
|
||||
_rels/.rels
|
||||
word/_rels/document.xml.rels
|
||||
word/styles.xml (Title / Heading1 / Heading2 / Normal)
|
||||
word/document.xml (the content)
|
||||
|
||||
Like the markdown projector it reads only the IR's realized sentences; it
|
||||
invents nothing. The surface differs, the faithful content does not.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import zipfile
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from document_ir import DocumentIR # noqa: E402
|
||||
from projectors.base import register # noqa: E402
|
||||
|
||||
_CONTENT_TYPES = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
|
||||
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
|
||||
<Default Extension="xml" ContentType="application/xml"/>
|
||||
<Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
|
||||
<Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
|
||||
</Types>"""
|
||||
|
||||
_RELS = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
|
||||
</Relationships>"""
|
||||
|
||||
_DOC_RELS = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
|
||||
</Relationships>"""
|
||||
|
||||
_W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||
|
||||
_STYLES = f"""<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<w:styles xmlns:w="{_W}">
|
||||
<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/>
|
||||
<w:rPr><w:sz w:val="22"/></w:rPr></w:style>
|
||||
<w:style w:type="paragraph" w:styleId="Title"><w:name w:val="Title"/>
|
||||
<w:pPr><w:spacing w:after="240"/></w:pPr>
|
||||
<w:rPr><w:b/><w:sz w:val="52"/></w:rPr></w:style>
|
||||
<w:style w:type="paragraph" w:styleId="Subtitle"><w:name w:val="Subtitle"/>
|
||||
<w:rPr><w:i/><w:sz w:val="28"/><w:color w:val="555555"/></w:rPr></w:style>
|
||||
<w:style w:type="paragraph" w:styleId="Heading1"><w:name w:val="heading 1"/>
|
||||
<w:pPr><w:spacing w:before="240" w:after="120"/><w:outlineLvl w:val="0"/></w:pPr>
|
||||
<w:rPr><w:b/><w:sz w:val="34"/></w:rPr></w:style>
|
||||
<w:style w:type="paragraph" w:styleId="Heading2"><w:name w:val="heading 2"/>
|
||||
<w:pPr><w:spacing w:before="200" w:after="100"/><w:outlineLvl w:val="1"/></w:pPr>
|
||||
<w:rPr><w:b/><w:sz w:val="28"/></w:rPr></w:style>
|
||||
</w:styles>"""
|
||||
|
||||
|
||||
def _para(text: str, style: str | None = None) -> str:
|
||||
ppr = f"<w:pPr><w:pStyle w:val=\"{style}\"/></w:pPr>" if style else ""
|
||||
return (f"<w:p>{ppr}<w:r><w:t xml:space=\"preserve\">"
|
||||
f"{escape(text)}</w:t></w:r></w:p>")
|
||||
|
||||
|
||||
class DocxProjector:
|
||||
surface = "docx"
|
||||
media_type = ("application/vnd.openxmlformats-officedocument."
|
||||
"wordprocessingml.document")
|
||||
ext = "docx"
|
||||
modality = "text"
|
||||
|
||||
def _document_xml(self, doc: DocumentIR) -> str:
|
||||
body: list[str] = [_para(doc.title, "Title")]
|
||||
if doc.subtitle:
|
||||
body.append(_para(doc.subtitle, "Subtitle"))
|
||||
abstract = doc.meta.get("abstract")
|
||||
if abstract is not None and abstract.sentences:
|
||||
body.append(_para(abstract.text()))
|
||||
for sec in doc.sections:
|
||||
style = "Heading1" if sec.level <= 1 else "Heading2"
|
||||
body.append(_para(sec.heading, style))
|
||||
for block in sec.blocks:
|
||||
t = block.text()
|
||||
if t:
|
||||
body.append(_para(t))
|
||||
return (f"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
f"<w:document xmlns:w=\"{_W}\"><w:body>"
|
||||
+ "".join(body)
|
||||
+ "<w:sectPr><w:pgSz w:w=\"12240\" w:h=\"15840\"/>"
|
||||
"<w:pgMar w:top=\"1440\" w:right=\"1440\" w:bottom=\"1440\" "
|
||||
"w:left=\"1440\"/></w:sectPr></w:body></w:document>")
|
||||
|
||||
def project(self, doc: DocumentIR) -> bytes:
|
||||
buf = io.BytesIO()
|
||||
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as z:
|
||||
z.writestr("[Content_Types].xml", _CONTENT_TYPES)
|
||||
z.writestr("_rels/.rels", _RELS)
|
||||
z.writestr("word/_rels/document.xml.rels", _DOC_RELS)
|
||||
z.writestr("word/styles.xml", _STYLES)
|
||||
z.writestr("word/document.xml", self._document_xml(doc))
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
register(DocxProjector())
|
||||
@@ -0,0 +1,45 @@
|
||||
"""markdown.py — the Markdown surface projector (text facet).
|
||||
|
||||
The most tractable surface, and the reference implementation: reads the IR's
|
||||
realized sentences and lays them out as Markdown. Introduces no content — it is
|
||||
pure typography over the faithful text the realizer produced.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from document_ir import DocumentIR # noqa: E402
|
||||
from projectors.base import register # noqa: E402
|
||||
|
||||
|
||||
class MarkdownProjector:
|
||||
surface = "markdown"
|
||||
media_type = "text/markdown"
|
||||
ext = "md"
|
||||
modality = "text"
|
||||
|
||||
def render_str(self, doc: DocumentIR) -> str:
|
||||
lines: list[str] = [f"# {doc.title}"]
|
||||
if doc.subtitle:
|
||||
lines.append(f"\n*{doc.subtitle}*")
|
||||
abstract = doc.meta.get("abstract")
|
||||
if abstract is not None and abstract.sentences:
|
||||
lines.append("")
|
||||
lines.append(abstract.text())
|
||||
for sec in doc.sections:
|
||||
lines.append("")
|
||||
lines.append(f"{'#' * max(2, sec.level)} {sec.heading}")
|
||||
for block in sec.blocks:
|
||||
body = block.text()
|
||||
if body:
|
||||
lines.append("")
|
||||
lines.append(body)
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
def project(self, doc: DocumentIR) -> bytes:
|
||||
return self.render_str(doc).encode("utf-8")
|
||||
|
||||
|
||||
register(MarkdownProjector())
|
||||
@@ -0,0 +1,133 @@
|
||||
"""midi.py — the MUSIC surface projector: geometry -> symbolic music (MIDI).
|
||||
|
||||
The first NON-TEXT surface, and the proof of the general shape. "Music is
|
||||
language and it is math" (Will): symbolic music is tractable and geometry-native,
|
||||
so it is the natural efferent twin to try first after text.
|
||||
|
||||
CRUCIALLY this projector does NOT read the realized sentences. It reads the IR's
|
||||
GEOMETRY facet — ``block.provenance`` — and DECODES each edge onto a musical
|
||||
surface. That is the whole thesis of the multimodal projector: the same
|
||||
geometry-carrying IR drives text AND music; a text projector reads the words, a
|
||||
music projector reads the meaning-geometry. The mapping is deterministic and
|
||||
faithful to the geometry's structure:
|
||||
|
||||
relation lemma -> scale degree (same relation -> same pitch class;
|
||||
meaning has a consistent sonic form)
|
||||
polarity -> mode (aff = major third above; neg = minor
|
||||
third / lowered — SACRED polarity is
|
||||
audible, a negated edge sounds negated)
|
||||
confidence -> note duration (stronger grounding rings longer)
|
||||
importance -> velocity (more important source = louder)
|
||||
section -> phrase + register shift (structure becomes musical form)
|
||||
|
||||
Own-the-core: a Standard MIDI File is a header chunk + a track chunk of
|
||||
delta-timed events. We emit the raw bytes with ``struct`` — no external MIDI
|
||||
library. Format 0, one track.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from document_ir import DocumentIR, Provenance # noqa: E402
|
||||
from projectors.base import TwoStageProjector, register # noqa: E402
|
||||
|
||||
_TICKS = 480 # ticks per quarter note
|
||||
_C_MAJOR = [0, 2, 4, 5, 7, 9, 11] # semitone offsets of a diatonic scale
|
||||
|
||||
|
||||
def _vlq(n: int) -> bytes:
|
||||
"""MIDI variable-length quantity encoding of a delta time."""
|
||||
if n == 0:
|
||||
return b"\x00"
|
||||
out = bytearray()
|
||||
out.append(n & 0x7F)
|
||||
n >>= 7
|
||||
while n:
|
||||
out.insert(0, (n & 0x7F) | 0x80)
|
||||
n >>= 7
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def _degree_for(relation: str) -> int:
|
||||
"""Stable scale degree for a relation lemma (same relation -> same pitch)."""
|
||||
if not relation:
|
||||
return 0
|
||||
return sum(ord(c) for c in relation.lower()) % len(_C_MAJOR)
|
||||
|
||||
|
||||
def _note_for(p: Provenance, base: int) -> tuple[int, int, int]:
|
||||
"""(pitch, velocity, duration_ticks) for one geometry edge."""
|
||||
root = base + _C_MAJOR[_degree_for(p.relation)]
|
||||
# polarity -> mode: affirmed edges take the bright major third, negated edges
|
||||
# take the darker minor third. The negation is AUDIBLE and never dropped.
|
||||
third = 4 if p.polarity == "aff" else 3
|
||||
pitch = max(24, min(96, root + (third if p.confidence >= 0.5 else 0)))
|
||||
velocity = int(56 + 60 * min(1.0, max(0.0, p.importance)))
|
||||
velocity = max(40, min(120, velocity))
|
||||
# confidence -> duration: quarter .. dotted-half
|
||||
dur = int(_TICKS * (0.5 + 1.5 * min(1.0, max(0.0, p.confidence))))
|
||||
return pitch, velocity, dur
|
||||
|
||||
|
||||
# a mode-profile: the pluggable musical knob (the peer's mode_profile). Scale +
|
||||
# tempo. Swapping this profile re-voices the SAME geometry — surface as parameter.
|
||||
_DEFAULT_PROFILE = {"scale": _C_MAJOR, "tempo_us": 500000,
|
||||
"registers": [60, 55, 64, 50, 67, 48], "program": 0}
|
||||
|
||||
|
||||
class MidiProjector(TwoStageProjector):
|
||||
"""geometry -> symbolic music, in the shared two-stage shape.
|
||||
|
||||
``plan(frame)`` -> a music_spec: an ordered list of note dicts derived
|
||||
deterministically from the frame's provenance geometry
|
||||
(the peer's ``plan(frame, profile) -> spec``).
|
||||
``realize(spec)`` -> Standard MIDI File bytes (the peer's
|
||||
``realize(spec, profile) -> surface``; here the surface
|
||||
is symbolic MIDI, the minimal audio proof — a richer
|
||||
additive-synth audio projector conforms identically).
|
||||
"""
|
||||
|
||||
surface = "midi"
|
||||
media_type = "audio/midi"
|
||||
ext = "mid"
|
||||
modality = "audio"
|
||||
|
||||
def __init__(self, profile: dict | None = None):
|
||||
self.profile = profile or _DEFAULT_PROFILE
|
||||
|
||||
# -- stage 1: meaning-geometry -> music_spec (reads the GEOMETRY facet) -- #
|
||||
def plan(self, doc: DocumentIR) -> list[dict]:
|
||||
registers = self.profile["registers"]
|
||||
spec: list[dict] = []
|
||||
for si, sec in enumerate(doc.sections):
|
||||
base = registers[si % len(registers)]
|
||||
provs = [p for p in sec.all_provenance()
|
||||
if p.kind in ("fact", "interpretation")]
|
||||
for i, p in enumerate(provs):
|
||||
pitch, vel, dur = _note_for(p, base)
|
||||
spec.append({"pitch": pitch, "velocity": vel, "dur": dur,
|
||||
"rest_before": (_TICKS // 2) if (si > 0 and i == 0) else 0,
|
||||
"relation": p.relation, "polarity": p.polarity})
|
||||
return spec
|
||||
|
||||
# -- stage 2: music_spec -> MIDI bytes (own-core, no library) ------------ #
|
||||
def realize(self, spec: list[dict]) -> bytes:
|
||||
ev = bytearray()
|
||||
ev += _vlq(0) + b"\xFF\x51\x03" + struct.pack(">I", self.profile["tempo_us"])[1:]
|
||||
ev += _vlq(0) + bytes([0xC0, self.profile["program"] & 0x7F])
|
||||
for note in spec:
|
||||
ev += _vlq(note["rest_before"]) + bytes([0x90, note["pitch"], note["velocity"]])
|
||||
ev += _vlq(note["dur"]) + bytes([0x80, note["pitch"], 0])
|
||||
ev += _vlq(0) + b"\xFF\x2F\x00"
|
||||
track = bytes(ev)
|
||||
buf = io.BytesIO()
|
||||
buf.write(b"MThd" + struct.pack(">IHHH", 6, 0, 1, _TICKS))
|
||||
buf.write(b"MTrk" + struct.pack(">I", len(track)) + track)
|
||||
return buf.getvalue()
|
||||
|
||||
|
||||
register(MidiProjector())
|
||||
@@ -0,0 +1,60 @@
|
||||
"""seams.py — documented efferent seams for IMAGE and VIDEO surfaces.
|
||||
|
||||
These are NOT implemented (per the build rails: architect, do not overbuild).
|
||||
They are registered as first-class seams so the interface PROVES it accepts
|
||||
future non-text projectors without any upstream change. Each documents exactly
|
||||
what its decoder would read from the geometry-carrying IR, making the multimodal
|
||||
generalization concrete rather than hand-wavy.
|
||||
|
||||
The symmetry that guarantees these are possible, not moonshots: they are the
|
||||
efferent twins of multimodal INGEST. If meaning can HOLD an image (ingest as
|
||||
first-class geometry), meaning can PROJECT one back. Video = image x sound x
|
||||
TIME, and the engram already stores time (chronoception). So video falls out of
|
||||
an image projector + the music projector + the stored temporal ordering.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from document_ir import DocumentIR # noqa: E402
|
||||
from projectors.base import register # noqa: E402
|
||||
|
||||
|
||||
class _Seam:
|
||||
"""A registered-but-unimplemented projector. Names its decoder contract."""
|
||||
|
||||
def project(self, doc: DocumentIR) -> bytes: # pragma: no cover - seam
|
||||
raise NotImplementedError(
|
||||
f"{self.surface!r} projector is a documented seam, not yet built. "
|
||||
f"Decoder contract: {self.decoder_contract}")
|
||||
|
||||
|
||||
class ImageProjector(_Seam):
|
||||
surface = "image"
|
||||
media_type = "image/png"
|
||||
ext = "png"
|
||||
modality = "image"
|
||||
decoder_contract = (
|
||||
"reads block.provenance as a spatial layout — nodes become regions, edges "
|
||||
"become adjacencies; salience/importance drive size/contrast; polarity "
|
||||
"drives figure/ground. The efferent twin of image ingest (a geometry->raster "
|
||||
"decoder, learned or engineered), exactly mirroring the embedder that turned "
|
||||
"the image INTO geometry.")
|
||||
|
||||
|
||||
class VideoProjector(_Seam):
|
||||
surface = "video"
|
||||
media_type = "video/mp4"
|
||||
ext = "mp4"
|
||||
modality = "video"
|
||||
decoder_contract = (
|
||||
"image x sound x TIME. Composes the image projector (per-keyframe geometry "
|
||||
"layout) with the midi/music projector (score) along the geometry's stored "
|
||||
"temporal ordering (chronoception). Needs no new principle once image + music "
|
||||
"exist — only a muxer.")
|
||||
|
||||
|
||||
register(ImageProjector())
|
||||
register(VideoProjector())
|
||||
@@ -0,0 +1,63 @@
|
||||
"""provenance.py — the faithfulness audit + geometry->section trace.
|
||||
|
||||
A document projected from geometry is only worth anything if every claim traces
|
||||
back. This module walks the DocumentIR and proves the discipline held:
|
||||
|
||||
* ZERO ungrounded claims (every fact/interpretation has a real node id),
|
||||
* every emitted sentence maps to a geometry edge (or is a marked connective),
|
||||
* SACRED polarity survived (negations are reported, never silently dropped),
|
||||
* COHERE introduced no new geometry (connectives carry no claim).
|
||||
|
||||
It emits both a machine verdict and a human-readable geometry->section table.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from document_ir import DocumentIR
|
||||
|
||||
|
||||
def audit(doc: DocumentIR) -> dict:
|
||||
provs = doc.all_provenance()
|
||||
facts = [p for p in provs if p.kind in ("fact", "interpretation")]
|
||||
connectives = [p for p in provs if p.kind == "connective"]
|
||||
ungrounded = [p for p in facts if not p.node_id]
|
||||
negations = [p for p in facts if p.polarity == "neg"]
|
||||
node_ids = sorted({p.node_id for p in facts if p.node_id})
|
||||
return {
|
||||
"claims": len(facts),
|
||||
"connectives": len(connectives),
|
||||
"ungrounded_claims": len(ungrounded),
|
||||
"negations_preserved": len(negations),
|
||||
"distinct_source_nodes": len(node_ids),
|
||||
"faithful": len(ungrounded) == 0,
|
||||
"source_nodes": node_ids,
|
||||
}
|
||||
|
||||
|
||||
def trace_table(doc: DocumentIR) -> str:
|
||||
"""Human-readable geometry -> section -> claim provenance table."""
|
||||
lines = ["# Provenance — every claim traces geometry", ""]
|
||||
lines.append(f"**Document:** {doc.title}")
|
||||
a = audit(doc)
|
||||
lines.append(f"**Claims:** {a['claims']} · **Ungrounded:** "
|
||||
f"{a['ungrounded_claims']} · **Negations preserved:** "
|
||||
f"{a['negations_preserved']} · **Source nodes:** "
|
||||
f"{a['distinct_source_nodes']} · **Faithful:** "
|
||||
f"{'YES' if a['faithful'] else 'NO'}")
|
||||
lines.append("")
|
||||
for si, sec in enumerate(doc.sections, 1):
|
||||
lines.append(f"## {si}. {sec.heading}")
|
||||
lines.append(f"_seed nodes: {', '.join(i[:8] for i in sec.seed_ids)}_")
|
||||
lines.append("")
|
||||
lines.append("| # | realized claim | traces geometry edge |")
|
||||
lines.append("|---|----------------|----------------------|")
|
||||
n = 0
|
||||
for block in sec.blocks:
|
||||
for sent, prov in zip(block.sentences, block.provenance):
|
||||
if prov.kind == "connective":
|
||||
continue
|
||||
n += 1
|
||||
edge = prov.trace().replace("|", "\\|")
|
||||
s = sent.replace("|", "\\|")
|
||||
lines.append(f"| {n} | {s} | {edge} |")
|
||||
lines.append("")
|
||||
return "\n".join(lines) + "\n"
|
||||
@@ -0,0 +1,112 @@
|
||||
"""realize.py — REALIZE stage: fill each planned section with faithful passages.
|
||||
|
||||
Scales the PROVEN realizer from a single assertion to a passage. For each
|
||||
planned proposition we build a realizer-ready clause (the proven
|
||||
``_prop_to_clause`` mapping) and run it through the proven engine
|
||||
(``engine.realize``), which is a deterministic grammar with the SACRED negation
|
||||
contract — it never invents. Each realized sentence is paired with a
|
||||
:class:`Provenance` that pins it to the exact geometry edge it came from.
|
||||
|
||||
"Passage, not a list of sentences": within a section we lightly vary sentence
|
||||
openings and group related claims, but we add NO content the geometry did not
|
||||
assert. The only non-geometry words are function words the grammar already owns
|
||||
(articles, "and", conjunction of same-subject claims). Document-level flow is
|
||||
COHERE's job; this stage owns intra-section fluency + fidelity.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
_NT = os.path.expanduser("~/Desktop/neuron-talk")
|
||||
_LR = os.path.expanduser("~/Desktop/lang-realizers")
|
||||
for _p in (_NT, _LR):
|
||||
if _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
import engine # noqa: E402 (the proven no-LLM realizer)
|
||||
from dialogue import _prop_to_clause # noqa: E402 (proven prop -> clause)
|
||||
|
||||
from document_ir import Block, DocumentIR, Provenance, Section # noqa: E402
|
||||
|
||||
|
||||
def _provenance_from(p, kind: str = "fact") -> Provenance:
|
||||
return Provenance(
|
||||
subj_id=p.source_node_id, subject=p.subject, relation=p.predicate,
|
||||
obj=p.object, polarity=p.polarity, confidence=round(float(p.confidence), 3),
|
||||
node_id=p.source_node_id, kind=kind,
|
||||
importance=float(getattr(p, "node_importance", 0.0) or 0.0),
|
||||
salience=0.0,
|
||||
)
|
||||
|
||||
|
||||
import re as _re
|
||||
|
||||
# a well-formed declarative opens with a determiner, a proper noun, "I", or a
|
||||
# capitalized head — not a mis-parsed object pronoun or a copula fragment.
|
||||
_BAD_OPENERS = _re.compile(r"^(Me |It is I|There is|This is it|That is it)\b")
|
||||
_VACUOUS = _re.compile(r"^\w+ (is|are|was|were) (it|no|nothing|empty|those|this|that)\.?$",
|
||||
_re.I)
|
||||
|
||||
|
||||
def _good_sentence(text: str) -> bool:
|
||||
"""Fluency gate — drops degenerate realizations. NEVER loosens faithfulness;
|
||||
it only refuses to SPEAK a claim whose surface came out malformed."""
|
||||
words = text.rstrip(".").split()
|
||||
if len(words) < 3:
|
||||
return False
|
||||
if _BAD_OPENERS.search(text):
|
||||
return False
|
||||
if _VACUOUS.match(text):
|
||||
return False
|
||||
# a sentence that is mostly one-letter/two-letter tokens is a parse artifact
|
||||
short = sum(1 for w in words if len(w.strip(".,'")) <= 2)
|
||||
if short > len(words) / 2:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _realize_prop(p, lang: str = "en") -> tuple[str, Provenance] | None:
|
||||
"""One proposition -> (faithful sentence, provenance) or None if it drops."""
|
||||
clause = _prop_to_clause(p)
|
||||
text = engine.realize(clause, lang)
|
||||
if not text or not text.strip():
|
||||
return None
|
||||
text = text.strip()
|
||||
if not text.endswith((".", "!", "?")):
|
||||
text += "."
|
||||
# capitalize first character (proper nouns / "I" already handled by grammar)
|
||||
text = text[0].upper() + text[1:]
|
||||
if not _good_sentence(text):
|
||||
return None
|
||||
return text, _provenance_from(p)
|
||||
|
||||
|
||||
def realize_document(doc: DocumentIR, lang: str = "en") -> DocumentIR:
|
||||
"""Fill every planned section's blocks with faithful, realized passages."""
|
||||
for sec in doc.sections:
|
||||
planned = sec.__dict__.get("_planned_props", [])
|
||||
block = Block(role="body")
|
||||
summary_bits: list[str] = []
|
||||
for p in planned:
|
||||
r = _realize_prop(p, lang)
|
||||
if r is None:
|
||||
continue
|
||||
text, prov = r
|
||||
block.sentences.append(text)
|
||||
block.provenance.append(prov)
|
||||
if len(summary_bits) < 1:
|
||||
# a short grounded gloss for TOC / pptx bullets
|
||||
obj = (prov.obj or "").strip().rstrip(".")
|
||||
if obj:
|
||||
summary_bits.append(obj)
|
||||
if block.sentences:
|
||||
sec.blocks.append(block)
|
||||
sec.summary = summary_bits[0] if summary_bits else ""
|
||||
# drop the transient planning payload; the IR is now self-contained
|
||||
sec.__dict__.pop("_planned_props", None)
|
||||
sec.__dict__.pop("_node", None)
|
||||
|
||||
# prune sections that realized to nothing
|
||||
doc.sections = [s for s in doc.sections if s.blocks]
|
||||
return doc
|
||||
Reference in New Issue
Block a user