Skip to content

Commit e39780e

Browse files
Add --input flag
1 parent a5cc926 commit e39780e

File tree

10 files changed

+151
-48
lines changed

10 files changed

+151
-48
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@
1111
/functions/tree-sitter-clj/target/
1212
/functions/tree-sitter-clj/.cpcache/
1313
/.cpcache/
14+
/.nrepl-port
15+
/target/

dev/conversations_t.clj

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
(ns conversations-t
2+
(:require
3+
[babashka.fs :as fs]
4+
[clojure.core.async :as async]
5+
[docker.main :as main]
6+
graph
7+
jsonrpc))
8+
9+
(def opts {:platform "darwin"
10+
:prompts (fs/file "/Users/slim/docker/labs-ai-tools-for-devs/prompts/curl/README.md")
11+
:host-dir "/Users/slim/vonwig/altaservice"})
12+
13+
(alter-var-root
14+
#'jsonrpc/notify
15+
(fn [_] (partial (if (:jsonrpc opts) jsonrpc/-notify jsonrpc/-println) opts)))
16+
17+
(try
18+
(main/with-options opts ["run"])
19+
(catch Throwable t
20+
(println t)))
21+
22+
(def run-command (main/command opts "run"))
23+
24+
(try
25+
(def x (run-command))
26+
(catch Throwable t
27+
(println t)))
28+
29+
(->> (:messages x)
30+
(map :role))
31+
32+
(keys x)
33+
(count (:messages x))
34+
35+
(def y (async/<!! (graph/stream (graph/chat-with-tools opts))))
36+
37+
(count (:messages y))
123 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-

graphs/prompts/pages/jsonrpc.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,10 @@
5050

5151
```json
5252
{"params": {"content": "here is the user prompt"}}
53+
```
54+
- #### exit
55+
56+
Exit the engine
57+
```json
58+
{"params": {}}
5359
```
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- ![graph.png](../assets/graph_1729537135592_0.png)
2+
- ```
3+
nix-store --query --graph ./result > graph.dot
4+
dot -Tpng graph.dot -o graph.png
5+
```
6+
-

src/docker/main.clj

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(ns docker.main
1+
(ns docker.main
22
(:require
33
[babashka.fs :as fs]
44
[cheshire.core :as json]
@@ -12,7 +12,8 @@
1212
graph
1313
jsonrpc
1414
[logging :refer [warn]]
15-
prompts)
15+
prompts
16+
user-loop)
1617
(:gen-class))
1718

1819
(set! *warn-on-reflection* true)
@@ -68,6 +69,7 @@
6869
:id :stream
6970
:assoc-fn (fn [m k _] (assoc m k false))]
7071
[nil "--debug" "add debug logging"]
72+
[nil "--input" "read jsonrpc messages from stdin"]
7173
[nil "--help" "print option summary"]])
7274

7375
(def output-handler (fn [x]
@@ -131,6 +133,12 @@
131133
(warn "Docker Desktop not logged in" {}))
132134
(warn "unable to check Docker Desktop for login" {})))
133135

136+
(defn with-options [opts args]
137+
((validate ::run-args)
138+
(merge
139+
(apply merge-deprecated opts args)
140+
(login-info))))
141+
134142
(defn command [opts & [c :as args]]
135143
(case c
136144
"prompts" (fn []
@@ -142,31 +150,39 @@
142150
"register" (fn []
143151
(if-let [{:keys [owner repo path]} (git/parse-github-ref (second args))]
144152
(registry/update-registry (fn [m]
145-
(update-in m [:prompts] (fnil conj [])
146-
{:type (second args)
147-
:title (format "%s %s %s"
148-
owner repo
149-
(if path (str "-> " path) ""))})))
153+
(update-in m [:prompts] (fnil conj [])
154+
{:type (second args)
155+
:title (format "%s %s %s"
156+
owner repo
157+
(if path (str "-> " path) ""))})))
150158
(throw (ex-info "Bad GitHub ref" {:ref (second args)}))))
151159
"unregister" (fn []
152160
(registry/update-registry
153161
(fn [m]
154162
(update-in m [:prompts] (fn [coll] (remove (fn [{:keys [type]}] (= type (second args))) coll))))))
155163
"run" (fn []
156-
(with-volume
157-
(fn [thread-id]
158-
(async/<!! ((comp graph/stream graph/chat-with-tools (validate ::run-args))
159-
(-> opts
160-
(assoc :thread-id thread-id)
161-
((fn [opts] (merge
162-
(apply merge-deprecated opts (rest args))
163-
(login-info))))))))
164-
165-
opts))
164+
(let [[in send]
165+
(if (:input opts)
166+
[*in* (constantly true)]
167+
(let [[[w c] in] (user-loop/create-pipe)]
168+
[in (fn []
169+
(w (jsonrpc/request "exit" {} (constantly 1)))
170+
(c))]))]
171+
(send)
172+
(with-volume
173+
(fn [thread-id]
174+
(async/<!!
175+
(user-loop/start-jsonrpc-loop
176+
(user-loop/create-step
177+
(graph/chat-with-tools
178+
(-> (with-options opts (rest args))
179+
(assoc :thread-id thread-id))))
180+
user-loop/state-reducer
181+
in
182+
{})))
183+
opts)))
166184
(fn []
167-
((comp prompts/get-prompts (validate ::run-args)) (merge
168-
(apply merge-deprecated opts args)
169-
(login-info))))))
185+
(prompts/get-prompts (with-options opts args)))))
170186

