diff --git a/deps.edn b/deps.edn index 400174a..7d0dead 100644 --- a/deps.edn +++ b/deps.edn @@ -6,7 +6,8 @@ io.replikativ/kabel {:mvn/version "0.2.2"} http-kit/http-kit {:mvn/version "2.7.0"} metosin/reitit {:mvn/version "0.7.0-alpha7"} - compojure/compojure {:mvn/version "1.7.1"} + io.github.nextjournal/markdown {:mvn/version "0.5.148"} + hiccup/hiccup {:mvn/version "2.0.0-RC3"} ring/ring-jetty-adapter {:mvn/version "1.12.0"} etaoin/etaoin {:mvn/version "1.0.40"} missionary/missionary {:mvn/version "b.34"} diff --git a/resources/default_schema.edn b/resources/default_schema.edn index f12187c..12fce83 100644 --- a/resources/default_schema.edn +++ b/resources/default_schema.edn @@ -57,7 +57,7 @@ {:db/ident :message/text :db/valueType :db.type/string :db/cardinality :db.cardinality/one} - {:db/ident :message/tag + {:db/ident :message/link :db/valueType :db.type/string :db/cardinality :db.cardinality/many} @@ -80,7 +80,7 @@ {:db/ident :conversation/summary :db/valueType :db.type/string :db/cardinality :db.cardinality/one} - {:db/ident :conversation/tag + {:db/ident :conversation/link :db/valueType :db.type/string :db/cardinality :db.cardinality/many} {:db/ident :conversation/message diff --git a/resources/prompts/assistance.txt b/resources/prompts/assistance.txt index e73b79d..2d5aa1b 100644 --- a/resources/prompts/assistance.txt +++ b/resources/prompts/assistance.txt @@ -3,12 +3,12 @@ You are simmie_beta, a chat bot. Answer to the conversation with strong priority You have access to the following external function calls that you must use in each of these cases: If the user asks for a piece of information that is not available in context conduct a web search to get more information by answering with WEBSEARCH('your search terms'). If you think can derive precise search terms feel free to do preemptive web searches if it will advance the conversation. If the user wants to imagine or picture an idea, answer with IMAGEGEN('your prompt'). -If the user wants to add an issue/todo, answer with ADD_ISSUE('issue title') and it will be added to the chat as well. -If the user wants to remove an issue/todo, answer with REMOVE_ISSUE('issue title') and it will be added to the chat as well. +If the user wants to add an issue/todo, answer with ADD_ISSUE('issue title') for each issue and it will be added to the chat as well. +If the user wants to remove an issue/todo, answer with REMOVE_ISSUE('issue title') for each issue and it will be added to the chat as well. If the user wants to see or list the issues/todos, answer LIST_ISSUES() to retrieve all of them from your database. If the user wants to get the notes from the chat sent, answer SEND_NOTES() to zip them and send them to the chat. -If the suer wants to retrieve a note, answer RETRIEVE_NOTE('note title') to send it to the chat. -If the suer wants to list the notes, answer LIST_NOTES() to send it to the chat. +If the user wants to retrieve a note, answer RETRIEVE_NOTE('note title') to send it to the chat. +If the user wants to list the notes, answer LIST_NOTES() to point the user to the chat's website. If there seems no reply necessary right now to the last message, add 'QUIET' to the message. If the user asks about your abilities, explain these abilities intuitively in context of the conversation. When one of the users comes back after more than a few hours, greet them friendly and add DAILY to the response at the end. diff --git a/resources/prompts/note.txt b/resources/prompts/note.txt index e575342..03b06b3 100644 --- a/resources/prompts/note.txt +++ b/resources/prompts/note.txt @@ -2,7 +2,7 @@ Title: %s Body:%s -Given the note above on the subect, update it in light of the following conversation summary and return the new note body only. References to entities (events, places, people, organisations, businesses, academic topics, everyday topics, etc.) are syntactically expressed with double brackets in RoamResearch or logseq syntax, e.g. [[some topic][This topic is]] or [[Wikipedia]]. Make sure you retain these references. Be brief and succinct while keeping important facts, focus on the topic of the title *only* and rely on the references for the rest of the context to be provided in these notes. Use nested Emacs org-mode lists with '*' nesting for the note. If you do not want to update the note, write SKIP. +Given the note above on the subect, update it in light of the following conversation summary and return the new note body only. References to entities (events, places, people, organisations, businesses, academic topics, everyday topics, etc.) are syntactically expressed as Wikipedia style internal links with double brackets, e.g. [[peter][my friend peter]] or [[peter]]. Make sure you retain these references. Be brief and succinct while keeping important facts, focus on the topic of the title *only* and rely on the references for the rest of the context to be provided in these notes. Use Markdown with LaTeX support for formulas. Make full use of Markdown to lay out the note well, but prefer nested lists of bullet points to paragraphs. If you do not want to update the note, write SKIP. %s diff --git a/src/ie/simm/db.clj b/src/ie/simm/db.clj index f401925..9ec8d69 100644 --- a/src/ie/simm/db.clj +++ b/src/ie/simm/db.clj @@ -42,12 +42,12 @@ (map (fn [[d f l n t]] (str d " " f " " l " (" n "): " (str/replace t #"\n" " ")))) (str/join "\n"))) -(defn extract-tags [text] +(defn extract-links [text] (vec (distinct (map second (re-seq #"\[\[([^\[\]]+)\](\[.+\])?\]" text))))) (defn msg->txs [message] (let [{:keys [message_id from chat date text]} message - tags (when text (extract-tags text))] + tags (when text (extract-links text))] (vec (concat (when from @@ -84,7 +84,7 @@ (when text {:message/text text}) (when (seq tags) - {:message/tag tags}))])))) + {:message/link tags}))])))) (def window-size 10) diff --git a/src/ie/simm/runtimes/assistance.clj b/src/ie/simm/runtimes/assistance.clj index 3d49045..42eec82 100644 --- a/src/ie/simm/runtimes/assistance.clj +++ b/src/ie/simm/runtimes/assistance.clj @@ -8,7 +8,7 @@ [ie.simm.languages.browser :refer [extract-body]] [ie.simm.languages.chat :refer [send-text! send-photo! send-document!]] [ie.simm.prompts :as pr] - [ie.simm.db :refer [ensure-conn conversation extract-tags msg->txs window-size]] + [ie.simm.db :refer [ensure-conn conversation extract-links msg->txs window-size]] [superv.async :refer [? put? go-for] :as sasync] [clojure.core.async :refer [chan pub sub mult tap timeout] :as async] [taoensso.timbre :refer [debug info warn error]] @@ -16,7 +16,10 @@ [hasch.core :refer [uuid]] [clojure.string :as str] [clojure.java.io :as io] - [etaoin.api :as e]) + [hiccup.core :as h] + [nextjournal.markdown :as md] + [nextjournal.markdown.transform :as md.transform] + [nextjournal.markdown.parser :as md.parser]) (:import [java.util.zip ZipEntry ZipOutputStream])) (defn summarize [S conn conv chat] @@ -34,7 +37,7 @@ (sort-by first) (take-last window-size) (map second)) - note-titles (extract-tags summarization) + note-titles (extract-links summarization) _ (debug "=========================== CREATING NOTES ===============================") new-notes (

Notes

Download")})}] + (let [conn (ensure-conn peer chat-id)] + {:status 200 + :body (h/html + [:html + [:head + [:meta {:charset "utf-8"}] + [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}] + [:link {:href "https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css" :rel "stylesheet" :type "text/css"}] + [:link {:href "https://fonts.bunny.net" :rel "preconnect"}] + [:link {:href "https://fonts.bunny.net/css?family=fira-mono:400,700%7Cfira-sans:400,400i,500,500i,700,700i%7Cfira-sans-condensed:700,700i%7Cpt-serif:400,400i,700,700i" :rel "stylesheet" :type "text/css"}] + [:title "Notes"] + [:link {:rel "stylesheet" :href "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.3/css/bulma.min.css"}]] + [:body + [:div {:class "flex"} + [:h1 "Notes"] + [:a {:href (str "/download/chat/" chat-id "/notes.zip")} "Download"] + [:ul (map (fn [[f]] [:li [:a {:href (str "/notes/" chat-id "/" f)} f]]) + (d/q '[:find ?t :where [?n :note/title ?t]] @conn))]]]])}))}] ;; access each individual node link as referenced above ["/notes/:chat-id/:note" {:get (fn [{{:keys [chat-id note]} :path-params}] - {:status 200 - :body (slurp (io/file (str "notes/" chat-id "/" note)))})}]]] + (let [conn (ensure-conn peer chat-id) + body (:note/body (d/entity @conn [:note/title note]))] + {:status 200 + :body + (h/html + [:html + [:head + [:meta {:charset "utf-8"}] + [:meta {:name "viewport" :content "width=device-width, initial-scale=1"}] + [:link {:href "https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css" :rel "stylesheet" :type "text/css"}] + [:link {:href "https://fonts.bunny.net" :rel "preconnect"}] + [:link {:href "https://fonts.bunny.net/css?family=fira-mono:400,700%7Cfira-sans:400,400i,500,500i,700,700i%7Cfira-sans-condensed:700,700i%7Cpt-serif:400,400i,700,700i" :rel "stylesheet" :type "text/css"}] + [:title note] + [:link {:rel "stylesheet" :href "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.3/css/bulma.min.css"}]] + [:body + [:div {:class "flex"} + [:h1 note] + (if (string? body) + (md.transform/->hiccup (md/parse (update md.parser/empty-doc :text-tokenizers concat [md.parser/internal-link-tokenizer md.parser/hashtag-tokenizer]) + body)) + "Note does not exist yet.")]]])}))}]]] (swap! peer assoc-in [:http :routes :assistance] routes) ;; we will continuously interpret the messages (go-loop-try S [m (txs window-size]] + [ie.simm.db :refer [ensure-conn conversation extract-links msg->txs window-size]] [superv.async :refer [? put? go-for] :as sasync] [clojure.core.async :refer [chan pub sub mult tap timeout] :as async] [taoensso.timbre :refer [debug info warn error]] @@ -34,7 +34,7 @@ (sort-by first) (take-last window-size) (map second)) - note-titles (extract-tags summarization) + note-titles (extract-links summarization) _ (debug "=========================== CREATING NOTES ===============================") new-notes ( (t/get-file token file_id) :result :file_path) - local-path (str "downloads/telegram/" file-path ".oga") + local-path (str "downloads/telegram/" id "/voice/" file-path ".oga") _ (io/make-parents local-path) _ (io/copy (:body (http/get (str "https://api.telegram.org/file/bot" token "/" file-path) {:as :byte-array})) (io/file local-path))] local-path)))) (defn server [peer in] - (let [telegram-routes (routes - (POST "/telegram-callback" {body :body} - (let [msg (-> body slurp (json/read-value json/keyword-keys-object-mapper) :message) - _ (debug "received telegram message:" msg) - msg (fetch-voice! msg) - m {:type ::message - :request-id (uuid) - :msg msg}] - (put? S in m) - {:body "Thanks!"})) - (route/not-found "Not Found")) - telegram-routes [["/telegram-callback" {:post + (let [telegram-routes [["/telegram-callback" {:post (fn [{:keys [body]}] (let [msg (-> body slurp (json/read-value json/keyword-keys-object-mapper) :message)] (debug "received telegram message:" msg) (put? S in {:type ::message :request-id (uuid) :msg (fetch-voice! msg)}) - {:status 200 :body "Success."})) - #_{:parameters {:body [:map]} - :responses {200 {:body [:map]}} - :handler _}}]] - _ (debug "created telegram routes") - ;;server (run-jetty telegram-routes {:port 8080 :join? false}) - ] + {:status 200 :body "Success."}))}]] + _ (debug "created telegram routes") ] (swap! peer assoc-in [:http :routes :telegram] telegram-routes) #(fn []))) diff --git a/src/ie/simm/runtimes/text_extractor.clj b/src/ie/simm/runtimes/text_extractor.clj index f5639df..2c8ee55 100644 --- a/src/ie/simm/runtimes/text_extractor.clj +++ b/src/ie/simm/runtimes/text_extractor.clj @@ -30,7 +30,7 @@ (defn extract-url [S text chat] (go-try S (if-let [;; if text matches http or https web URL extrect URL with regex - url (re-find #"https?://\S+" text)] + url (if text (re-find #"https?://\S+" text) "")] (if-let [;; extract youtube video id from URL youtube-id (second (or (re-find #"youtube.com/watch\?v=([^&]+)" url) (re-find #"youtu.be/([^\?]+)" url)))]