Skip to content

Commit a647745

Browse files
Add README.md on /thread volume
1 parent 6f38c6d commit a647745

File tree

3 files changed

+41
-23
lines changed

3 files changed

+41
-23
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ Prompts are fetched from a GitHub repository. The mandatory parts of the ref ar
9393
but optional `path` and `ref` can be added to pull prompts from branches, and to specify a subdirectory
9494
where the prompt files are located in the repo.
9595

96+
## Function volumes
97+
98+
Every function container will have a shared volume mounted into the container at `/thread`.
99+
The volume is intended to be ephemeral and will be deleted at the end of the run. However, the volume
100+
can be saved for inspection by passing the argument `--save-thread-volume`. The name of the shared volume
101+
can also be controlled using `--thread-id <name>` but will normally just be a guid.
102+
96103
## Output json-rpc notifications
97104

98105
Add the flag `--jsonrpc` to the list of arguments to switch the stdout stream to be a series of `jsonrpc` notifications.

src/docker.clj

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@
9191
:headers {"Content-Type" "application/json"
9292
"Content-Length" (count payload)}})))
9393

94-
(defn create-volume [{:keys [thread-volume-name]}]
94+
(defn create-volume [{:keys [Name]}]
9595
(curl/post "http://localhost/volumes/create"
9696
{:raw-args ["--unix-socket" "/var/run/docker.sock"]
9797
:throw false
98-
:body (json/generate-string {:Name thread-volume-name})
98+
:body (json/generate-string {:Name Name})
9999
:headers {"Content-Type" "application/json"}}))
100100

101-
(defn remove-volume [{:keys [thread-volume-name]}]
102-
(curl/delete (format "http://localhost/volumes/%s" thread-volume-name)
101+
(defn remove-volume [{:keys [Name]}]
102+
(curl/delete (format "http://localhost/volumes/%s" Name)
103103
{:raw-args ["--unix-socket" "/var/run/docker.sock"]
104104
:throw false}))
105105

@@ -178,15 +178,13 @@
178178
(pull (assoc m :creds {:username (:user m)
179179
:password (or (:pat m) (creds/credential-helper->jwt))
180180
:serveraddress "https://index.docker.io/v1/"})))
181-
(when (:thread-volume m) (thread-volume m))
182181
(let [x (create m)]
183182
(start x)
184183
(wait x)
185184
;; body is raw PTY output
186185
(let [s (:body (attach x))
187186
info (inspect x)]
188187
(delete x)
189-
(when (and (:thread-volume m) (not (true? (:save-thread-volume m)))) (delete-thread-volume m))
190188
{:pty-output s
191189
:exit-code (-> info :State :ExitCode)
192190
:info info})))

src/prompts.clj

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
function-name - the name of the function that the LLM has selected
160160
json-arg-string - the JSON arg string that the LLM has generated
161161
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]}]
163163
(if-let [definition (->
164164
(->> (filter #(= function-name (-> % :function :name)) functions)
165165
first)
@@ -175,21 +175,23 @@
175175
(if json-arg-string [json-arg-string] ["{}"])
176176
(when-let [c (-> definition :container :command)] c))}
177177
(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}))
181179
{:keys [pty-output exit-code]} (docker/run-function function-call)]
182180
(if (= 0 exit-code)
183181
(resolve pty-output)
184182
(fail (format "call exited with non-zero code (%d): %s" exit-code pty-output))))
185183
(= "prompt" (:type definition)) ;; asynchronous call to another agent - new conversation-loop
186184
;; TODO set a custom map for prompts in the next conversation loop
187185
(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])))]
193195
(jsonrpc/notify :message {:debug (with-out-str (pprint m))})
194196
(resolve (->> messages
195197
(filter #(= "assistant" (:role %)))
@@ -208,7 +210,7 @@
208210
args for extracting functions, host-dir, user, platform
209211
returns channel that will contain the final set of messages and a finish-reason"
210212
[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
212214
prompt-dir (get-dir prompts-dir)
213215
m (collect-metadata prompt-dir)
214216
functions (collect-functions prompt-dir)
@@ -221,17 +223,16 @@
221223
:platform platform}
222224
(when pat {:pat pat})
223225
(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})))]
227228
(try
228229
(openai/openai
229230
(merge
230231
{:messages prompts}
231232
(when (seq functions) {:tools functions})
232233
(when url {:url url})
233234
m) h)
234-
(catch ConnectException t
235+
(catch ConnectException _
235236
;; when the conversation-loop can not connect to an openai compatible endpoint
236237
(async/>!! c {:messages [{:role "assistant" :content "I cannot connect to an openai compatible endpoint."}]
237238
:finish-reason "error"}))
@@ -262,6 +263,15 @@
262263
(jsonrpc/notify :message {:debug (with-out-str (pprint m))})
263264
{:messages (concat prompts messages) :done finish-reason})))))
264265

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+
265275
(defn- -run-command
266276
" returns map result"
267277
[& args]
@@ -290,9 +300,12 @@
290300
(update-in m [:prompts] (fn [coll] (remove (fn [{:keys [type]}] (= type (second args))) coll)))))
291301

292302
(= "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))
296309

297310
:else
298311
(apply get-prompts args)))

0 commit comments

Comments
 (0)