Thinking

Thinking

Liebe Leser, dieser Artikel handelt von nichts Bestimmtem – er ist eine Reflexion über das Thema einer wirklich denkenden Maschine, die nicht auf Statistiken wie LLM & Co. basiert. Meiner bescheidenen Meinung nach gilt: Ich würde meinen LLM-Patienten nicht behandeln wollen und auch kein Flugzeug mit einem permanenten LLM-Roboter fliegen lassen. Und was ist mit RAG? Ja, es ist definitiv ein Erfolg! Aber wenn die Wissensbasis im Wesentlichen ein statistischer Graph ist, ändert das im Großen und Ganzen nichts. Ich will damit aber keinesfalls sagen, dass LLMs schlecht sind! Sie sind eine hervorragende Ein- und Ausgabeschnittstelle für eine Wissensbasis.

1. Gedanken laut aussprechen

Der Bau einer solchen Maschine führt uns zurück zu den Wurzeln der symbolischen KI, kognitiven Architekturen (wie ACT-R oder SOAR) und den Arbeiten von John McCarthy zur Metaprogrammierung in Lisp, wo Code und Daten buchstäblich dasselbe sind (Homoikonizität).

Wenn ein LLM eine gigantische statistische Approximation ist (die das nächste Token anhand der Gewichte in der Matrix probabilistisch errät), dann funktioniert eine „denkende“ Maschine, die auf TST (Ternärer Suchbaum) und Lisp basiert, als ein lebendiger, dynamischer Graph von Bedeutungen, der sich ständig im laufenden Betrieb selbst umstrukturiert.

2. Lisp als Substrat: Code gleich Daten (Homoikonizität)

In Lisp ist jede Datenstruktur (Liste, Baum) ein gültiger Ausdruck (S-Ausdruck), der sofort ausgeführt (eval) oder geändert (setcar, rplacd) werden kann.

  • Im Gegensatz zu LLMs, wo die Gewichte nach dem Training „eingefroren“ werden, ist hier der Programmspeicher ein ausführbarer Baum.
  • Wir speichern nicht nur Fakten in Speicherzellen, sondern auch Rechenwege. Wissen wird als verschachtelte Lisp-Listen repräsentiert, die die Knoten unseres ternären Baums bilden.

3. TST (Ternärer Suchbaum) als „Gedankenstruktur“

Anstelle einer flachen Datenbank oder eines Vektorraums organisieren wir den Speicher als dynamischen ternären Suchbaum, bei dem die Verzweigung in drei Richtungen erfolgt:

  • Links (<) / Rechts (>): Alternative Kontexte, Assoziationen oder Synonyme eines Konzepts.
  • Mitte (=): Vertiefung der Struktur (Detaillierung des Konzepts, Übergang zu einem Unterausdruck oder einer Nebenbedeutung).

Jeder TST-Knoten speichert nicht nur einen Buchstaben oder ein Symbol, sondern einen Lisp-Ausdruck (Lambda oder Atom).

4. Kontinuierliche Bewegung und „Bewertung“ (Bewertung & Umstrukturierung)

Die Maschine „denkt“ nicht durch Matrixmultiplikation von Token, sondern durch kontinuierliches Wandern und Verändern der TST-Struktur basierend auf Feedback:

  • Walker: Der Cursor (Gedankenzeiger) bewegt sich kontinuierlich durch die TST-Knoten. In jedem Schritt bewertet er den aktuellen Knoten mithilfe einer Nutzenfunktion (nennen wir sie heuristischen Wert oder epistemischen Wert).
  • Dynamische Umstrukturierung: Ist die Bewertung eines Knotens hoch (das Konzept ist bestätigt, die Logik funktioniert, die korrekte Verbindung hergestellt), verstärkt die Maschine diesen Pfad – beispielsweise durch Verschieben des Knotens näher an die Wurzel oder durch Verstärken der Verbindungen (analog zur Neuroplastizität, jedoch auf der Ebene von Lisp-Zeigern). Ist die Bewertung niedrig, verschwindet der Zweig (wird aus dem Baum entfernt) oder wird umgeleitet.
  • Selbstmodifikation: Das Programm liest seinen eigenen Code (TST-Struktur), schreibt ihn in Echtzeit um und führt die modifizierten Strukturen aus.

