Skip to content

Commit

Permalink
Next batch of features at 0.1
Browse files Browse the repository at this point in the history
:pre-when? :post-when? :starter, front-end-only blocks, :hide for UI values, REST endpoints...
  • Loading branch information
ryrobes committed Aug 21, 2023
1 parent f68ce98 commit f02f0cb
Show file tree
Hide file tree
Showing 8 changed files with 6,397 additions and 6,295 deletions.
8 changes: 4 additions & 4 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
[io.pedestal/pedestal.service "0.5.10"]
[io.pedestal/pedestal.jetty "0.5.10"]
[org.slf4j/slf4j-nop "1.7.32"]
[org.clojure/java.jdbc "0.7.12"] ;; example flow testing purposes only, will be removed next release
[org.xerial/sqlite-jdbc "3.36.0.3"] ;; example flow testing purposes only, will be removed next release
[clj-http "3.12.3"] ;; example flow testing purposes only, will be removed next release
[org.clojure/data.json "2.4.0"] ;; example flow testing purposes only, will be removed next release
[org.clojure/java.jdbc "0.7.12"] ;; ex flow testing purposes only, will be removed next release
[org.xerial/sqlite-jdbc "3.36.0.3"] ;; ex flow testing purposes only, will be removed next release
[clj-http "3.12.3"] ;; ex flow testing purposes only, will be removed next release
[org.clojure/data.json "2.4.0"] ;; ex flow testing purposes only, will be removed next release
[talltale "0.5.8" ;; exclusions recommended by `lein deps :tree`
:exclusions [org.clojure/spec.alpha org.clojure/core.specs.alpha]]
[mvxcvi/puget "1.3.2"]
Expand Down
12,204 changes: 6,107 additions & 6,097 deletions resources/public/js/compiled/app.js

Large diffs are not rendered by default.

123 changes: 93 additions & 30 deletions src/flowmaps/core.clj

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/flowmaps/db.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
(defonce chains-completed (atom []))
(defonce port-accumulator (atom {}))
(defonce block-defs (atom {}))
(defonce hidden-values (atom {}))
(defonce waffle-data (atom {}))
(defonce channels-atom (atom {})) ;; ref for putting things on later via REPL or whatever.
(defonce condi-channels-atom (atom {})) ;; ref for putting things on later via REPL or whatever.
Expand Down
101 changes: 49 additions & 52 deletions src/flowmaps/examples/simple_flows.clj
Original file line number Diff line number Diff line change
Expand Up @@ -8,65 +8,62 @@
[flowmaps.utility :as ut]))

;; flow defs for examples. work in progress.
(def openai-calls {:description "WIP - a simple HTTP loop using OpenAI API endpoint" ;; will be 10x better when we have a :when flow op instead of checking "super-local atoms"
:components {:prompt "Hello, how are you?"
:openai-api-key "suburban-sasquatch!"
(def openai-calls {:description "a simple HTTP loop using OpenAI API endpoint that keeps adding to chat history"
:components {:prompt "Top O' the morning!"
:openai-api-key (System/getenv "OAI_KEY")
:ai-ask {:fn (fn [prompt openai-api-key history]
(let [question {:role "user"
:content (str prompt)}]
(defonce last-prompt (atom nil))
(reset! last-prompt prompt) ;; to keep the loop from running amok (see :pre-when? below)
{:question question
:answer (walk/keywordize-keys
(json/read-str
(get (client/post "https://api.openai.com/v1/chat/completions"
{:body (json/write-str {:model "gpt-3.5-turbo"
:messages (vec (conj history question))})
:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " openai-api-key)}
:socket-timeout 9000
:connection-timeout 9000
:content-type :json
:accept :json}) :body)))}))
:view (fn [{:keys [question answer]}]
[:re-com/v-box :children [[:re-com/box :child (str (get question :content))]
[:re-com/box :child (str (get-in answer [:choices 0 :message :content]))]]])
:cond {:hold (fn [x] (do (defonce last-q (atom nil))
(let [q (get x :question)
repeat? (= q @last-q)]
(do (reset! last-q q)
repeat?))))}
:history (vec (conj history question))
:answer (clojure.walk/keywordize-keys
(clojure.data.json/read-str
(get (clj-http.client/post
"https://api.openai.com/v1/chat/completions"
{:body (clojure.data.json/write-str
{:model "gpt-4" ; "gpt-3.5-turbo"
:messages (vec (conj history question))})
:headers {"Content-Type" "application/json"
"Authorization" (str "Bearer " openai-api-key)}
:socket-timeout 300000
:connection-timeout 300000
:content-type :json
:accept :json}) :body)))}))
:pre-when? (fn [prompt _ _] ;; pre-when gets the same payload as the main fn
(let [same? (= prompt @last-prompt)]
(not same?)))
:inputs [:prompt :openai-api-key :history]}
:hold :hold
:memory []
:history (fn [{:keys [a q]}]
(let [msg (get (last a) :message {:role "system"
:content "You are a helpful assistant."})]
(defonce history (atom []))
(swap! history conj (or q {})) ;; append q
(swap! history conj msg) ;; append a
(remove empty? @history)))
:viewer {:fn (fn [x] {:a (get-in x [:answer :choices])
:q (get x :question)})
:view (fn [x] (str x))}}
:last-response (fn [x] x) ;; just to have a data block for the UI
:memory {:fn (fn [{:keys [question history answer]}]
(let [aa (get-in answer [:choices 0 :message])]
(conj history aa)))
:speak (fn [x] (str (get (last x) :content))) ;; if in Rabbit, and ElevenLabs KEY, read the answer
:starter [{:role "system" ;; ""bootstrap"" history with sys prompt
:content "You are a helpful assistant, you responses will be framed as if you are Buffy from the 1992 film."}]}}
;; canned REST / sub-flow endpoints
:points {"question" [[:prompt :ai-ask/prompt] ;; (channel to insert into)
[:ai-ask :memory]]} ;; (channel to snatch out of downstream)
;; ^^ send question, get answer (keeps convo state)
:hide [:openai-api-key]
:connections [[:prompt :ai-ask/prompt]
[:openai-api-key :ai-ask/openai-api-key]
[:ai-ask :viewer]
[:memory :history]
[:viewer :history]
[:history :ai-ask/history]]
:canvas {:ai-ask/openai-api-key
{:x 430 :y 430 :h 255 :w 240 :view-mode "data"}
:viewer {:x 1492 :y 692 :h 255 :w 240 :view-mode "view"}
:ai-ask/prompt
{:x 430 :y 100 :h 255 :w 240 :view-mode "data"}
:ai-ask/history
{:x 784 :y 959 :h 362 :w 622 :view-mode "grid"}
:memory {:x -79 :y 887 :h 144 :w 194 :view-mode "input"}
:hold {:x 1521 :y 374 :h 147 :w 255 :view-mode "input"}
:history {:x 228 :y 841 :h 544 :w 430 :view-mode "grid"}
:openai-api-key
{:x -72 :y 506 :h 104 :w 410 :view-mode "input"}
:prompt {:x 100 :y 100 :h 255 :w 240 :view-mode "input"}
:ai-ask {:x 811 :y 372 :h 387 :w 540 :view-mode "view"}}})
[:ai-ask :memory]
[:ai-ask :last-response]
[:memory :ai-ask/history]]
:canvas {:ai-ask/openai-api-key {:x 430 :y 430 :h 255 :w 240 :view-mode "text" :hidden? true}
:ai-ask/prompt {:x 430 :y 100 :h 255 :w 240 :view-mode "text" :hidden? true}
:ai-ask/history {:x 466 :y 962 :h 350 :w 894 :view-mode "text" :hidden? true}
:ai-ask {:x 815 :y 347 :h 522 :w 434 :view-mode "text"}
:memory {:x -199 :y 750 :h 369 :w 538 :view-mode "data"}
:openai-api-key {:x -243 :y 505 :h 141 :w 565 :view-mode "input"}
:prompt {:x -136 :y 145 :h 212 :w 415 :view-mode "input"}
:last-response {:x 1383 :y 380 :h 755 :w 818 :view-mode "data"}
"just-the-answer" {:inputs [[:last-response [:text [:map [:v :answer :choices 0 :message :content]]]]]
:x 2585 :y 984 :h 215 :w 400}
"just-the-question" {:inputs [[:last-response [:text [:map [:v :question :content]]]]]
:x 2575 :y 577 :h 215 :w 400}}})

