|
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