Architekturskizze in Common Lisp / Scheme

Konzeptionell ähnelt dies einem sich selbst modifizierenden Graphen, bei dem die Traversierung eines Baums mit der Berechnung von Bedeutungen kombiniert wird:


sudo apt update && sudo apt install sbcl -y
                

;; Definition der TST-Knotenstruktur (Trinity Meaning Tree).
(defstruct tst-node
  char          ; Konzeptsymbol
  left          ; Alternative (<)
  mid           ; Ausführlicher / Ausführbarer Lisp-Code (=)
  right         ; Alternative (>)
  (score 1.0))  ; Dynamische Nutzenbewertung

;; Die „Denkfunktion“: Baumdurchlauf, Codeauswertung und Ausführung zur Laufzeit
(defun think (node stream)
  (if (null node)
      '(:dead-end)
    (let ((current-char (car stream)))
      (cond
        ;; Ist das Symbol kleiner als der aktuelle Knoten, gehe nach links.
        ((and current-char (char< current-char (tst-node-char node)))
         (think (tst-node-left node) stream))

        ;; Wenn es größer ist, gehen wir nach rechts.
        ((and current-char (char> current-char (tst-node-char node)))
         (think (tst-node-right node) stream))

        ;; Match (=): Tauche ein und führe den Knotencode aus.
        (t
         (format t "[Think] Ich habe einen Knoten gefunden: ~A | Lisp-Code ausführen...~%" (tst-node-char node))
         ;; Dynamische Auswertung von Code, der direkt in einer Datenstruktur gespeichert ist
         (let ((result (eval (tst-node-mid node))))
           ;; Dynamische Anpassung der Knotengewichtung (Punktzahl) in Echtzeit
           (setf (tst-node-score node) (+ (tst-node-score node) 0.1))
           (format t "[Think] Die Bewertung des Knotens '~A' wurde auf ~A erhöht.~%"
                   (tst-node-char node) (tst-node-score node))
           result))))))

