Skip to content

Commit

Permalink
chore: Refactor namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
motform committed Oct 5, 2024
1 parent 136e0fb commit 30fdd65
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 135 deletions.
16 changes: 8 additions & 8 deletions src/org/motform/multiverse/components/reader.cljs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
(ns org.motform.multiverse.components.reader
(:require [clojure.string :as str]
[re-frame.core :as rf]
[org.motform.multiverse.util :as util]))
(:require
[clojure.string :as str]
[re-frame.core :as rf]))

;; TODO use OpenAI to detech paragraphs
;; https://andrewmayneblog.wordpress.com/2020/06/13/openai-api-alchemy-smart-formatting-and-code-creation/
(defn format-story [paragraphs]
(reduce
(fn [story {:sentence/keys [text]}]
(if (str/starts-with? (str/trim text) "\"")
(conj story text)
(conj (pop story) (apply str (last story) " " text))))
[(-> paragraphs first :sentence/text)] (rest paragraphs)))
(fn [story {:sentence/keys [text]}]
(if (str/starts-with? (str/trim text) "\"")
(conj story text)
(conj (pop story) (apply str (last story) " " text))))
[(-> paragraphs first :sentence/text)] (rest paragraphs)))

(defn literary [paragraphs]
[:article.reader.shadow-large.pad-full.rounded.v-stack.gap-full
Expand Down
2 changes: 1 addition & 1 deletion src/org/motform/multiverse/components/story.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
[map/RadialMap :source/story]])
[:section.v-stack.gap-full.pad-full
(if request?
[:section.children.pad-full [util/spinner]]
[:section.children.pad-full [util/Spinner]]
[:section.children.h-equal-3.gap-full
(for [{:sentence/keys [id text children]} children] ^{:key id}
[ChildSelector text id (seq children)])])]]]))
21 changes: 21 additions & 0 deletions src/org/motform/multiverse/db.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,24 @@
(fn [cofx _]
(assoc cofx :local-store-collections
(some->> (.getItem js/localStorage ls-key) (reader/read-string)))))

(defn children
([db parent-id] (children db parent-id nil))
([db parent-id story-id]
(let [story-id (or story-id (get-in db [:db/state :story/active]))]
(select-keys (get-in db [:db/stories story-id :story/sentences])
(get-in db [:db/stories story-id :story/sentences parent-id :sentence/children])))))

(defn completion-meta [db]
(let [story-id (get-in db [:db/state :story/active])
parent-id (get-in db [:db/stories story-id :story/meta :sentence/active])
api-key (get-in db [:db/state :open-ai/key :open-ai/api-key])]
{:story-id story-id
:parent-id parent-id
:api-key api-key}))

(defn paragraph [db story-id sentence-id]
(reduce
(fn [sentences id]
(conj sentences (get-in db [:db/stories story-id :story/sentences id])))
[] (get-in db [:db/stories story-id :story/sentences sentence-id :sentence/path])))
97 changes: 10 additions & 87 deletions src/org/motform/multiverse/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[org.motform.multiverse.db :as db]
[org.motform.multiverse.open-ai :as open-ai]
[org.motform.multiverse.routes :as routes]
[org.motform.multiverse.util :as util]
[org.motform.multiverse.story :as story]
[re-frame.core :as rf :refer [reg-event-db reg-event-fx reg-fx inject-cofx after]]))

;; Interceptors
Expand Down Expand Up @@ -80,31 +80,11 @@
(fn [db _]
(assoc-in db [:db/state :tab/highlight] nil)))

;; New-story

