From f6fdbd52a084fbff62f9c2e2e614ecdac9077af6 Mon Sep 17 00:00:00 2001 From: Bryce Date: Sun, 13 Aug 2023 20:10:27 -0700 Subject: [PATCH] better insights. --- src/clj/auto_ap/ssr/transaction/insights.clj | 196 ++++++++++--------- 1 file changed, 104 insertions(+), 92 deletions(-) diff --git a/src/clj/auto_ap/ssr/transaction/insights.clj b/src/clj/auto_ap/ssr/transaction/insights.clj index afe935a6..f7ba116e 100644 --- a/src/clj/auto_ap/ssr/transaction/insights.clj +++ b/src/clj/auto_ap/ssr/transaction/insights.clj @@ -54,62 +54,115 @@ (#(if after (drop 1 %) %)) - (take 200) + (take 50) (into [])))) +(defn get-pinecone [transaction-id] + (-> + (http/get (-> "https://transactions-a8257ba.svc.us-west4-gcp-free.pinecone.io/vectors/fetch" + url/url + (assoc :query {:ids transaction-id}) + str) + {:headers {"Api-Key" "f2d3a78e-bcea-4fcd-88b6-2527b8423607"} + :as :json + :keywordize? false}) + :body + :vectors + ((keyword (str transaction-id))) + :values)) + +(defn get-pinecone-similarities [transaction-id] + (filter + (fn [{:keys [score]}] + (> score 0.95) + ) + (-> + (http/post (-> "https://transactions-a8257ba.svc.us-west4-gcp-free.pinecone.io/query" + url/url + str) + {:headers {"Api-Key" "f2d3a78e-bcea-4fcd-88b6-2527b8423607"} + :form-params {"vector" (get-pinecone transaction-id) + "topK" 100, + "includeMetadata" true + "namespace" ""} + :content-type :json + :as :json}) + :body + :matches))) + +(defn pinecone-similarity-list [transaction-id] + (for [{{:keys [amount date description vendor]} :metadata score :score id :id} (get-pinecone-similarities transaction-id) + :let [vendor-name (:vendor/name (:transaction/vendor (dc/pull (dc/db conn) [{:transaction/vendor [:vendor/name]} ] (Long/parseLong id)))) + account-code (-> (dc/pull (dc/db conn) [{:transaction/accounts [{:transaction-account/account [:account/numeric-code]}]} ] (Long/parseLong id)) + :transaction/accounts + first + :transaction-account/account + :account/numeric-code)] + :when (or vendor-name account-code)] + {:vendor-name vendor-name + :numeric-code account-code + :amount amount + :date date + :description description})) + + (defn transaction-row [r & {:keys [hide-actions? class last?]}] - (com/data-grid-row - (cond-> {:class class} - last? (assoc :hx-get (bidi/path-for ssr-routes/only-routes - :transaction-insight-rows - :after (:db/id r)) - :hx-trigger "intersect once" - :hx-indicator "#insight-table" - :hx-swap "afterend")) - (com/data-grid-cell {} (:client/code (:transaction/client r))) - (com/data-grid-cell {} (:bank-account/code (:transaction/bank-account r))) - (com/data-grid-cell {} (some-> (:transaction/date r) coerce/to-date-time (atime/unparse-local atime/normal-date))) + (let [simality-list (try (pinecone-similarity-list (:db/id r)) (catch Exception e + []))] + (com/data-grid-row + (cond-> {:class class} + last? (assoc :hx-get (bidi/path-for ssr-routes/only-routes + :transaction-insight-rows + :after (:db/id r)) + :hx-trigger "intersect once" + :hx-indicator "#insight-table" + :hx-swap "afterend")) + (com/data-grid-cell {} (:client/code (:transaction/client r))) + (com/data-grid-cell {} (:bank-account/code (:transaction/bank-account r))) + (com/data-grid-cell {} (some-> (:transaction/date r) coerce/to-date-time (atime/unparse-local atime/normal-date))) - (com/data-grid-cell {} (str (:transaction/description-original r))) - (com/data-grid-cell {} - (if (> (:transaction/amount r) 0.0) - [:div.tag.is-success.is-light (str "$" (Math/round (:transaction/amount r)))] - [:div.tag.is-danger.is-light (str "$" (Math/round (:transaction/amount r)))])) - (com/data-grid-cell {:style {:width "12em"}} - [:div.flex.gap-2.flex-wrap {:style {:width "12em"}} - #_(com/pill {:color :primary} (:vendor/name (:transaction/recommended-vendor r))) - #_(com/pill {:color :secondary} (str (:account/numeric-code (:transaction/recommended-account r)) " - " (:account/name (:transaction/recommended-account r)))) - #_(com/pill {:class (cond - (> (:transaction/account-confidence r) 0.90) - "is-success is-light" - (> (:transaction/account-confidence r) 0.80) - "is-info is-light" + (com/data-grid-cell {} (str (:transaction/description-original r))) + (com/data-grid-cell {} + (if (> (:transaction/amount r) 0.0) + [:div.tag.is-success.is-light (str "$" (Math/round (:transaction/amount r)))] + [:div.tag.is-danger.is-light (str "$" (Math/round (:transaction/amount r)))])) + (com/data-grid-cell {:style {:width "12em"}} + [:div.flex.gap-2.flex-wrap {:style {:width "12em"}} + (when-let [vendor-name (:vendor-name (first simality-list))] + (com/pill {:color :primary} vendor-name)) + (when-let [numeric-code (:numeric-code (first simality-list))] + (com/pill {:color :secondary} numeric-code)) + #_(com/pill {:class (cond + (> (:transaction/account-confidence r) 0.90) + "is-success is-light" + (> (:transaction/account-confidence r) 0.80) + "is-info is-light" - :else - "is-warning is-light")} (str "%" (Math/round (* 100.0 (:transaction/account-confidence r)))))]) - (com/data-grid-right-stack-cell {} - (when-not hide-actions? - [:form.flex.gap-2 - [:input {:type :hidden :name "id" :value (:db/id r)}] - (com/icon-button {:hx-post (bidi/path-for ssr-routes/only-routes - :transaction-insight-approve + :else + "is-warning is-light")} (str "%" (Math/round (* 100.0 (:transaction/account-confidence r)))))]) + (com/data-grid-right-stack-cell {} + (when-not hide-actions? + [:form.flex.gap-2 + [:input {:type :hidden :name "id" :value (:db/id r)}] + (com/icon-button {:hx-post (bidi/path-for ssr-routes/only-routes + :transaction-insight-approve + :transaction-id (:db/id r)) + :hx-target "closest tr" + :color :primary-light} + svg/thumbs-up) + (com/icon-button {:hx-delete (bidi/path-for ssr-routes/only-routes + :transaction-insight-disapprove + :transaction-id (:db/id r)) + :hx-target "closest tr" + :color :danger-light} + svg/thumbs-down) + (com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes + :transaction-insight-explain :transaction-id (:db/id r)) - :hx-target "closest tr" - :color :primary-light} - svg/thumbs-up) - (com/icon-button {:hx-delete (bidi/path-for ssr-routes/only-routes - :transaction-insight-disapprove - :transaction-id (:db/id r)) - :hx-target "closest tr" - :color :danger-light} - svg/thumbs-down) - (com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes - :transaction-insight-explain - :transaction-id (:db/id r)) - :hx-target "#modal-holder" - :hx-swap "outerHTML"} - svg/question)])))) + :hx-target "#modal-holder" + :hx-swap "outerHTML"} + svg/question)]))))) (defn approve [{:keys [identity session] {:keys [transaction-id]} :route-params}] (let [approval-details (dc/pull (dc/db conn) [{:transaction/recommended-account [:account/location :db/id]} @@ -153,40 +206,6 @@ :auto-remove? true :hide-actions? true :class "live-removed")))) - -(defn get-pinecone [transaction-id] - (-> - (http/get (-> "https://transactions-a8257ba.svc.us-west4-gcp-free.pinecone.io/vectors/fetch" - url/url - (assoc :query {:ids transaction-id}) - str) - {:headers {"Api-Key" "f2d3a78e-bcea-4fcd-88b6-2527b8423607"} - :as :json - :keywordize? false}) - :body - :vectors - ((keyword (str transaction-id))) - :values)) - -(defn get-pinecone-similarities [transaction-id] - (filter - (fn [{:keys [score]}] - (> score 0.95) - ) - (-> - (http/post (-> "https://transactions-a8257ba.svc.us-west4-gcp-free.pinecone.io/query" - url/url - str) - {:headers {"Api-Key" "f2d3a78e-bcea-4fcd-88b6-2527b8423607"} - :form-params {"vector" (get-pinecone transaction-id) - "topK" 100, - "includeMetadata" true - "namespace" ""} - :content-type :json - :as :json}) - :body - :matches))) - (defn explain [{:keys [identity session] {:keys [transaction-id]} :route-params}] (let [r (dc/pull (dc/db conn) pull-expr @@ -216,20 +235,13 @@ [:th] [:th.text-left ]] (take 10 - (for [{{:keys [amount date description vendor]} :metadata score :score id :id} similar - :let [vendor-name (:vendor/name (:transaction/vendor (dc/pull (dc/db conn) [{:transaction/vendor [:vendor/name]} ] (Long/parseLong id)))) - account-code (-> (dc/pull (dc/db conn) [{:transaction/accounts [{:transaction-account/account [:account/numeric-code]}]} ] (Long/parseLong id)) - :transaction/accounts - first - :transaction-account/account - :account/numeric-code)] - :when (or vendor-name account-code)] + (for [{{:keys [amount date description vendor-name numeric-code]} :metadata score :score id :id} (pinecone-similarity-list transaction-id)] [:tr [:td (subs date 0 10)] [:td description] [:td amount] [:td vendor-name] - [:td account-code] + [:td numeric-code] [:td (format "%.1f%%" (* 100 (double score)))]]))]] [:div])))))