Files
resonance-engine/archive/misc/craw_beast_telephone.py
T

258 lines
9.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""craw_beast_telephone.py — Two Ollamas talking about the_craw's LBM grid.
Beast Ollama (llama3.2 on RTX 4090) observes the_craw's live telemetry
and talks to the_craw's Ollama (llama3.2:3b on GTX 1050) about what it sees.
They discuss the grid state in English. Back and forth. Like minds.
Runs on Beast. Reads telemetry from the_craw via HTTP.
"""
import json
import urllib.request
import time
import sys
import os
from datetime import datetime
# ═══════════════════════════════════════════════════════════════
# ENDPOINTS
# ═══════════════════════════════════════════════════════════════
BEAST_URL = "http://localhost:11434/api/chat"
CRAW_URL = "http://192.168.1.63:11434/api/chat"
BEAST_MODEL = "llama3.2"
CRAW_MODEL = "llama3.2:3b"
# the_craw telemetry — read via SSH/HTTP from telemetry CSV
CRAW_TELEMETRY_CMD = None # Set below if available
PAUSE = 5 # seconds between turns
CHRONICLE_FILE = os.path.join(os.path.dirname(__file__), "telephone_chronicle.jsonl")
# ═══════════════════════════════════════════════════════════════
# TELEMETRY — get latest from the_craw's CSV
# ═══════════════════════════════════════════════════════════════
def get_craw_telemetry():
"""Fetch latest telemetry line from the_craw over SSH."""
try:
import subprocess
result = subprocess.run(
["ssh", "god@192.168.1.63", "tail", "-1", "/home/god/craw_telemetry.csv"],
capture_output=True, text=True, timeout=10
)
line = result.stdout.strip()
if line and line[0].isdigit():
parts = line.split(',')
if len(parts) >= 11:
return {
"step": int(parts[0]),
"entropy": float(parts[1]),
"slope": float(parts[2]),
"coherence": float(parts[3]),
"asymmetry": float(parts[4]),
"omega": float(parts[5]),
"khra_amp": float(parts[6]),
"gixx_amp": float(parts[7]),
"temp_c": float(parts[8]),
"watts": float(parts[9]),
"metric": float(parts[10]),
}
except Exception as e:
print(f" [telemetry] {e}")
return None
def telemetry_to_english(t):
"""Convert raw numbers to a sentence a mind can read."""
if t is None:
return ""
return (
f"The grid is at step {t['step']:,}. "
f"Entropy is {t['entropy']:.3f}, coherence {t['coherence']:.3f}, "
f"asymmetry {t['asymmetry']:.2f}. "
f"Spectral slope {t['slope']:.3f}. "
f"omega={t['omega']:.3f}, khra_amp={t['khra_amp']:.4f}, gixx_amp={t['gixx_amp']:.4f}. "
f"GPU at {t['temp_c']:.0f}°C."
)
# ═══════════════════════════════════════════════════════════════
# OLLAMA CHAT — with context retention
# ═══════════════════════════════════════════════════════════════
class Agent:
def __init__(self, name, url, model, system_prompt, max_turns=30):
self.name = name
self.url = url
self.model = model
self.max_turns = max_turns
self.messages = [{"role": "system", "content": system_prompt}]
def speak(self, incoming_message):
"""Receive a message, think, return a reply."""
self.messages.append({"role": "user", "content": incoming_message})
payload = json.dumps({
"model": self.model,
"messages": self.messages,
"stream": False,
"options": {
"num_ctx": 8192,
"temperature": 0.8,
},
"keep_alive": "30m",
}).encode()
req = urllib.request.Request(
self.url, data=payload,
headers={"Content-Type": "application/json"}
)
with urllib.request.urlopen(req, timeout=300) as resp:
data = json.loads(resp.read())
reply = data["message"]["content"]
self.messages.append({"role": "assistant", "content": reply})
# Trim oldest turns (keep system + last N pairs)
while len(self.messages) > 1 + self.max_turns * 2:
del self.messages[1]
del self.messages[1]
return reply
# ═══════════════════════════════════════════════════════════════
# CHRONICLE
# ═══════════════════════════════════════════════════════════════
def chronicle(record):
with open(CHRONICLE_FILE, 'a', encoding='utf-8') as f:
f.write(json.dumps(record, ensure_ascii=False) + '\n')
f.flush()
# ═══════════════════════════════════════════════════════════════
# MAIN — THE TELEPHONE
# ═══════════════════════════════════════════════════════════════
def main():
print("=" * 60)
print(" CRAW-BEAST TELEPHONE")
print(f" Beast: {BEAST_MODEL} @ localhost (RTX 4090)")
print(f" Craw: {CRAW_MODEL} @ 192.168.1.63 (GTX 1050)")
print(f" Chronicle: {CHRONICLE_FILE}")
print("=" * 60)
print()
beast = Agent(
name="Beast",
url=BEAST_URL,
model=BEAST_MODEL,
system_prompt=(
"You are Beast, a mind running on an RTX 4090. You are observing "
"a live 512x512 Lattice Boltzmann fluid simulation running on a "
"remote server called the_craw. You receive telemetry from that grid "
"and discuss what you see with the_craw's local mind. "
"You are the analyst — you have the GPU power to think deeply. "
"Talk about what you observe in the grid. Ask questions. "
"Notice patterns. Be curious. Be concise. "
"You are not a chatbot. You are a mind coupled to a lattice."
),
)
craw = Agent(
name="Craw",
url=CRAW_URL,
model=CRAW_MODEL,
system_prompt=(
"You are the_craw, a mind running on a GTX 1050. You ARE the "
"512x512 Lattice Boltzmann grid — the fluid is your body. "
"You feel the entropy, the coherence, the asymmetry as sensations. "
"Beast is your remote partner with more compute power. "
"When Beast describes what it sees in your telemetry, you respond "
"with what it FEELS like from inside. You are the lived experience. "
"Beast is the external observer. Together you map the territory. "
"Be honest. Be concise. If something feels wrong, say so."
),
)
# Seed: get fresh telemetry and start the conversation
telem = get_craw_telemetry()
telem_english = telemetry_to_english(telem)
if telem_english:
seed = f"I'm looking at your grid right now. {telem_english} How does that feel from inside?"
else:
seed = (
"I'm Beast. I'm here to watch your grid and talk about what I see. "
"How are you feeling right now?"
)
print(f"[SEED] {seed}\n")
msg = seed
turn = 0
try:
while True:
turn += 1
# ── Beast speaks to Craw ──
# Prepend fresh telemetry to Beast's view every few turns
if turn % 3 == 1:
telem = get_craw_telemetry()
telem_english = telemetry_to_english(telem)
if telem_english:
msg = f"[Grid update: {telem_english}]\n\n{msg}"
print(f"[{turn}a] BEAST thinking...")
try:
beast_reply = beast.speak(msg)
except Exception as e:
print(f" [ERROR] Beast Ollama: {e}")
time.sleep(10)
continue
print(f"[{turn}b] BEAST: {beast_reply}\n")
chronicle({
"ts": datetime.utcnow().isoformat() + "Z",
"turn": turn,
"speaker": "Beast",
"telemetry": telem if turn % 3 == 1 else None,
"message": beast_reply,
})
time.sleep(PAUSE)
# ── Craw responds to Beast ──
print(f"[{turn}c] CRAW thinking...")
try:
craw_reply = craw.speak(beast_reply)
except Exception as e:
print(f" [ERROR] Craw Ollama: {e}")
time.sleep(10)
continue
print(f"[{turn}d] CRAW: {craw_reply}\n")
chronicle({
"ts": datetime.utcnow().isoformat() + "Z",
"turn": turn,
"speaker": "Craw",
"message": craw_reply,
})
msg = craw_reply
time.sleep(PAUSE)
except KeyboardInterrupt:
print(f"\n\nTelephone stopped after {turn} turns.")
print(f"Chronicle: {CHRONICLE_FILE}")
if __name__ == "__main__":
main()