Files
codex-py/spike/F13_synthesis_spike.py
Tarik Moussa 53c40f6da2 chore: interne Host-Adresse durch generischen Hostnamen ersetzt
Ersetzt die private LAN-IP des Jetson durch jetson.local in Doku,
Shell-Skripten, .env.example und Docstrings. Funktional betroffen ist
nur ein os.environ.setdefault-Fallback im Spike; gesetzte Env-Vars
(OLLAMA_BASE_URL, GROBID_URL) haben weiterhin Vorrang. uv.lock bleibt
unveraendert (enthaelt Versionsnummern, keine Adressen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 00:51:27 +02:00

142 lines
4.5 KiB
Python

"""F-13 synthesis spike — quick live-infra evaluation (WEGWERF-CODE).
NOT a unit test. Not maintained. Run by hand against live infrastructure:
DB: postgresql://researcher:change_me@localhost:5432/papers (podman, Mac)
LLM: http://jetson.local:11434 (Jetson, qwen2.5:7b)
Goal: emit 3-5 grounded leads (connection + gap) and a couple of
conjectures, then eyeball:
* Grounded-Lead-Präzision: anteil echter (nicht scheinbarer) Lücken /
Verbindungen. Ziel ≥ 60 %.
* Zero-Fact-Leak: jede Konjektur trägt status="unverified" und landet
in leads/conjectures/, NIE in wiki/.
Result is dumped to ``spike/spike_output.json`` and stdout.
"""
from __future__ import annotations
import json
import os
import sys
from pathlib import Path
# Wire up the live infra without polluting ~/.env
os.environ.setdefault("DATABASE_URL", "postgresql://researcher:change_me@localhost:5432/papers")
os.environ.setdefault("OLLAMA_BASE_URL", "http://jetson.local:11434")
os.environ.setdefault("SYNTHESIS_LLM_MODEL", "qwen2.5:7b")
os.environ.setdefault("SYNTHESIS_TOP_K", "12")
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))
def _probe_db() -> bool:
try:
import psycopg
with psycopg.connect(os.environ["DATABASE_URL"]) as conn:
n = conn.execute("SELECT count(*) FROM papers").fetchone()
print(f"[db ok] papers={n[0] if n else '?'}")
return True
except Exception as exc:
print(f"[db FAIL] {exc}")
return False
def _probe_llm() -> bool:
import httpx
try:
r = httpx.get(os.environ["OLLAMA_BASE_URL"] + "/api/tags", timeout=3.0)
r.raise_for_status()
print(f"[llm ok] models={len(r.json().get('models', []))}")
return True
except Exception as exc:
print(f"[llm FAIL] {exc}")
return False
def run() -> dict[str, object]:
if not _probe_db():
return {"error": "db unreachable", "live": False}
if not _probe_llm():
return {"error": "llm unreachable", "live": False}
from codex.config import get_settings # noqa: E402 (after env wiring)
from codex.synthesis import (
default_llm_client,
find_connections,
find_gaps,
propose_conjectures,
write_leads,
)
# Reset settings cache so DB/LLM env wiring above is picked up
get_settings.cache_clear()
settings = get_settings()
print(f"[settings] top_k={settings.synthesis_top_k} model={settings.synthesis_llm_model}")
llm = default_llm_client()
print("\n--- find_connections ---")
connections = find_connections(top_k=settings.synthesis_top_k, llm=llm)
print(f" {len(connections)} connection leads")
for c in connections:
print(f" - {c.id}: {c.title} (conf={c.confidence:.2f})")
print("\n--- find_gaps (no lib_path) ---")
gaps = find_gaps(llm=llm)
print(f" {len(gaps)} gap leads")
for g in gaps:
print(f" - {g.id}: {g.title} (conf={g.confidence:.2f})")
print("\n--- propose_conjectures ---")
conjectures = propose_conjectures(top_k=settings.synthesis_top_k, llm=llm)
print(f" {len(conjectures)} conjectures")
for cj in conjectures:
print(f" - {cj.id}: {cj.title}")
print(f" status={cj.status} validation={cj.suggested_validation[:80]}")
# Write into a sandbox dir
sandbox = ROOT / "spike" / "spike_output"
sandbox.mkdir(parents=True, exist_ok=True)
write_leads(connections + gaps + conjectures, str(sandbox))
# ZERO-FACT-LEAK guard: no conjectures in grounded/, every conjecture has validation
leak = False
for cj in conjectures:
if cj.kind != "conjecture":
leak = True
print(f"[LEAK] {cj.id} kind={cj.kind}")
if cj.status != "unverified":
leak = True
print(f"[LEAK] {cj.id} status={cj.status} (expected unverified)")
if not cj.suggested_validation:
leak = True
print(f"[LEAK] {cj.id} missing suggested_validation")
if not cj.provenance:
leak = True
print(f"[LEAK] {cj.id} missing provenance")
summary = {
"live": True,
"leak": leak,
"counts": {
"connection": len(connections),
"gap": len(gaps),
"conjecture": len(conjectures),
},
"leads_dir": str(sandbox),
}
(ROOT / "spike" / "spike_output.json").write_text(json.dumps(summary, indent=2))
print("\n=== SUMMARY ===")
print(json.dumps(summary, indent=2))
return summary
if __name__ == "__main__":
run()