|
1 | 1 | (ns init |
2 | 2 | (:require |
3 | | - [babashka.fs :as fs] |
4 | 3 | [cheshire.core :as json] |
5 | | - [clojure.java.io :as io] |
6 | | - [clojure.string :as string])) |
7 | | - |
8 | | -(defn- item [graph item] |
9 | | - (let [{:keys [type] :as m} (json/parse-string item keyword)] |
10 | | - (case type |
11 | | - "entity" (update graph :entities (fnil conj []) m) |
12 | | - "relation" (update graph :relations (fnil conj []) m)))) |
13 | | - |
14 | | -(def db-file "/memory/memory.json") |
15 | | -#_(def db-file "memory.json") |
16 | | - |
17 | | -(defn- load-graph [] |
18 | | - (try |
19 | | - (->> (line-seq (io/reader db-file)) |
20 | | - (reduce item {})) |
21 | | - (catch Throwable _ |
22 | | - {:entities [] |
23 | | - :relations []}))) |
24 | | - |
25 | | -(defn- save-graph [graph] |
26 | | - (spit |
27 | | - db-file |
28 | | - (->> |
29 | | - (concat |
30 | | - (->> (:entities graph) |
31 | | - (map #(assoc % :type "entity")) |
32 | | - (map json/generate-string)) |
33 | | - (->> (:relations graph) |
34 | | - (map #(assoc % :type "relation")) |
35 | | - (map json/generate-string))) |
36 | | - (string/join "\n")))) |
37 | | - |
38 | | -(comment |
39 | | - (fs/delete db-file) |
40 | | - (save-graph |
41 | | - (load-graph))) |
42 | | - |
43 | | -(defn- entity? [graph e] |
44 | | - (some #(= (:name e) (:name %)) (:entities graph))) |
45 | | - |
46 | | -;; must have names |
47 | | -(defn create-entities [{:keys [entities]}] |
48 | | - (let [graph (load-graph) |
49 | | - new-entities (->> entities |
50 | | - (filter |
51 | | - (complement (partial entity? graph))))] |
52 | | - (save-graph (update graph :entities concat new-entities)) |
53 | | - new-entities)) |
54 | | - |
55 | | -(comment |
56 | | - (create-entities {:entities [{:name "me"} {:name "rod"}]})) |
57 | | - |
58 | | -(defn- relation? [graph e] |
59 | | - (some |
60 | | - #(and |
61 | | - (= (:from e) (:from %)) |
62 | | - (= (:to e) (:to %)) |
63 | | - (= (:relationType e) (:relationType %))) |
64 | | - (:relations graph))) |
65 | | - |
66 | | -;; must have from, to, and relationType |
67 | | -(defn create-relations [{:keys [relations]}] |
68 | | - (let [graph (load-graph) |
69 | | - new-relations (->> relations |
70 | | - (filter |
71 | | - (complement |
72 | | - (partial relation? graph))))] |
73 | | - (save-graph (update graph :relations (fnil concat []) new-relations)) |
74 | | - new-relations)) |
75 | | - |
76 | | -(comment |
77 | | - (create-relations {:relations [{:from "me" :to "rod" :relationType "friend"}]}) |
78 | | - (load-graph)) |
79 | | - |
80 | | -(defn- add-observation [agg {:keys [entityName contents]}] |
81 | | - (if-let [[n entity] (some |
82 | | - (fn [[_ m :as v]] (when (= entityName (:name m)) v)) |
83 | | - (->> (-> agg :graph :entities) |
84 | | - (interleave (range)) |
85 | | - (partition 2)))] |
86 | | - (let [new-observations (->> contents |
87 | | - (filter (complement #(some (partial = %) (:observations entity)))))] |
88 | | - (-> agg |
89 | | - (update :results conj {:entityName entityName :addedObservations new-observations}) |
90 | | - (update :graph update-in [:entities n :observations] (fnil concat []) new-observations))) |
91 | | - agg)) |
92 | | - |
93 | | -(comment |
94 | | - (add-observation |
95 | | - {:graph {:entities [{:name "me"} {:name "rod"}]}} |
96 | | - {:entityName "me" :contents ["fact"]})) |
97 | | - |
98 | | -;; observations are a list of entityName contents maps - contents are string arrays |
99 | | -(defn add-observations [{:keys [observations]}] |
100 | | - (let [graph (load-graph) |
101 | | - {:keys [results graph]} (->> observations |
102 | | - (reduce |
103 | | - add-observation |
104 | | - {:graph graph :results []}))] |
105 | | - (save-graph graph) |
106 | | - results)) |
107 | | - |
108 | | -(comment |
109 | | - (add-observations |
110 | | - {:observations |
111 | | - [{ :entityName "me" :contents [ "my personal email is [email protected]"]} |
112 | | - {:entityName "rod" :contents ["Rod is in Sydney, Australia"]}]}) |
113 | | - (load-graph)) |
114 | | - |
115 | | -(defn delete-entities [{:keys [entityNames]}] |
116 | | - (let [entity? (into #{} entityNames) |
117 | | - relation? (fn [{:keys [from to]}] (or (entity? from) (entity? to)))] |
118 | | - (save-graph |
119 | | - (-> (load-graph) |
120 | | - (update :entities (fn [coll] (filter (complement #(entity? (:name %))) coll))) |
121 | | - (update :relations (fn [coll] (filter (complement #(relation? %)) coll))))))) |
122 | | - |
123 | | -(comment |
124 | | - (do |
125 | | - (fs/delete db-file) |
126 | | - (create-entities {:entities [{:name "me"} {:name "rod"}]}) |
127 | | - (create-relations {:relations [{:from "me" :to "rod" :relationType "friend"}]}) |
128 | | - (add-observations |
129 | | - {:observations |
130 | | - [{ :entityName "me" :contents [ "my personal email is [email protected]"]} |
131 | | - {:entityName "rod" :contents ["Rod is in Sydney, Australia"]}]}) |
132 | | - (load-graph)) |
133 | | - |
134 | | - (delete-entities {:entityNames ["rod"]}) |
135 | | - (load-graph)) |
136 | | - |
137 | | -(defn delete-observation [coll {:keys [entityName observations]}] |
138 | | - (->> coll |
139 | | - (map (fn [m] |
140 | | - (if (= entityName (:name m)) |
141 | | - (update m :observations (fn [obs] (remove (into #{} observations) obs))) |
142 | | - m))))) |
143 | | - |
144 | | -(defn delete-observations [{:keys [deletions]}] |
145 | | - (save-graph |
146 | | - (-> (load-graph) |
147 | | - (update :entities (fn [entities] (reduce delete-observation entities deletions)))))) |
148 | | - |
149 | | -(comment |
150 | | - (do |
151 | | - (fs/delete db-file) |
152 | | - (create-entities {:entities [{:name "me"} {:name "rod"}]}) |
153 | | - (create-relations {:relations [{:from "me" :to "rod" :relationType "friend"}]}) |
154 | | - (add-observations |
155 | | - {:observations |
156 | | - [{ :entityName "me" :contents [ "my personal email is [email protected]"]} |
157 | | - {:entityName "rod" :contents ["Rod is in Sydney, Australia"]}]}) |
158 | | - (load-graph)) |
159 | | - |
160 | | - (delete-observations {:deletions [{:entityName "rod" :observations ["Rod is in Sydney, Australia"]}]}) |
161 | | - (load-graph)) |
162 | | - |
163 | | -(defn delete-relation [coll {:keys [from to relationType]}] |
164 | | - (remove (fn [m] (and |
165 | | - (= from (:from m)) |
166 | | - (= to (:to m)) |
167 | | - (= relationType (:relationType m)))) coll)) |
168 | | - |
169 | | -(defn delete-relations [{:keys [relations]}] |
170 | | - (save-graph |
171 | | - (-> (load-graph) |
172 | | - (update :relations (fn [coll] (reduce delete-relation coll relations)))))) |
173 | | - |
174 | | -(defn entity-matches? [q entity] |
175 | | - (or |
176 | | - (string/includes? (-> entity :name string/lower-case) q) |
177 | | - (try (string/includes? (-> entity :entityType string/lower-case) q) (catch Throwable _ false)) |
178 | | - (try (some #(string/includes? (string/lower-case %) q) (:observations entity)) (catch Throwable _ false)))) |
179 | | - |
180 | | -(defn search-nodes [{:keys [query]}] |
181 | | - (let [graph (load-graph) |
182 | | - filtered-entities (filter (partial entity-matches? (string/lower-case query)) (:entities graph)) |
183 | | - filtered-entity-names (->> filtered-entities (map :name) (into #{}))] |
184 | | - {:entities filtered-entities |
185 | | - :relations (filter |
186 | | - #(and (filtered-entity-names (:from %)) (filtered-entity-names (:to %))) |
187 | | - (:relations graph))})) |
188 | | - |
189 | | -(defn open-nodes [{:keys [names]}] |
190 | | - (let [graph (load-graph) |
191 | | - entity-names (into #{} names) |
192 | | - filtered-entities (filter (comp entity-names :name) (:entities graph)) |
193 | | - filtered-entity-names (->> filtered-entities (map :name) (into #{}))] |
194 | | - {:entities filtered-entities |
195 | | - :relations (filter |
196 | | - #(and (filtered-entity-names (:from %)) (filtered-entity-names (:to %))) |
197 | | - (:relations graph))})) |
198 | | - |
199 | | -(comment |
200 | | - (do |
201 | | - (fs/delete db-file) |
202 | | - (create-entities {:entities [{:name "me"} {:name "rod"}]}) |
203 | | - (create-relations {:relations [{:from "me" :to "rod" :relationType "friend"}]}) |
204 | | - (add-observations |
205 | | - {:observations |
206 | | - [{ :entityName "me" :contents [ "my personal email is [email protected]"]} |
207 | | - {:entityName "rod" :contents ["Rod is in Sydney, Australia"]}]}) |
208 | | - (load-graph)) |
209 | | - |
210 | | - (search-nodes {:query "rod"}) |
211 | | - (open-nodes {:names ["me" "rod"]}) |
212 | | - (load-graph)) |
| 4 | + [memory]) |
| 5 | + (:import |
| 6 | + [clojure.lang ExceptionInfo])) |
213 | 7 |
|
214 | 8 | (try |
215 | 9 | (let [[s raw-json-string] *command-line-args* |
216 | 10 | m (json/parse-string raw-json-string true)] |
217 | 11 | (println |
218 | | - ((get (ns-publics 'init) (symbol s)) m))) |
| 12 | + ((get (ns-publics 'memory) (symbol s)) m))) |
| 13 | + (catch ExceptionInfo e |
| 14 | + (println (ex-message e)) |
| 15 | + (System/exit 1)) |
219 | 16 | (catch Throwable t |
220 | 17 | (binding [*out* *err*] |
221 | | - (println (str "Error: " (.getMessage t))) |
| 18 | + (println (str "Error: " t)) |
222 | 19 | (System/exit 1)))) |
223 | 20 |
|
0 commit comments