(def my-network {:description "a simple example flow: addition and integers"
:components {:comp1 10
Expand Down
33 changes: 29 additions & 4 deletions src/flowmaps/rest.clj
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@
:dest (last channel-name)
:start start
:end (System/currentTimeMillis)
:value (ut/limited v)
:value (ut/limited v flow-id)
:data-type (ut/data-typer v)}))
(swap! db/fn-history assoc flow-id (conj (get @db/fn-history flow-id []) {:block from :from :static
:path [:from :static from]
:value (ut/limited value) ;(ut/limited (get web-val-map :v)) ;; since it's going to the front-end ultimately
:value (ut/limited value flow-id)
:type :function
:dest from
:channel [from]
:data-type (ut/data-typer (ut/limited value))
:data-type (ut/data-typer (ut/limited value flow-id))
:start start
:end (System/currentTimeMillis)
:elapsed-ms (- (System/currentTimeMillis) start)}))
Expand All @@ -85,10 +85,35 @@
event event ;(get event :value) ; Found the desired event, return it
(> (System/currentTimeMillis) deadline)
(throw (Exception. (str "Timeout waiting for event to hit channel " channel " in flow " flow-id)))
:else (do (Thread/sleep 50) ; Wait for a short duration before polling again
:else (do (Thread/sleep 300) ; Wait for a short duration before polling again
(recur))))))
(catch Exception e {:error (str e)})))

(defn flow-point-push [request]
(let [point-id (get-in request [:path-params :point-id])
flow-id (get-in request [:path-params :flow-id])
point-data (get-in @db/working-data [flow-id :points point-id])
time-key (System/currentTimeMillis)
value (get request :edn-params) ;(get-in request [:edn-params :value])
channel (first point-data) ;(get-in request [:edn-params :channel])
return-channel (last point-data) ;(get-in request [:edn-params :return])
_ (push-channel-value [channel] flow-id value)
return (wait-for-event return-channel flow-id time-key 30000)]
(let [base {:flow-id flow-id ;; extra let to wait until return?
:return-value (get return :value)
:channel-sent-to channel
:value-sent value
:value value
:return-channel return-channel}
err-base {:flow-id flow-id
:return-value return
:channel-sent-to channel
:value-sent value
:error (get return :error)
:return-channel return-channel}
error? (get return :error)]
(send-edn (if error? err-base base)))))

(defn flow-value-push [request]
(if (get-in request [:edn-params :return]) ;; are we picking up a channel val to return?
(let [time-key (System/currentTimeMillis)
Expand Down

0 comments on commit f02f0cb

Please sign in to comment.