|
2 | 2 | (:require |
3 | 3 | [babashka.fs :as fs] |
4 | 4 | [clojure.core.async :as async] |
5 | | - [clojure.pprint :refer [pprint]] |
6 | 5 | [clojure.core.match :refer [match]] |
7 | 6 | git |
8 | 7 | jsonrpc |
|
72 | 71 | [state] |
73 | 72 | (run-llm (:messages state) (dissoc (:metadata state) :agent) (:functions state) (:opts state))) |
74 | 73 |
|
75 | | -;; TODO does the LangGraph Tool Node always search for the a tool_call |
76 | 74 | (defn tool |
77 | 75 | "execute the tool_calls from the last AI message in the conversation" |
78 | 76 | [state] |
|
97 | 95 | [_] |
98 | 96 | (async/go {})) |
99 | 97 |
|
100 | | -(defn construct-initial-state-from-prompts [{{:keys [prompts] :as opts} :opts :as state}] |
101 | | - (try |
102 | | - (-> state |
103 | | - (merge |
104 | | - {:metadata (prompts/collect-metadata prompts) |
105 | | - :functions (prompts/collect-functions prompts) |
106 | | - :opts (merge opts {:level (or (:level opts) 0)})}) |
107 | | - (update |
108 | | - :messages |
109 | | - (fnil concat []) |
110 | | - (when (not (seq (:messages state))) |
111 | | - (let [new-prompts (prompts/get-prompts opts)] |
112 | | - (jsonrpc/notify :prompts {:messages new-prompts}) |
113 | | - new-prompts)))) |
114 | | - (catch Throwable ex |
115 | | - (jsonrpc/notify :error {:content |
116 | | - (format "failure for prompt configuration:\n %s" (with-out-str (pprint (dissoc opts :pat :jwt)))) |
117 | | - :exception (str ex)})))) |
118 | | - |
119 | | -; tool_calls are maps with an id and a function with arguments an name |
120 | | -; look up the full tool definition using the name |
121 | | - |
122 | | -(defn add-prompt-ref [state] |
123 | | - (let [definition (state/get-function-definition state) |
124 | | - arg-context (let [raw-args (-> state :messages last :tool_calls first :function :arguments)] |
125 | | - (tools/arg-context raw-args))] |
126 | | - (-> state |
127 | | - (dissoc :messages) |
128 | | - (update-in [:opts :level] (fnil inc 0)) |
129 | | - (update-in [:opts :prompts] (constantly (git/prompt-file (-> definition :function :ref)))) |
130 | | - (update-in [:opts :parameters] (constantly arg-context))))) |
131 | | - |
132 | | -(comment |
133 | | - ;; TODO move this into the thingy |
134 | | - (add-prompt-ref {:messages [{:tool_calls [{:function {:name "sql_db_list_tables" |
135 | | - :arguments "{\"arg\": 1}"}}]}] |
136 | | - :functions [{:function {:name "sql_db_list_tables" |
137 | | - :description "List all tables in the database" |
138 | | - :parameters {:type "object" |
139 | | - :properties |
140 | | - {:database {:type "string" :description "the database to query"}}} |
141 | | - :ref "github:docker/labs-ai-tools-for-devs?path=prompts/curl/README.md"}}]})) |
142 | | - |
143 | 98 | (declare stream chat-with-tools) |
144 | 99 |
|
145 | | -(defn add-last-message-as-tool-call |
146 | | - [state sub-graph-state] |
147 | | - {:messages [(-> sub-graph-state |
148 | | - :messages |
149 | | - last |
150 | | - (state/add-tool-call-id (-> state :messages last :tool_calls first :id)))]}) |
151 | | - |
152 | | -(defn append-new-messages |
153 | | - [state sub-graph-state] |
154 | | - {:messages (->> (:messages sub-graph-state) |
155 | | - (filter (complement (fn [m] (some #(= m %) (:messages state))))))}) |
156 | | - |
157 | 100 | (defn sub-graph-node |
158 | 101 | "create a sub-graph node that initializes a conversation from the current one, |
159 | 102 | creates a new agent graph from the current state and returns the messages to be added |
|
165 | 108 | (async/<! |
166 | 109 | (stream |
167 | 110 | ((or construct-graph chat-with-tools) state) |
168 | | - ((or init-state (comp construct-initial-state-from-prompts add-prompt-ref)) state)))] |
169 | | - ((or next-state add-last-message-as-tool-call) state sub-graph-state))))) |
| 111 | + (-> |
| 112 | + ((or init-state (comp state/construct-initial-state-from-prompts state/add-prompt-ref)) state) |
| 113 | + (update-in [:opts :level] (fnil inc 0)))))] |
| 114 | + ((or next-state state/add-last-message-as-tool-call) state sub-graph-state))))) |
170 | 115 |
|
171 | 116 | ; ===================================================== |
172 | 117 | ; edge functions takes state and returns next node |
|
280 | 225 | ["tools-query"]] |
281 | 226 | [["end" end]]]) |
282 | 227 |
|
283 | | -(defn one-tool-call [_] |
| 228 | +(defn generate-one-tool-call [_] |
284 | 229 | (-> {} |
285 | 230 | (add-node "start" start) |
286 | 231 | (add-node "completion" completion) |
|
302 | 247 | ["completion"]] |
303 | 248 | [["end" end]]]) |
304 | 249 |
|
305 | | -(comment |
306 | | - (alter-var-root #'jsonrpc/notify (fn [_] (partial jsonrpc/-println {:debug true}))) |
307 | | - (let [x {:prompts (fs/file "/Users/slim/docker/labs-ai-tools-for-devs/prompts/curl/README.md") |
308 | | - :platform "darwin" |
309 | | - :user "jimclark106" |
310 | | - :thread-id "thread" |
311 | | - :host-dir "/Users/slim" |
312 | | - :stream true}] |
313 | | - (state/summarize (async/<!! (stream (chat-with-tools x) x))))) |
314 | | - |
315 | | -(comment |
316 | | - (def x {:stream true, |
317 | | - :host-dir "/Users/slim/docker/labs-make-runbook", |
318 | | - :prompts "/Users/slim/docker/labs-ai-tools-for-devs/prompts/hub/default.md" |
319 | | - :platform "darwin", :user "jimclark106", |
320 | | - :thread-id "3e61ffe7-840e-4177-b84a-f6f7db58b24d"}) |
321 | | - (state/summarize |
322 | | - (async/<!! (stream (chat-with-tools x) x)))) |
| 250 | +; requires finish-reason to be set to tool_calls |
| 251 | +(def start-with-tool |
| 252 | + [[["start" start] |
| 253 | + [:edge tool-or-end]] |
| 254 | + [["sub-graph" (sub-graph-node {})] |
| 255 | + ["end" end]] |
| 256 | + [["tool" (tool-node {})] |
| 257 | + ["end"]]]) |
323 | 258 |
|
0 commit comments