171187
(defn -main [& args]
172188
(try

src/graph.clj

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,23 @@
5454

5555
(defn start
5656
"create starting messages, metadata, and functions to bootstrap the thread"
57-
[{:keys [prompts] :as opts} _]
57+
[{:keys [prompts] :as opts} state]
5858
(let [c (async/promise-chan)]
5959
(try
60-
(let [new-prompts (prompts/get-prompts opts)]
61-
(jsonrpc/notify :prompts {:messages new-prompts})
62-
(async/put! c {:metadata (prompts/collect-metadata prompts)
63-
:functions (prompts/collect-functions prompts)
64-
:opts (merge opts {:level (or (:level opts) 0)})
65-
:messages new-prompts}))
60+
(async/put!
61+
c
62+
(-> state
63+
(merge
64+
{:metadata (prompts/collect-metadata prompts)
65+
:functions (prompts/collect-functions prompts)
66+
:opts (merge opts {:level (or (:level opts) 0)})})
67+
(update
68+
:messages
69+
(fnil concat [])
70+
(when (not (seq (:messages state)))
71+
(let [new-prompts (prompts/get-prompts opts)]
72+
(jsonrpc/notify :prompts {:messages new-prompts})
73+
new-prompts)))))
6674
(catch Throwable ex
6775
(jsonrpc/notify :error {:content
6876
(format "failure for prompt configuration:\n %s" (with-out-str (pprint (dissoc opts :pat :jwt))))
@@ -75,7 +83,7 @@
7583
[state]
7684
(let [c (async/promise-chan)]
7785
;; this is a normal ending and we try to add a :done key to the state for this
78-
(async/put! c (assoc state :done (:finish-reason state)))
86+
(async/put! c {:done (:finish-reason state)})
7987
c))
8088

8189
(defn completion

src/user_loop.clj

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,51 @@
1010
PipedInputStream
1111
PipedOutputStream]))
1212

13-
(declare graph)
13+
(defn create-step
14+
"compile a function that inserts a user message to-array
15+
to the conversation and stream it through the graph
16+
compiled function returns a channel that will emit the final state"
17+
[graph]
18+
(fn [state]
19+
(graph/stream graph state)))
1420

15-
(def do-stream (partial graph/stream graph))
21+
(defn state-reducer [state s]
22+
(update state :messages (fnil conj []) {:role "user" :content s}))
1623

17-
(defn start-jsonrpc-loop [f in m]
24+
(defn create-test-step []
25+
(fn [state]
26+
(async/go
27+
state)))
28+
29+
(defn start-jsonrpc-loop
30+
"start a jsonrpc loop that will inject jsonrpc requests into an
31+
ongoing set of state transitions
32+
params
33+
run-graph async state -> state
34+
reduce-state state, message -> state
35+
in input stream
36+
m initial state
37+
returns
38+
the final state"
39+
[run-graph state-reducer in m]
1840
(let [c (jsonrpc/input-stream->input-chan in {})]
1941
(async/go-loop
20-
[state m]
21-
(let [message (async/<! c)
22-
s (-> message :params :content)]
23-
(println "message content: " s)
24-
(if (some (partial = s) ["exit" "quit" "q"])
25-
state
26-
(recur (async/<! (f state s))))))))
42+
[next-state (async/<! (run-graph m)) n 0]
43+
(println "### loop " n)
44+
(let [message (async/<! c)]
45+
(cond
46+
(= "exit" (:method message))
47+
(assoc next-state :jsonrpc-loop-finished :exit)
48+
:else
49+
(recur (async/<! ((comp run-graph state-reducer) next-state (-> message :params :content))) (inc n)))))))
2750

2851
(def counter (atom 0))
2952
(defn get-id [] (swap! counter inc))
3053

3154
(def ^{:private true} start-test-loop
32-
(partial start-jsonrpc-loop (fn [state s]
33-
(async/go
34-
(update state :messages (fnil conj []) s)))))
55+
(partial start-jsonrpc-loop (create-test-step) state-reducer))
3556

36-
(defn -create-pipe []
57+
(defn create-pipe []
3758
;; Create a PipedInputStream and PipedOutputStream
3859
(let [piped-out (PipedOutputStream.)
3960
piped-in (PipedInputStream. piped-out)
@@ -43,12 +64,17 @@
4364
piped-in]))
4465

4566
(comment
46-
(let [[[w c] in] (-create-pipe)]
47-
(async/go (println "ending: " (async/<! (start-test-loop in {}))))
48-
(w (jsonrpc/request "prompt" {:content "hello"} get-id))
49-
(w (jsonrpc/request "prompt" {:content "hello1"} get-id))
50-
(w (jsonrpc/request "prompt" {:content "exit"} get-id))
51-
(c)))
67+
(println "should be true: "
68+
(async/<!!
69+
(let [[[w c] in] (create-pipe)]
70+
(w (jsonrpc/request "prompt" {:content "hello"} get-id))
71+
(w (jsonrpc/request "prompt" {:content "hello1"} get-id))
72+
(w (jsonrpc/request "prompt" {:content "hello2"} get-id))
73+
(w (jsonrpc/request "exit" {} get-id))
74+
(c)
75+
(async/go
76+
(println "ending: " (async/<! (start-test-loop in {})))
77+
true)))))
5278

5379
(comment
5480
;; an input stream is something from which we can read bytes

0 commit comments

Comments
 (0)