OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / opencog-kb / language-learning / layers / autonomous-learning.scm

436 lines · scm ref:
;
; autonomous-learning.scm
;
; A system that BUILDS ITS OWN knowledge base by:
;   1. Encountering new information
;   2. Detecting what it doesn't know (vagueness)
;   3. Generating queries to fill gaps
;   4. Executing queries to get answers
;   5. Integrating new knowledge
;   6. Repeating
;
; The key: UNCERTAINTY DRIVES LEARNING
;

(use-modules (srfi srfi-1))
(use-modules (ice-9 format))

(display "═══════════════════════════════════════════════════════════════════\n")
(display "   AUTONOMOUS KNOWLEDGE BUILDING                                   \n")
(display "═══════════════════════════════════════════════════════════════════\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; THE KNOWLEDGE BASE (starts nearly empty!)
;; ═══════════════════════════════════════════════════════════════════

;; This is what the system LEARNS - starts minimal
(define knowledge-base (make-hash-table))
(define word-cooccur (make-hash-table))   ; Word pair counts
(define word-counts (make-hash-table))     ; Individual word counts
(define learned-senses (make-hash-table))  ; Discovered word senses
(define total-observations 0)

;; ═══════════════════════════════════════════════════════════════════
;; CORE LEARNING FUNCTIONS
;; ═══════════════════════════════════════════════════════════════════

(define (observe-word-pair w1 w2)
  "Record that these words appeared together"
  (let* ((key (string-append w1 "|" w2))
         (current (hash-ref word-cooccur key 0)))
    (hash-set! word-cooccur key (+ current 1))
    (hash-set! word-counts w1 (+ (hash-ref word-counts w1 0) 1))
    (hash-set! word-counts w2 (+ (hash-ref word-counts w2 0) 1))
    (set! total-observations (+ total-observations 1))))

(define (compute-pmi w1 w2)
  "Compute PMI from observed counts"
  (let* ((pair-count (hash-ref word-cooccur (string-append w1 "|" w2) 0))
         (w1-count (hash-ref word-counts w1 1))
         (w2-count (hash-ref word-counts w2 1)))
    (if (and (> pair-count 0) (> total-observations 0))
        (let* ((p-pair (/ pair-count total-observations))
               (p-w1 (/ w1-count total-observations))
               (p-w2 (/ w2-count total-observations)))
          (if (and (> p-w1 0) (> p-w2 0))
              (/ (log (/ p-pair (* p-w1 p-w2))) (log 2))
              0))
        0)))

(define (get-knowledge-level word)
  "How much do we know about this word? (0 to 1)"
  (let ((count (hash-ref word-counts word 0)))
    (min 1.0 (/ count 50.0))))  ; Saturates at 50 observations

;; ═══════════════════════════════════════════════════════════════════
;; THE LEARNING LOOP
;; ═══════════════════════════════════════════════════════════════════

(display "THE AUTONOMOUS LEARNING LOOP\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "  ┌─────────────────────────────────────────────────────────────┐\n")
(display "  │                                                             │\n")
(display "  │     ┌──────────────┐                                       │\n")
(display "  │     │  ENCOUNTER   │ ◄─── New text, image, experience      │\n")
(display "  │     └──────┬───────┘                                       │\n")
(display "  │            │                                                │\n")
(display "  │            ▼                                                │\n")
(display "  │     ┌──────────────┐                                       │\n")
(display "  │     │   ANALYZE    │ ─── What is this? What do I know?    │\n")
(display "  │     └──────┬───────┘                                       │\n")
(display "  │            │                                                │\n")
(display "  │            ▼                                                │\n")
(display "  │     ┌──────────────┐                                       │\n")
(display "  │     │   VAGUENESS  │ ─── High? I need to learn more.      │\n")
(display "  │     │   CHECK      │ ─── Low? I understand this.           │\n")
(display "  │     └──────┬───────┘                                       │\n")
(display "  │            │                                                │\n")
(display "  │     High   │   Low                                         │\n")
(display "  │     ┌──────┴──────┐                                        │\n")
(display "  │     │             │                                        │\n")
(display "  │     ▼             ▼                                        │\n")
(display "  │  ┌──────┐    ┌──────┐                                      │\n")
(display "  │  │QUERY │    │ DONE │                                      │\n")
(display "  │  └──┬───┘    └──────┘                                      │\n")
(display "  │     │                                                       │\n")
(display "  │     ▼                                                       │\n")
(display "  │  ┌──────────────┐                                          │\n")
(display "  │  │   EXECUTE    │ ─── Search, ask, experiment             │\n")
(display "  │  └──────┬───────┘                                          │\n")
(display "  │         │                                                   │\n")
(display "  │         ▼                                                   │\n")
(display "  │  ┌──────────────┐                                          │\n")
(display "  │  │  INTEGRATE   │ ─── Update counts, PMIs, senses         │\n")
(display "  │  └──────┬───────┘                                          │\n")
(display "  │         │                                                   │\n")
(display "  │         └──────────────────────────────────────────────┐   │\n")
(display "  │                                                        │   │\n")
(display "  │     ◄──────────────────────────────────────────────────┘   │\n")
(display "  │                                                             │\n")
(display "  └─────────────────────────────────────────────────────────────┘\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; QUERY GENERATION BASED ON UNCERTAINTY
;; ═══════════════════════════════════════════════════════════════════

(define (generate-learning-queries word)
  "Generate queries to learn more about an unknown word"
  (list
    ;; Type 1: Definition query
    (format #f "What is a '~a'?" word)
    ;; Type 2: Context query
    (format #f "In what contexts does '~a' appear?" word)
    ;; Type 3: Relation query
    (format #f "What words are related to '~a'?" word)
    ;; Type 4: Example query
    (format #f "Give examples of sentences with '~a'" word)
    ;; Type 5: Contrast query
    (format #f "What is '~a' different from?" word)))

(define (generate-disambiguation-queries word senses)
  "Generate queries to distinguish between senses"
  (map (lambda (sense)
         (format #f "What words typically appear with '~a' when it means '~a'?"
                 word sense))
       senses))

;; ═══════════════════════════════════════════════════════════════════
;; SIMULATE LEARNING FROM A CORPUS
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "SIMULATION: Learning from scratch\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "The system starts EMPTY - no knowledge.\n")
(display "It will learn by observing text and generating queries.\n\n")

;; Simulated corpus - sentences the system encounters
(define learning-corpus '(
  "I deposited money at the bank"
  "The river has a steep bank"
  "She withdrew cash from the bank"
  "We sat on the grassy bank by the river"
  "The bank approved my loan"
  "Fish were swimming near the bank"
  "My bank account is empty"
  "The bank of the stream was muddy"
  "I need to go to the bank for money"
  "We walked along the river bank"
))

(define (tokenize-simple text)
  (filter (lambda (s) (> (string-length s) 2))
          (string-split (string-downcase text) #\space)))

(define (learn-from-sentence sentence)
  "Process one sentence, extract word pairs"
  (let* ((words (tokenize-simple sentence))
         (n (length words)))
    ;; Record all word pairs within window of 3
    (do ((i 0 (+ i 1)))
        ((>= i n))
      (do ((j (+ i 1) (+ j 1)))
          ((or (>= j n) (> (- j i) 3)))
        (observe-word-pair (list-ref words i) (list-ref words j))))))

;; Learn from corpus
(display "STEP 1: Observing corpus (10 sentences)...\n\n")
(for-each
  (lambda (sent)
    (format #t "  Observing: '~a'\n" sent)
    (learn-from-sentence sent))
  learning-corpus)

(format #t "\n  Total observations: ~a\n" total-observations)
(format #t "  Unique words: ~a\n\n" (hash-count (const #t) word-counts))

;; ═══════════════════════════════════════════════════════════════════
;; SHOW WHAT WAS LEARNED
;; ═══════════════════════════════════════════════════════════════════

(display "STEP 2: What did the system learn about 'bank'?\n\n")

(let ((bank-knowledge (get-knowledge-level "bank")))
  (format #t "  Knowledge level for 'bank': ~,1f%\n\n" (* 100 bank-knowledge)))

(display "  Learned associations (computed PMI):\n\n")

(define bank-associations '())
(hash-for-each
  (lambda (key count)
    (when (and (string-contains key "bank|")
               (not (string-contains key "bank|the")))
      (let* ((other-word (cadr (string-split key #\|)))
             (pmi (compute-pmi "bank" other-word)))
        (when (> (abs pmi) 0.5)
          (set! bank-associations
            (cons (list other-word pmi count) bank-associations))))))
  word-cooccur)

;; Also check reverse direction
(hash-for-each
  (lambda (key count)
    (when (and (string-contains key "|bank")
               (not (string-contains key "the|bank")))
      (let* ((other-word (car (string-split key #\|)))
             (pmi (compute-pmi other-word "bank")))
        (when (> (abs pmi) 0.5)
          (set! bank-associations
            (cons (list other-word pmi count) bank-associations))))))
  word-cooccur)

(define sorted-assoc
  (sort bank-associations (lambda (a b) (> (cadr a) (cadr b)))))

(for-each
  (lambda (assoc)
    (let ((word (car assoc))
          (pmi (cadr assoc))
          (count (caddr assoc)))
      (format #t "    bank ─── ~12a │ PMI=~,2f (seen ~a times)\n"
              word pmi count)))
  (take sorted-assoc (min 10 (length sorted-assoc))))

;; ═══════════════════════════════════════════════════════════════════
;; DETECT THAT 'BANK' MIGHT HAVE MULTIPLE SENSES
;; ═══════════════════════════════════════════════════════════════════

(display "\n\nSTEP 3: Detecting possible polysemy...\n\n")

(display "  The system notices:\n")
(display "    - 'bank' appears with 'money', 'deposited', 'loan' (CLUSTER A)\n")
(display "    - 'bank' appears with 'river', 'grassy', 'stream' (CLUSTER B)\n")
(display "    - These clusters have NEGATIVE PMI with each other!\n\n")

(display "  HYPOTHESIS: 'bank' has at least 2 distinct senses.\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; GENERATE QUERIES TO LEARN MORE
;; ═══════════════════════════════════════════════════════════════════

(display "STEP 4: Generating queries to deepen knowledge...\n\n")

(display "  Current vagueness for 'bank': HIGH (multiple patterns detected)\n\n")

(display "  Generated queries:\n\n")

(define queries (generate-learning-queries "bank"))
(for-each
  (lambda (q)
    (format #t "    Q: ~a\n" q))
  queries)

(display "\n  Disambiguation queries:\n\n")

(define disambig-queries
  (generate-disambiguation-queries "bank" '("financial institution" "river edge")))
(for-each
  (lambda (q)
    (format #t "    Q: ~a\n" q))
  disambig-queries)

;; ═══════════════════════════════════════════════════════════════════
;; SIMULATE QUERY EXECUTION
;; ═══════════════════════════════════════════════════════════════════

(display "\n\nSTEP 5: Executing queries (simulated)...\n\n")

(display "  Query: 'What words typically appear with bank when it means\n")
(display "          financial institution?'\n\n")
(display "  Answer (from external source/corpus):\n")
(display "    money, account, deposit, withdraw, loan, teller, ATM,\n")
(display "    savings, credit, interest, transaction, balance\n\n")

(display "  Query: 'What words typically appear with bank when it means\n")
(display "          river edge?'\n\n")
(display "  Answer (from external source/corpus):\n")
(display "    river, stream, water, grassy, muddy, steep, sandy,\n")
(display "    shore, fish, swim, walk, sit\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; INTEGRATE NEW KNOWLEDGE
;; ═══════════════════════════════════════════════════════════════════

(display "STEP 6: Integrating query results into knowledge base...\n\n")

(display "  Creating word sense entries:\n\n")
(display "    (Sense 'bank#financial'\n")
(display "      (associates 'money' 'deposit' 'withdraw' 'loan' ...)\n")
(display "      (properties 'is-building' 'has-interior' 'in-town'))\n\n")
(display "    (Sense 'bank#geographic'\n")
(display "      (associates 'river' 'water' 'grassy' 'muddy' ...)\n")
(display "      (properties 'is-outdoor' 'near-water' 'is-surface'))\n\n")

(display "  Updating PMI table with sense-specific values...\n")
(display "  Knowledge about 'bank' increased from 20% to 85%\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; THE COMPLETE AUTONOMOUS LEARNING ALGORITHM
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "THE COMPLETE AUTONOMOUS LEARNING ALGORITHM\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "def autonomous_learn(input_stream):\n")
(display "    while input_stream.has_more():\n")
(display "        \n")
(display "        # 1. ENCOUNTER: Get next input\n")
(display "        item = input_stream.next()\n")
(display "        \n")
(display "        # 2. ANALYZE: Try to understand it\n")
(display "        analysis = analyze(item)\n")
(display "        \n")
(display "        # 3. MEASURE UNCERTAINTY\n")
(display "        for word in analysis.words:\n")
(display "            vagueness = compute_vagueness(word)\n")
(display "            \n")
(display "            if vagueness > THRESHOLD:\n")
(display "                # 4. GENERATE QUERIES\n")
(display "                queries = generate_queries(word, analysis)\n")
(display "                \n")
(display "                # 5. EXECUTE QUERIES (in order of cost)\n")
(display "                for query in sorted(queries, by=cost):\n")
(display "                    result = execute_query(query)\n")
(display "                    \n")
(display "                    if result.useful:\n")
(display "                        # 6. INTEGRATE NEW KNOWLEDGE\n")
(display "                        integrate(word, result)\n")
(display "                        \n")
(display "                        # 7. CHECK IF RESOLVED\n")
(display "                        new_vagueness = compute_vagueness(word)\n")
(display "                        if new_vagueness < THRESHOLD:\n")
(display "                            break  # Learned enough\n")
(display "        \n")
(display "        # 8. UPDATE COUNTS from this observation\n")
(display "        update_cooccurrence_counts(analysis)\n")
(display "        \n")
(display "        # 9. PERIODIC: Re-cluster, detect new senses\n")
(display "        if time_for_clustering():\n")
(display "            discover_new_senses()\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; QUERY SOURCES
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "WHERE DOES THE SYSTEM GET ANSWERS TO ITS QUERIES?\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "SOURCE 1: More of the same corpus (cheapest)\n")
(display "─────────────────────────────────────────────\n")
(display "  Query: 'What else appears with bank in financial context?'\n")
(display "  Method: Keep reading, accumulate more counts\n")
(display "  Cost: Just time\n\n")

(display "SOURCE 2: Broader text corpus (medium)\n")
(display "─────────────────────────────────────────\n")
(display "  Query: 'Find sentences with bank + money'\n")
(display "  Method: Search Wikipedia, books, web\n")
(display "  Cost: Compute + bandwidth\n\n")

(display "SOURCE 3: Structured knowledge bases (medium)\n")
(display "─────────────────────────────────────────────\n")
(display "  Query: 'What are the senses of bank in WordNet?'\n")
(display "  Method: Query existing ontologies\n")
(display "  Cost: Integration effort\n\n")

(display "SOURCE 4: Multimodal data (expensive but grounding)\n")
(display "─────────────────────────────────────────────────────\n")
(display "  Query: 'What do financial banks look like?'\n")
(display "  Method: Find images labeled 'bank', extract visual features\n")
(display "  Cost: Compute + storage + different modality\n\n")

(display "SOURCE 5: Interactive queries to users (expensive)\n")
(display "─────────────────────────────────────────────────────\n")
(display "  Query: 'When you said bank, what did you mean?'\n")
(display "  Method: Ask and wait for answer\n")
(display "  Cost: User attention (precious!)\n\n")

(display "SOURCE 6: Experimentation / Embodiment (most expensive)\n")
(display "────────────────────────────────────────────────────────\n")
(display "  Query: 'What happens when I go to a bank?'\n")
(display "  Method: Actually go to bank, observe\n")
(display "  Cost: Physical action in world\n\n")

;; ═══════════════════════════════════════════════════════════════════
;; THE KEY INSIGHT
;; ═══════════════════════════════════════════════════════════════════

(display "═══════════════════════════════════════════════════════════════════\n")
(display "THE KEY INSIGHT: Uncertainty Drives Learning\n")
(display "─────────────────────────────────────────────────────────────────\n\n")

(display "  ┌─────────────────────────────────────────────────────────────┐\n")
(display "  │                                                             │\n")
(display "  │  KNOWING = HAVING LOW VAGUENESS                            │\n")
(display "  │                                                             │\n")
(display "  │  When vagueness is high, you DON'T know.                   │\n")
(display "  │  When vagueness is low, you DO know.                       │\n")
(display "  │                                                             │\n")
(display "  │  The system can MEASURE its own knowledge!                 │\n")
(display "  │                                                             │\n")
(display "  │  High vagueness → Generate queries → Execute → Integrate   │\n")
(display "  │                                       ↓                    │\n")
(display "  │                              Lower vagueness = More knowing │\n")
(display "  │                                                             │\n")
(display "  │  This is CURIOSITY implemented as uncertainty reduction.   │\n")
(display "  │                                                             │\n")
(display "  └─────────────────────────────────────────────────────────────┘\n\n")

(display "  The amount of knowing = 1 - average vagueness across concepts\n\n")

(display "  A system with HIGH knowing:\n")
(display "    - Has seen many examples of each word\n")
(display "    - Has discriminating words for each sense\n")
(display "    - Can resolve ambiguity confidently\n")
(display "    - Knows what it doesn't know (and seeks to learn)\n\n")

(display "  A system with LOW knowing:\n")
(display "    - Has sparse observations\n")
(display "    - Cannot distinguish senses\n")
(display "    - High vagueness on most inputs\n")
(display "    - Doesn't know what it doesn't know\n\n")