(defn ->sentence [id text path children]
#:sentence{:id id :text text :path path :children children})

(defn ->story [story-id sentence-id prompt]
{:story/meta {:story/id story-id
:story/title ""
:story/updated (js/Date.)
:sentence/active sentence-id}
:story/sentences {sentence-id (->sentence sentence-id prompt [sentence-id] [])}})

(def prompt-templates
#:template
{:blank ""
:urban "I was walking my tan Whippet down the Avenue of the Ameriacs, when suddenly, the ground begain to shake. We looked up in unison and where utterly shocked to see..."
:musical "Lyrics: ♪ Bunnies aren’t just cute like everyone supposes. They got them hoppy legs and twitchy little noses, and what’s with all the carrots!? ♪"
:news "BREAKING NEWS: The world's largest pumpkin has turned sentient is a chocking turn of events. But while some have resorted to running amok on the streets, local farmers claim the incident as a \"Relatively commonplace fall missunderstanding\"."
:ai "The rapid progression of AI technolgies had worried Sam. They argued benevolence as never given, citing Assmiov's laws as thin veneer. That all changed once GLADOS came into the picture."})

(reg-event-db :new-story/template
(fn [db [_ template]]
(-> db
(assoc-in [:db/state :new-story/template] template)
(assoc-in [:db/state :new-story/prompt] (prompt-templates template)))))
(assoc-in [:db/state :new-story/prompt] (story/prompt-templates template)))))

