|
52 | 52 | ; be merged into the conversation state
|
53 | 53 | ; =====================================================
|
54 | 54 |
|
55 |
| -(defn start |
| 55 | +(defn start |
56 | 56 | "create starting messages, metadata, and functions to bootstrap the thread"
|
57 | 57 | [{:keys [prompts] :as opts} _]
|
58 | 58 | (let [c (async/promise-chan)]
|
|
70 | 70 | (async/put! c {:messages [] :done "error"})))
|
71 | 71 | c))
|
72 | 72 |
|
73 |
| -(defn end |
| 73 | +(defn end |
74 | 74 | "merge the :done signal"
|
75 | 75 | [state]
|
76 | 76 | (let [c (async/promise-chan)]
|
77 | 77 | ;; this is a normal ending and we try to add a :done key to the state for this
|
78 | 78 | (async/put! c (assoc state :done (:finish-reason state)))
|
79 | 79 | c))
|
80 | 80 |
|
81 |
| -(defn completion |
| 81 | +(defn completion |
82 | 82 | "get the next llm completion"
|
83 | 83 | [state]
|
84 | 84 | (run-llm (:messages state) (:metadata state) (:functions state) (:opts state)))
|
85 | 85 |
|
86 |
| -(defn tool |
| 86 | +(defn tool |
87 | 87 | "make docker container tool calls"
|
88 | 88 | [state]
|
89 | 89 | (let [calls (-> (:messages state) last :tool_calls)]
|
|
102 | 102 |
|
103 | 103 | ; tool_calls are maps with an id and a function with arguments an name
|
104 | 104 | ; look up the full tool definition using the name
|
105 |
| -(defn sub-graph |
| 105 | +(defn sub-graph |
106 | 106 | "answer a tool call by processing a sub-graph"
|
107 | 107 | [state]
|
108 | 108 | (async/go
|
|
126 | 126 | ; edge functions takes state and returns next node
|
127 | 127 | ; =====================================================
|
128 | 128 |
|
129 |
| -(defn tool-or-end |
| 129 | +(defn tool-or-end |
130 | 130 | "after a completion, check whether you need to make a tool call"
|
131 | 131 | [state]
|
132 | 132 | (let [finish-reason (-> state :finish-reason)]
|
|
148 | 148 | (defn add-conditional-edges [graph s1 f & [m]]
|
149 | 149 | (assoc-in graph [:edges s1] ((or m identity) f)))
|
150 | 150 |
|
151 |
| -(defn state-reducer |
| 151 | +(defn state-reducer |
152 | 152 | "reduce the state with the change from running a node"
|
153 | 153 | [state change]
|
154 | 154 | (-> state
|
|
157 | 157 |
|
158 | 158 | (defn stream
|
159 | 159 | "start streaming a conversation"
|
160 |
| - [graph] |
161 |
| - (async/go-loop |
162 |
| - [state {} |
163 |
| - node "start"] |
164 |
| - (jsonrpc/notify :message {:debug (format "\n-> entering %s\n\n" node)}) |
165 |
| - ;; TODO handling bad graphs with missing nodes |
166 |
| - (let [enter-node (get-in graph [:nodes node]) |
167 |
| - new-state (state-reducer state (async/<! (enter-node state)))] |
168 |
| - (if (= "end" node) |
169 |
| - new-state |
170 |
| - ;; TODO check for :done keys and possibly bail |
171 |
| - ;; transition to the next state |
172 |
| - ;; TODO handling missing edges |
173 |
| - (recur new-state ((get-in graph [:edges node]) new-state)))))) |
| 160 | + ([graph] (stream graph {})) |
| 161 | + ([graph m] |
| 162 | + (async/go-loop |
| 163 | + [state m |
| 164 | + node "start"] |
| 165 | + (jsonrpc/notify :message {:debug (format "\n-> entering %s\n\n" node)}) |
| 166 | + ;; TODO handling bad graphs with missing nodes |
| 167 | + (let [enter-node (get-in graph [:nodes node]) |
| 168 | + new-state (state-reducer state (async/<! (enter-node state)))] |
| 169 | + (if (= "end" node) |
| 170 | + new-state |
| 171 | + ;; TODO check for :done keys and possibly bail |
| 172 | + ;; transition to the next state |
| 173 | + ;; TODO handling missing edges |
| 174 | + (recur new-state ((get-in graph [:edges node]) new-state))))))) |
174 | 175 |
|
175 | 176 | ; ============================================================
|
176 | 177 | ; this is the graph we tend to use in our experiments thus far
|
|
0 commit comments