|
31 | 31 | (logger/warn logger-tag "Error listing running models:" (ex-message e)) |
32 | 32 | []))) |
33 | 33 |
|
34 | | -(defn ^:private raw-data->messages [data] |
35 | | - (let [{:keys [message done_reason]} (json/parse-string data true)] |
36 | | - (cond-> {} |
37 | | - message (assoc :message (:content message)) |
38 | | - done_reason (assoc :finish-reason done_reason)))) |
39 | | - |
40 | 34 | (defn ^:private ->message-with-context [context user-prompt] |
41 | 35 | (format "%s\nThe user is asking: '%s'" context user-prompt)) |
42 | 36 |
|
43 | | -(defn completion! [{:keys [model user-prompt context host port past-messages]} |
44 | | - {:keys [on-message-received on-error]}] |
45 | | - (let [body {:model model |
46 | | - :messages (if (empty? past-messages) |
47 | | - [{:role "user" :content (->message-with-context context user-prompt)}] |
48 | | - (conj past-messages {:role "user" :content user-prompt})) |
49 | | - :stream true}] |
50 | | - (http/post |
51 | | - (format chat-url (base-url host port)) |
52 | | - {:body (json/generate-string body) |
53 | | - :throw-exceptions? false |
54 | | - :async? true |
55 | | - :as :stream} |
56 | | - (fn [{:keys [status body]}] |
57 | | - (try |
| 37 | +(defn ^:private base-completion-request! [{:keys [url body on-error on-response]}] |
| 38 | + (http/post |
| 39 | + url |
| 40 | + {:body (json/generate-string body) |
| 41 | + :throw-exceptions? false |
| 42 | + :async? true |
| 43 | + :as :stream} |
| 44 | + (fn [{:keys [status body]}] |
| 45 | + (try |
| 46 | + (if (not= 200 status) |
| 47 | + (let [body-str (slurp body)] |
| 48 | + (logger/warn logger-tag "Unexpected response status: %s body: %s" status body-str) |
| 49 | + (on-error {:message (format "Ollama response status: %s body: %s" status body-str)})) |
58 | 50 | (with-open [rdr (io/reader body)] |
59 | 51 | (doseq [line (line-seq rdr)] |
60 | | - (if (not= 200 status) |
61 | | - (let [msg line] |
62 | | - (logger/warn logger-tag "Unexpected response status" status "." msg) |
63 | | - (on-error {:message (str "Ollama response status: " status)})) |
64 | | - (when-let [message (raw-data->messages line)] |
65 | | - (on-message-received message))))) |
66 | | - (catch Exception e |
67 | | - (on-error {:exception e})))) |
68 | | - (fn [e] |
69 | | - (on-error {:exception e}))))) |
| 52 | + (on-response (json/parse-string line true))))) |
| 53 | + (catch Exception e |
| 54 | + (on-error {:exception e})))) |
| 55 | + (fn [e] |
| 56 | + (on-error {:exception e})))) |
| 57 | + |
| 58 | +(defn ^:private ->tools [tools] |
| 59 | + (mapv (fn [tool] |
| 60 | + {:type "function" |
| 61 | + :function (select-keys tool [:name :description :parameters])}) |
| 62 | + tools)) |
| 63 | + |
| 64 | +(defn completion! [{:keys [model user-prompt context host port past-messages tools]} |
| 65 | + {:keys [on-message-received on-error _on-tool-called]}] |
| 66 | + (let [messagess (if (empty? past-messages) |
| 67 | + [{:role "user" :content (->message-with-context context user-prompt)}] |
| 68 | + (conj past-messages {:role "user" :content user-prompt})) |
| 69 | + body {:model model |
| 70 | + :messages messagess |
| 71 | + :tools (->tools tools) |
| 72 | + :stream true} |
| 73 | + url (format chat-url (base-url host port)) |
| 74 | + on-response-fn (fn handle-response [data] |
| 75 | + (let [{:keys [message done_reason]} data] |
| 76 | + (on-message-received |
| 77 | + (cond-> {} |
| 78 | + message (assoc :message (:content message)) |
| 79 | + done_reason (assoc :finish-reason done_reason)))))] |
| 80 | + (base-completion-request! |
| 81 | + {:url url |
| 82 | + :body body |
| 83 | + :on-error on-error |
| 84 | + :on-response on-response-fn}))) |
0 commit comments