I use lambda over let over lambda (lolol)[1] like this (Clojure):
(def chatgpt
(-> (endpoint :chat "gpt-4" auth)
(chat/set-opts [:endpoint] {:stream true})
chat/retry
chat/catch-unkown-commands
;; chat/history
chat/string-input
(chat/file-io "file.txt" :stream true)
#_(chat/preserve-ctx chatgpt-ctx)))
These higher-level functions take as input the next function in the chain, and return a function that is responsible for calling it and takes a context hashmap as argument. Additionally, you can pass messages to these functions like :history/reset, impacting the atom defined in the let part of lolol. I use the same pattern for higher level constructs:[1]https://letoverlambda.com/index.cl/guest/chap2.html#sec_6