;
; shell.scm - Interactive chatbot shell
;
; Handles input/output, commands, and dispatches to layers.
;
(use-modules (ice-9 readline))
(use-modules (ice-9 regex))
(use-modules (ice-9 format))
(activate-readline)
;; ═══════════════════════════════════════════════════════════════════
;; CONVERSATION STORAGE
;; ═══════════════════════════════════════════════════════════════════
(define utterance-count 0)
(define (store-utterance text role)
"Store utterance in AtomSpace"
(set! utterance-count (+ 1 utterance-count))
(let ((node (cog-new-node 'ConceptNode
(format #f "utterance:~a:~a" role utterance-count))))
;; Store the text as a value
(cog-set-value! node (Predicate "text") (StringValue text))
(cog-set-value! node (Predicate "time") (FloatValue (current-time)))
node))
;; ═══════════════════════════════════════════════════════════════════
;; COMMAND HANDLING
;; ═══════════════════════════════════════════════════════════════════
(define (command? text)
(string-prefix? "/" text))
(define (parse-command text)
"Parse /command arg1 arg2 into (command arg1 arg2)"
(let ((parts (string-split (substring text 1) #\space)))
(filter (lambda (s) (> (string-length s) 0)) parts)))
(define (handle-command parts)
(let ((cmd (car parts))
(args (cdr parts)))
(cond
((string=? cmd "help")
(show-help))
((string=? cmd "stats")
(show-stats))
((string=? cmd "assoc")
(if (null? args)
"Usage: /assoc <word>"
(show-associations (car args))))
((string=? cmd "pmi")
(if (< (length args) 2)
"Usage: /pmi <word1> <word2>"
(show-pmi (car args) (cadr args))))
((string=? cmd "dump")
(show-atomspace))
((string=? cmd "clear")
(clear-atomspace))
((string=? cmd "vagueness")
(if (null? args)
(show-overall-vagueness)
(show-vagueness (car args))))
((string=? cmd "explain")
(if (null? args)
"Usage: /explain <word>"
(explain-word (car args))))
((string=? cmd "quit")
'quit)
(else
(format #f "Unknown command: /~a (try /help)" cmd)))))
(define (show-help)
"
Commands:
/help Show this help
/stats Show learning statistics
/assoc <word> Show top associations for word
/pmi <w1> <w2> Show PMI between two words
/vagueness [word] Show uncertainty (overall or for word)
/explain <word> Show all evidence about word
/dump Show raw AtomSpace contents
/clear Clear all knowledge (careful!)
/quit Exit chatbot
")
;; ═══════════════════════════════════════════════════════════════════
;; MAIN PROCESSING
;; ═══════════════════════════════════════════════════════════════════
(define (process-input text)
"Process user input through all layers"
;; Layer 1: Count word pairs
(layer1-process text)
;; Layer 2: Update clusters (when implemented)
;; (layer2-process text)
;; Generate response
(generate-response text))
(define (generate-response text)
"Generate response based on current knowledge"
;; Phase 0: Simple acknowledgment
;; Later: Use layer knowledge for intelligent responses
(let ((pairs-learned (layer1-count-for-text text)))
(if (> pairs-learned 0)
(format #f "Learned ~a word associations." pairs-learned)
"I heard you.")))
;; ═══════════════════════════════════════════════════════════════════
;; STATS & INTROSPECTION
;; ═══════════════════════════════════════════════════════════════════
(define (show-stats)
(format #f "
Statistics:
Utterances: ~a
Word pairs: ~a
Unique words: ~a
Total observations: ~a
"
utterance-count
(layer1-pair-count)
(layer1-word-count)
(layer1-total-observations)))
(define (show-atomspace)
(format #f "AtomSpace contains ~a atoms\n~a"
(cog-count-atoms 'Atom)
(cog-prt-atomspace)))
(define (clear-atomspace)
(cog-atomspace-clear)
(set! utterance-count 0)
(layer1-reset)
"Knowledge cleared.")
;; Placeholders for higher layers
(define (show-overall-vagueness)
"Vagueness tracking not yet implemented (Layer 6+)")
(define (show-vagueness word)
(format #f "Vagueness for '~a': not yet implemented" word))
(define (explain-word word)
(let ((assocs (layer1-associations word 5)))
(if (null? assocs)
(format #f "No knowledge about '~a'" word)
(format #f "Evidence for '~a':\n Layer 1 (associations): ~a"
word assocs))))
;; ═══════════════════════════════════════════════════════════════════
;; MAIN LOOP
;; ═══════════════════════════════════════════════════════════════════
(define (chatbot-loop)
(let ((input (readline "you> ")))
(cond
((not input) ; EOF
(display "\nGoodbye!\n"))
((string=? input "")
(chatbot-loop))
((command? input)
(let ((result (handle-command (parse-command input))))
(if (eq? result 'quit)
(display "Goodbye!\n")
(begin
(display result)
(newline)
(chatbot-loop)))))
(else
;; Store and process
(store-utterance input "user")
(let ((response (process-input input)))
(display (format #f "bot> ~a\n" response))
(store-utterance response "bot"))
(chatbot-loop)))))