;; --- Initialisierung des minimalen „Speichers“ der Maschine ---
;; Wir erstellen einen Knoten 'A', in den der ausführbare Lisp-Code eingebettet ist.
(defparameter *root*
  (make-tst-node
   :char #\A
   :mid '(+ 40 2))) ; Daten entsprechen Code: Das Ergebnis der Berechnung ist 42.

;; --- Den Test ausführen ---
(format t "--- Start der ternären Lisp-Maschine ---~%~%")
(print (think *root* "A"))
(format t "~%Fertig!")

sbcl --script mind.lisp
                

--- Start der ternären Lisp-Maschine ---

[Think] Ich habe einen Knoten gefunden: A | Lisp-Code wird ausgeführt...
[Think] Die Bewertung des Knotens „A“ wurde auf 1.1 erhöht.

42
Fertig!
                

Was ist dabei der Trick?

  • Keine Kompilation durch neuronale Netze: Die Maschine interpretiert das Symbol #\A, findet es im TST und führt den Codeabschnitt '(+ 40 2) via eval sofort aus.
  • Selbstoptimierung im laufenden Betrieb: Das Score-Feld wurde direkt im Prozessspeicher ohne Gradientenabstieg geändert. Hätte dieser Knoten einen Fehler ausgelöst, hätte der Code in tst-node-mid im laufenden Betrieb in einen anderen Logikzweig umschreiben können (Graph-Neuverknüpfung).

Worin besteht der grundlegende Unterschied zum LLM?

  • Determinismus + Emergenz: Die Inferenzlogik ist vollständig transparent (es handelt sich um symbolische Graphen und Lisp-Code), aber das Verhalten des Systems entwickelt sich dynamisch aufgrund von Änderungen in der Baumtopologie.
  • Echtes kontinuierliches Lernen: Es müssen keine Gradienten auf einer GPU feinabgestimmt oder neu berechnet werden. Die Maschine ändert den TST-Knotenzeiger direkt im RAM – und „denkt“ dadurch anders.
  • Von Halluzinationen zur Logik: Anstatt das nächste Wort probabilistisch zu erraten, arbeitet das System mit Anwendbarkeitsgrenzen und symbolischen Regeln, die es selbst auf der Grundlage von TST-Bewertungen rekonstruiert.

5. Sprechende Maschinen in Lisp und TST: Semantische Geister

Anstelle einer flachen Datenbanktabelle erstellen wir einen dynamischen Klassifikationsbaum, in dem jeder Knoten nicht nur ein Zeichen, sondern auch ein Merkmal und einen vorgefertigten Lisp-Ausdruck zur Ausgabe einer Lösung speichert.


;; Struktur eines dynamischen TST-Knotens (Ternärer Konzeptbaum).
(defstruct tst-node
  char        ; Symbol für die Schnellnavigation nach Titel
  name        ; Konzeptname (z. B. „Karotte“)
  left        ; Alternative (<)
  mid         ; Bedeutung / Eigenschaften / Ausführbarer Code (=)
  right       ; Alternative (>)
  (score 1.0)) ; Dynamische Bewertung (wie erfolgreich die Regel ist)

;; Die Funktion des „Denkens“ und der Klassifizierung
(defun evaluate-vegetable (node query-char properties)
  (if (null node)
      '(:unknown-concept "Mir ist kein solches Objekt in der Speicherstruktur bekannt.")
    (let ((node-char (tst-node-char node)))
      (cond
        ((char< query-char node-char)
         (evaluate-vegetable (tst-node-left node) query-char properties))

        ((char> query-char node-char)
         (evaluate-vegetable (tst-node-right node) query-char properties))

        (t
         ;; Knoten gefunden! Werte die eingehenden Eigenschaften mithilfe von Lisp-Code im Knoten aus.
         (format t "[Cognition] Konzept: ~A | Überprüfung der Eigenschaften: ~A~%" (tst-node-name node) properties)
         (let ((result (funcall (tst-node-mid node) properties)))
           ;; Selbstmodifikation: Wenn die Logik funktioniert, erhöhen wir das Gewicht des Knotens.
           (setf (tst-node-score node) (+ (tst-node-score node) 0.2))
           (format t "[Plasticity] Knotengewicht '~A' wuchs zu ~A~%" (tst-node-name node) (tst-node-score node))
           result))))))

;; --- Aufbau eines dynamischen Speichers (Wissensbasis) ---

;; 1. Karotte (Beispiel)
(defparameter *node-carrot*
  (make-tst-node
   :char #\K ; von „Karotte“
   :name "Morkov"
   :mid (lambda (props)
          (let ((taste (getf props :taste))
                (edible (getf props :edible)))
            (if (and (eq taste :sweet) edible)
                "Dies ist ein gesundes Wurzelgemüse: süß und essbar!"
                "Geschmacksklassifizierungsfehler.")))))

;; 2. Wolfsbeere (oder ein herkömmlicher bitterer, ungenießbarer Gegenstand)
(defparameter *node-poison*
  (make-tst-node
   :char #\W ; von „Wolfsbeeren“
   :name "Die Beere ist ungenießbar."
   :mid (lambda (props)
          (let ((taste (getf props :taste))
                (edible (getf props :edible)))
            (if (and (eq taste :bitter) (not edible))
                "Vorsicht! Bittere und ungenießbare Substanzen sind Gift!"
                "Widerspruch in den Eigenschaften.")))))

;; Verknüpfung von Knoten im TST-Baum um das Wurzelkonzept
(setf (tst-node-left *node-carrot*) *node-poison*)

;; --- Testen eines „Denksystems“ ---

(format t "--- Test 1: Abfragen von Karotteneigenschaften ---~%")
(let ((properties '(:taste :sweet :edible t)))
  (print (evaluate-vegetable *node-carrot* #\K properties)))

(format t "~%--- Test 2: Abfragen der Eigenschaften eines gefährlichen Objekts ---~%")
(let ((properties '(:taste :bitter :edible nil)))
  (print (evaluate-vegetable *node-carrot* #\W properties)))

sbcl --script vegetables_mind.lisp
                

Was geschieht auf der logischen Ebene:

  • Code und Daten werden zusammengeführt: Das Feld :mid enthält eine anonyme Funktion (Lambda), die Eigenschaftsparameter akzeptiert (:taste :sweet :edible t).
  • Dynamische Anpassung: Bei jedem erfolgreichen Maschinenaufruf wird der Parameter :score direkt im Arbeitsspeicher erhöht. In einem realen System, das auf dieser Architektur basiert, können Knoten mit niedrigen Werten automatisch neu verknüpft werden, ohne dass ein Training des neuronalen Netzes erforderlich ist.

6. Ausweitung auf echte, „knifflige“ Gemüsesorten

Hier kommt die Stärke der symbolischen Logik ins Spiel: Im Gegensatz zu LLMs, die bei Geschmack und Toxizität oft „halluzinieren“, überprüft unsere Maschine klare Eigenschaften mithilfe eingebetteter Lisp-Funktionen und kann bei Bedarf Verbindungen dynamisch umbauen (Rewiring).

Der Einfachheit halber teilen wir unser Skript in zwei Teile auf: den Datenteil und den Logikteil (in der Praxis würden hier natürlich binäre .fsl-Dateien stehen).

Erstellen wir eine separate data.lisp-Datei, in der Gemüse und Logik als reine S-Ausdrücke gespeichert sind:


;; Datei: data.lisp
(defparameter *raw-data*
'((:char #\G :name "Gurke"
   :logic (lambda (p) (and (eq (getf p :taste) :fresh) (not (getf p :poison)))))

  (:char #\Z :name "Zwiebel"
   :logic (lambda (p) (and (eq (getf p :taste) :bitter) (not (getf p :poison)))))

  (:char #\W :name "Wolfsbeeren"
   :logic (lambda (p) (and (not (eq (getf p :taste) :bitter)) (getf p :poison))))))
                

Die Hauptdatei main.lisp lädt die Datendatei einfach mit der Funktion load in den Speicher, und der Interpreter wandelt den Text direkt in ausführbare Datenstrukturen um:


;; Datei: main.lisp

;; 1. Die Struktur eines Knotens im ternären Baum (TST)
(defstruct tst-node
  char
  name
  left
  mid   ; Speichert eine Logikfunktion
  right
  (score 1.0))

;; 2. Daten laden (Include)
(load "data.lisp")

;; 3. Funktion zum Zusammensetzen des TST-Baums
(defun build-tst (data-list)
  (let ((root nil))
    (dolist (item data-list root)
      (let ((new-node (make-tst-node
                       :char (getf item :char)
                       :name (getf item :name)
                       :mid  (getf item :logic))))
        (if (null root)
            (setf root new-node)
            (let ((curr root))
              (loop while (tst-node-left curr)
                    do (setf curr (tst-node-left curr)))
              (setf (tst-node-left curr) new-node)))))))

;; 4. Die Denk- und Bewertungsfunktion
(defun think (node query-char properties)
  (if (null node)
      "Objekt nicht gefunden"
      (if (char= query-char (tst-node-char node))
          (progn
            (format t "[Cognition] Überprüfung des Objekts: ~A~%" (tst-node-name node))
            (if (funcall (tst-node-mid node) properties)
                (format t " -> Ergebnis: Eigenschaften BESTÄTIGT für ~A!~%" (tst-node-name node))
                (format t " -> Ergebnis: Eigenschaftenfehler für ~A.~%" (tst-node-name node))))
          (think (tst-node-left node) query-char properties))))

;; --- START ---
(defparameter *mind-root* (build-tst *raw-data*))

(format t "=== TEST INCLUDE DURCH LOAD ===~%~%")

;; Überprüfung der Zwiebel (#\Z)
(think *mind-root* #\Z '(:taste :bitter :poison nil))
                

sbcl --script main.lisp
                

Ergebnis:


=== TEST INCLUDE DURCH LOAD ===

[Cognition] Überprüfung des Objekts: Zwiebel
 -> Ergebnis: Eigenschaften BESTÄTIGT für Zwiebel!
                

Warum diese Architektur überlegen ist:

  • Neuronale Netze verwechseln oft Regeln wie „bitter = giftig“ und klassifizieren Zwiebeln fälschlicherweise als gefährlich. Unser System führt exakten Booleschen Code aus.
  • Dynamische Topologie: Wollen wir einen Knoten verschieben, ändern wir einfach den Zeiger in der Lisp-Struktur zur Laufzeit, ohne das gesamte Netz neu trainieren zu müssen.

7. Wie funktioniert das im Detail?

Dieses System funktioniert völlig anders als herkömmliche Datenbanken oder neuronale Netze. Hier verschmelzen Daten, Code und Suchalgorithmen zu einem einzigen, lebendigen Organismus.

Schritt 1: Wissen verknüpfen („Direkte Hirninjektion“)

Normalerweise lesen Programme Textdateien (JSON oder SQL), parsen diese aufwendig und mappen sie in Variablen. Hier nutzen wir (load "data.lisp"). Lisp lädt den Code als ausführbare S-Ausdrücke, die direkt ein Mikroprogramm (eine Lambda-Funktion) zur Validierung mitbringen.

Schritt 2: Konstruktion des Bedeutungsbaums (TST)

Aus den Daten baut die Maschine einen TST auf. Jeder Knoten besitzt ein Symbol zur Schnellnavigation (z. B. #\Z), einen Namen und drei Zeiger (Links, Mitte, Rechts). Der „Mid“-Zweig speichert das logische Gehirn des Konzepts.

Schritt 3: Das System befragen

Wir übergeben der Maschine einen Suchbuchstaben und Eigenschaften (z. B. #\Z und bitter + ungifttig). Der Walker gleitet in Nanosekunden durch den Baum, ohne lineare Tabellenscans durchzuführen.

Schritt 4: Ausführung im Knoten

Sobald der Knoten erreicht ist, wird der direkt eingebettete Code ausgeführt:


(and (eq taste :bitter) (not poison))
                

Schritt 5: Feedback und Plastizität

Bei Erfolg wird das Gewicht im RAM erhöht (Score = Score + 0.1). Das System optimiert sich selbst durch direkte Pointer-Manipulation im Arbeitsspeicher statt durch ressourcenintensiven Gradientenabstieg.

8. Warum ausgerechnet die Zwiebel?

Die Wahl der Zwiebel (#\Z) war kein Zufall – es gibt einen semantischen und einen technischen Grund:

1. Semantisches Denken: Eine Gurke ist ein zu triviales Objekt (frisch, wässrig, essbar). Zwiebeln hingegen stellen einfache Klassifikatoren vor ein Paradoxon, da oft fälschlicherweise assoziiert wird: „bitter = Gift“. Unser System führt hier eine präzise boolesche Funktion aus:

$$\text{Ergebnis} = (\text{Geschmack} == \text{Bitter}) \land \neg(\text{Giftig})$$

2. Technische TST-Baumstruktur: In unserem kleinen Array werden die Elemente nacheinander eingelesen. Über die baumbasierte Navigation (Links/Rechts anhand der ASCII-Werte) demonstriert dies, wie zielgerichtet symbolische Suchen ohne statistisches Rauschen ablaufen.

to be continued ...

Im nächsten Schritt werden wir versuchen, das Ganze so umzusetzen: Als Interaktionsschnittstelle nutzen wir ein LLM, während unsere Wissensbasis auf unserem eigenen Algorithmus basiert. Es soll so etwas Ähnliches wie RAG entstehen – nur dass unsere Wissensbasis ‚denkt‘ und die benötigten Informationen im Laufe der Interaktion mit dem Nutzer automatisch an die ‚Oberfläche‘ befördert werden.

Diese Website verwendet den Browser-Cache für den Offline-Modus und verarbeitet Ihre Daten aus dem Kontaktformular gemäß unserer Datenschutzerklärung.