|
159 | 159 | function-name - the name of the function that the LLM has selected |
160 | 160 | json-arg-string - the JSON arg string that the LLM has generated |
161 | 161 | resolve fail - callbacks" |
162 | | - [{:keys [functions user pat thread-volume save-thread-volume] :as opts} function-name json-arg-string {:keys [resolve fail]}] |
| 162 | + [{:keys [functions user pat thread-id offline] :as opts} function-name json-arg-string {:keys [resolve fail]}] |
163 | 163 | (if-let [definition (-> |
164 | 164 | (->> (filter #(= function-name (-> % :function :name)) functions) |
165 | 165 | first) |
|
175 | 175 | (if json-arg-string [json-arg-string] ["{}"]) |
176 | 176 | (when-let [c (-> definition :container :command)] c))} |
177 | 177 | (when user {:user user}) |
178 | | - (when pat {:pat pat}) |
179 | | - (when thread-volume {:thread-volume thread-volume}) |
180 | | - (when (true? save-thread-volume) {:save-thread-volume true})) |
| 178 | + (when pat {:pat pat})) |
181 | 179 | {:keys [pty-output exit-code]} (docker/run-function function-call)] |
182 | 180 | (if (= 0 exit-code) |
183 | 181 | (resolve pty-output) |
184 | 182 | (fail (format "call exited with non-zero code (%d): %s" exit-code pty-output)))) |
185 | 183 | (= "prompt" (:type definition)) ;; asynchronous call to another agent - new conversation-loop |
186 | 184 | ;; TODO set a custom map for prompts in the next conversation loop |
187 | 185 | (let [{:keys [messages _finish-reason] :as m} |
188 | | - (async/<!! (conversation-loop |
189 | | - (:host-dir opts) |
190 | | - (:user opts) |
191 | | - (:host-dir opts) |
192 | | - (:ref definition)))] |
| 186 | + (async/<!! (apply conversation-loop |
| 187 | + (concat |
| 188 | + [(:host-dir opts) |
| 189 | + (:user opts) |
| 190 | + (:host-dir opts) |
| 191 | + (:ref definition)] |
| 192 | + (when pat [:pat pat]) |
| 193 | + (when offline [:offline true]) |
| 194 | + [:thread-id thread-id])))] |
193 | 195 | (jsonrpc/notify :message {:debug (with-out-str (pprint m))}) |
194 | 196 | (resolve (->> messages |
195 | 197 | (filter #(= "assistant" (:role %))) |
|
208 | 210 | args for extracting functions, host-dir, user, platform |
209 | 211 | returns channel that will contain the final set of messages and a finish-reason" |
210 | 212 | [prompts & args] |
211 | | - (let [[host-dir user platform prompts-dir & {:keys [url pat save-thread-volume thread-id]}] args |
| 213 | + (let [[host-dir user platform prompts-dir & {:keys [url pat save-thread-volume offline thread-id]}] args |
212 | 214 | prompt-dir (get-dir prompts-dir) |
213 | 215 | m (collect-metadata prompt-dir) |
214 | 216 | functions (collect-functions prompt-dir) |
|
221 | 223 | :platform platform} |
222 | 224 | (when pat {:pat pat}) |
223 | 225 | (when save-thread-volume {:save-thread-volume true}) |
224 | | - (if thread-id |
225 | | - {:thread-volume thread-id} |
226 | | - {:thread-volume (str (random-uuid))}))))] |
| 226 | + (when offline {:offline true}) |
| 227 | + {:thread-id thread-id})))] |
227 | 228 | (try |
228 | 229 | (openai/openai |
229 | 230 | (merge |
230 | 231 | {:messages prompts} |
231 | 232 | (when (seq functions) {:tools functions}) |
232 | 233 | (when url {:url url}) |
233 | 234 | m) h) |
234 | | - (catch ConnectException t |
| 235 | + (catch ConnectException _ |
235 | 236 | ;; when the conversation-loop can not connect to an openai compatible endpoint |
236 | 237 | (async/>!! c {:messages [{:role "assistant" :content "I cannot connect to an openai compatible endpoint."}] |
237 | 238 | :finish-reason "error"})) |
|
262 | 263 | (jsonrpc/notify :message {:debug (with-out-str (pprint m))}) |
263 | 264 | {:messages (concat prompts messages) :done finish-reason}))))) |
264 | 265 |
|
| 266 | +(defn- with-volume [f & {:keys [thread-id save-thread-volume]}] |
| 267 | + (let [thread-id (or thread-id (str (random-uuid)))] |
| 268 | + (try |
| 269 | + (docker/thread-volume {:Name thread-id}) |
| 270 | + (f thread-id) |
| 271 | + (finally |
| 272 | + (when (not (true? save-thread-volume)) |
| 273 | + (docker/delete-thread-volume {:Name thread-id})))))) |
| 274 | + |
265 | 275 | (defn- -run-command |
266 | 276 | " returns map result" |
267 | 277 | [& args] |
|
290 | 300 | (update-in m [:prompts] (fn [coll] (remove (fn [{:keys [type]}] (= type (second args))) coll))))) |
291 | 301 |
|
292 | 302 | (= "run" (first args)) |
293 | | - (select-keys |
294 | | - (async/<!! (apply conversation-loop (rest args))) |
295 | | - [:done]) |
| 303 | + (with-volume |
| 304 | + (fn [thread-id] |
| 305 | + (select-keys |
| 306 | + (async/<!! (apply conversation-loop (concat (rest args) [:thread-id thread-id]))) |
| 307 | + [:done])) |
| 308 | + (rest args)) |
296 | 309 |
|
297 | 310 | :else |
298 | 311 | (apply get-prompts args))) |
|
0 commit comments