(reg-event-fx :new-story/submit
(fn [{:keys [db]} _]
Expand All @@ -121,7 +101,7 @@
(let [story-id (nano-id 10)
sentence-id (nano-id 10)]
{:db (-> db
(assoc-in [:db/stories story-id] (->story story-id sentence-id prompt))
(assoc-in [:db/stories story-id] (story/->story story-id sentence-id prompt))
(assoc-in [:db/state :story/active] story-id)
(assoc-in [:db/state :sentence/active] sentence-id)
(assoc-in [:db/state :sentence/highlight] {:id sentence-id :source :page/new-story})
Expand All @@ -148,30 +128,15 @@

;; OpenAI

(defn auth [api-key]
{"Authorization" (str "Bearer " api-key)})

(defn ->children
"Make children map to be merged into sentences."
[parent-path child-ids texts]
(let [child-pairs (util/pairs child-ids texts)]
(reduce (fn [children [id text]]
(assoc children id (->sentence id text (conj parent-path id) [])))
{} child-pairs)))

(defn- open-ai-texts [completion]
(map #(-> % :message :content)
(:choices completion)))

(reg-event-fx :open-ai/handle-children
[local-storage-interceptor]
(fn [{:keys [db]} [_ story-id parent-id completions]]
(let [parent-path (get-in db [:db/stories story-id :story/sentences parent-id :sentence/path])
child-ids (repeatedly 3 #(nano-id 10))
children (->children
children (story/->children
parent-path
child-ids
(open-ai-texts completions))]
(open-ai/completion-texts completions))]
{:db (-> db
(update-in [:db/stories story-id :story/sentences] merge children)
(assoc-in [:db/stories story-id :story/sentences parent-id :sentence/children] child-ids)
Expand Down Expand Up @@ -202,20 +167,20 @@
{:method :get
;; The key is "validated" by the endpoint, not the request.
:uri (open-ai/endpoint :models)
:headers (auth api-key)
:headers (open-ai/auth api-key)
:response-format (ajax/json-response-format {:keywords? true})
:on-success [:open-ai/handle-validate-api-key]
:on-failure [:failure-http]}})))

(reg-event-fx :open-ai/completions
(fn [{:keys [db]} [_ parent-id prompt]]
(let [{:keys [story-id api-key]} (util/completion-data db)
(let [{:keys [story-id api-key]} (db/completion-meta db)
params (open-ai/request-next-sentence :gpt-4-1106-preview prompt)]
{:db (assoc-in db [:db/state :open-ai/pending-request?] true)
:http-xhrio
{:method :post
:uri (open-ai/endpoint :chat)
:headers (auth api-key)
:headers (open-ai/auth api-key)
:params params
:format (ajax/json-request-format)
:response-format (ajax/json-response-format {:keywords? true})
Expand All @@ -224,60 +189,18 @@

(reg-event-fx :open-ai/title
(fn [{:keys [db]} _]
(let [{:keys [story-id api-key]} (util/completion-data db)
(let [{:keys [story-id api-key]} (db/completion-meta db)
pargraphs (vals (get-in db [:db/stories story-id :story/sentences]))
params (open-ai/request-title :gpt-4-1106-preview pargraphs)]
{:http-xhrio {:method :post
:uri (open-ai/endpoint :chat)
:headers (auth api-key)
:headers (open-ai/auth api-key)
:params params
:format (ajax/json-request-format)
:response-format (ajax/json-response-format {:keywords? true})
:on-success [:open-ai/handle-title story-id]
:on-failure [:open-ai/failure]}})))

(reg-event-db :open-ai/replace-children
(fn [db [_ story-id parent-id unrealized-child-ids completions]]
(let [original-children (util/children db parent-id story-id)
realized-children (select-keys original-children
(->> original-children
vals
(map :sentence/id)
(remove unrealized-child-ids)))
new-child-ids (repeatedly (count unrealized-child-ids)
#(nano-id 10))
parent-path (get-in db [:db/stories story-id :story/sentences parent-id :sentence/path])
new-children (->children parent-path
new-child-ids
(open-ai-texts completions))]
(-> db
(update-in [:db/stories story-id :story/sentences] #(apply dissoc % unrealized-child-ids))
(update-in [:db/stories story-id :story/sentences] merge new-children)
(assoc-in [:db/stories story-id :story/sentences parent-id :sentence/children] (keys (merge realized-children new-children)))
(assoc-in [:db/stories story-id :story/meta :story/updated] (js/Date.))
(assoc-in [:db/state :open-ai/pending-request?] false)))))

(reg-event-fx :open-ai/replace-completions
(fn [{:keys [db]} [_]]
(let [{:keys [story-id parent-id api-key]} (util/completion-data db)
unrealized-children (->> (util/children db parent-id)
vals
(filter #(empty? (:sentence/children %))))
n-unrealized-children (count unrealized-children)]
(when-not (zero? n-unrealized-children)
(let [paragraph (util/paragraph db story-id parent-id)
params (open-ai/request-next-sentence :gpt-4-1106-preview paragraph)]
{:db (assoc-in db [:db/state :open-ai/pending-request?] true)
:http-xhrio
{:method :post
:uri (open-ai/endpoint :chat)
:headers (auth api-key)
:params params
:format (ajax/json-request-format)
:response-format (ajax/json-response-format {:keywords? true})
:on-success [:open-ai/replace-children story-id parent-id (set (map :sentence/id unrealized-children))]
:on-failure [:open-ai/failure]}})))))

(reg-event-db :open-ai/failure
(fn [db [_ result]]
(assoc-in db [:db/state :open-ai/failure] result)))
7 changes: 7 additions & 0 deletions src/org/motform/multiverse/open_ai.cljs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
(ns org.motform.multiverse.open-ai)

(defn auth [api-key]
{"Authorization" (str "Bearer " api-key)})

(def endpoint
{:chat "https://api.openai.com/v1/chat/completions"
:models "https://api.openai.com/v1/models"})
Expand All @@ -16,6 +19,10 @@
(:pre [(valid-role? role)])
{:role (name role) :content content})

(defn completion-texts [completion]
(map #(-> % :message :content)
(:choices completion)))

;; Chat

(def system-message
Expand Down
7 changes: 4 additions & 3 deletions src/org/motform/multiverse/routes.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(ns org.motform.multiverse.routes
(:require [bidi.bidi :as bidi]
[re-frame.core :as rf]
[pushy.core :as pushy]))
(:require
[bidi.bidi :as bidi]
[pushy.core :as pushy]
[re-frame.core :as rf]))

(def titles
{:page/new-story "New story"
Expand Down
29 changes: 29 additions & 0 deletions src/org/motform/multiverse/story.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
(ns org.motform.multiverse.story
(:require
[org.motform.multiverse.util :as util]))

(defn ->sentence [id text path children]
#:sentence{:id id :text text :path path :children children})

(defn ->story [story-id sentence-id prompt]
{:story/meta {:story/id story-id
:story/title ""
:story/updated (js/Date.)
:sentence/active sentence-id}
:story/sentences {sentence-id (->sentence sentence-id prompt [sentence-id] [])}})

(def prompt-templates
#:template
{:blank ""
:urban "I was walking my tan Whippet down the Avenue of the Ameriacs, when suddenly, the ground begain to shake. We looked up in unison and where utterly shocked to see..."
:musical "Lyrics: ♪ Bunnies aren’t just cute like everyone supposes. They got them hoppy legs and twitchy little noses, and what’s with all the carrots!? ♪"
:news "BREAKING NEWS: The world's largest pumpkin has turned sentient is a chocking turn of events. But while some have resorted to running amok on the streets, local farmers claim the incident as a \"Relatively commonplace fall missunderstanding\"."
:ai "The rapid progression of AI technolgies had worried Sam. They argued benevolence as never given, citing Assmiov's laws as thin veneer. That all changed once GLADOS came into the picture."})

(defn ->children
"Make children map to be merged into sentences."
[parent-path child-ids texts]
(let [child-pairs (util/pairs child-ids texts)]
(reduce (fn [children [id text]]
(assoc children id (->sentence id text (conj parent-path id) [])))
{} child-pairs)))
6 changes: 3 additions & 3 deletions src/org/motform/multiverse/subs.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns org.motform.multiverse.subs
(:require
[org.motform.multiverse.util :as util]
[org.motform.multiverse.db :as db]
[re-frame.core :as rf :refer [reg-sub]]))

(defn from-state [k]
Expand Down Expand Up @@ -47,7 +47,7 @@
(reg-sub
:sentence/children
(fn [db [_ parent-id story-id]]
(vals (util/children db parent-id story-id))))
(vals (db/children db parent-id story-id))))

;; db

Expand Down Expand Up @@ -86,7 +86,7 @@
(fn [db [_ sentence-id story-id]]
(let [story-id (or story-id @(rf/subscribe [:story/active]))
sentence-id (or sentence-id @(rf/subscribe [:sentence/active story-id]))]
(util/paragraph db story-id sentence-id))))
(db/paragraph db story-id sentence-id))))

(defn sentence-tree-level [sentences sentence-id active-sentence-id parent-id]
(let [{:sentence/keys [children]} (sentences sentence-id)]
Expand Down
44 changes: 11 additions & 33 deletions src/org/motform/multiverse/util.cljs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(ns org.motform.multiverse.util
(:require [clojure.string :as str]))
(:require
[clojure.string :as str]))

;;; Stdlib
;; Stdlib

(defn conj?
"`conj` `x` to `xs` if non-nil, otherwise return `xs`"
Expand All @@ -13,7 +14,7 @@
[xs ys]
(mapv (fn [x y] [x y]) xs ys))

;;; Text formatting
;; Text formatting

(defn title-case
"A simple title case by short list of common stop words."
Expand All @@ -22,38 +23,15 @@
"so" "at" "around" "by" "of" "from" "on"
"with" "to" "without" "after" "and" "how"}]
(as-> title $
(str/trim $)
(str/split $ #" ")
(mapv #(if-not (stop-words %) (str/capitalize %) %) $)
(update $ 0 str/capitalize) ; always capitalize the leading word
(str/join " " $))))
(str/trim $)
(str/split $ #" ")
(mapv #(if-not (stop-words %) (str/capitalize %) %) $)
(update $ 0 str/capitalize) ; always capitalize the leading word
(str/join " " $))))

;;; DB helpers
;; Graphical elements

(defn children
([db parent-id] (children db parent-id nil))
([db parent-id story-id]
(let [story-id (or story-id (get-in db [:db/state :story/active]))]
(select-keys (get-in db [:db/stories story-id :story/sentences])
(get-in db [:db/stories story-id :story/sentences parent-id :sentence/children])))))

(defn completion-data [db]
(let [story-id (get-in db [:db/state :story/active])
parent-id (get-in db [:db/stories story-id :story/meta :sentence/active])
api-key (get-in db [:db/state :open-ai/key :open-ai/api-key])]
{:story-id story-id
:parent-id parent-id
:api-key api-key}))

(defn paragraph [db story-id sentence-id]
(reduce
(fn [sentences id]
(conj sentences (get-in db [:db/stories story-id :story/sentences id])))
[] (get-in db [:db/stories story-id :story/sentences sentence-id :sentence/path])))

;;; Graphical elements

(defn spinner []
(defn Spinner []
[:div.v-stack.centered.spinner-container
[:svg {:height 30
:width 80}
Expand Down

0 comments on commit 30fdd65

Please sign in to comment.