Skip to content

Commit 0426eb4

Browse files
committed
Add tools config
1 parent 180dcb7 commit 0426eb4

File tree

7 files changed

+68
-42
lines changed

7 files changed

+68
-42
lines changed

docs/configuration.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ interface Config {
7676
ollama?: {
7777
host: string;
7878
port: string;
79+
useTools: boolean;
7980
}
8081
chat?: {
8182
welcomeMessage: string;
@@ -99,7 +100,8 @@ interface Config {
99100
"mcpServers" : [ ],
100101
"ollama" : {
101102
"host" : "http://localhost",
102-
"port" : 11434
103+
"port" : 11434,
104+
"useTools": false
103105
},
104106
"chat" : {
105107
"welcomeMessage" : "Welcome to ECA! What you have in mind?\n\n"

src/eca/config.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
:mcp-timeout-seconds 10
2323
:mcp-servers []
2424
:ollama {:host "http://localhost"
25-
:port 11434}
25+
:port 11434
26+
:use-tools false}
2627
:chat {:welcome-message "Welcome to ECA! What you have in mind?\n\n"}
2728
:index {:ignore-files [{:type :gitignore}]}})
2829

src/eca/db.clj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
:chats {}
1010
:chat-behaviors ["agent" "chat"]
1111
:chat-default-behavior "chat"
12-
:models ["o4-mini"
13-
"gpt-4.1"
14-
"claude-sonnet-4-0"
15-
"claude-opus-4-0"
16-
"claude-3-5-haiku-latest"] ;; + ollama local models
12+
:models {"o4-mini" {:tools true}
13+
"gpt-4.1" {:tools true}
14+
"claude-sonnet-4-0" {:tools true}
15+
"claude-opus-4-0" {:tools true}
16+
"claude-3-5-haiku-latest" {:tools true}} ;; + ollama local models
1717
:default-model "o4-mini" ;; unless a ollama model is running.
1818
})
1919

src/eca/features/chat.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@
102102
chosen-model (or model (default-model db))
103103
past-messages (get-in db [:chats chat-id :messages] [])
104104
user-prompt message
105-
mcp-tools (all-mcp-tools! chat-id request-id messenger db*)
105+
mcp-tools (when (get-in db [:models chosen-model :use-tools])
106+
(all-mcp-tools! chat-id request-id messenger db*))
106107
received-msgs* (atom "")]
107108
(swap! db* update-in [:chats chat-id :messages] (fnil conj []) {:role "user" :content user-prompt})
108109
(messenger/chat-content-received

src/eca/handlers.clj

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212
(defn ^:private initialize-extra-models! [db*]
1313
(let [config (config/all @db*)]
1414
(when-let [ollama-models (seq (llm-api/extra-models config))]
15-
(swap! db* update :models concat (map #(str config/ollama-model-prefix (:model %)) ollama-models)))))
15+
(swap! db* update :models merge
16+
(reduce
17+
(fn [models {:keys [model]}]
18+
(assoc models (str config/ollama-model-prefix model) {:tools (get-in config [:ollama :use-tools] false)}))
19+
{}
20+
ollama-models)))))
1621

1722
(defn initialize [{:keys [db*]} params]
1823
(logger/logging-task
@@ -26,7 +31,7 @@
2631
(initialize-extra-models! db*)
2732
;; TODO initialize async with progress support
2833
(f.mcp/initialize! db* config)
29-
{:models (:models @db*)
34+
{:models (keys (:models @db*))
3035
:chat-default-model (f.chat/default-model @db*)
3136
:chat-behaviors (:chat-behaviors @db*)
3237
:chat-default-behavior (:chat-default-behavior @db*)

src/eca/llm_api.clj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@
6565
:model (string/replace-first model config/ollama-model-prefix "")
6666
:past-messages past-messages
6767
:context context
68+
:tools tools
6869
:user-prompt user-prompt}
6970
{:on-message-received on-message-received-wrapper
70-
:on-error on-error})
71+
:on-error on-error
72+
:on-tool-called on-tool-called})
7173

7274
:else
7375
(on-error {:msg (str "ECA Unsupported model: " model)}))))

src/eca/llm_providers/ollama.clj

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,54 @@
3131
(logger/warn logger-tag "Error listing running models:" (ex-message e))
3232
[])))
3333

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-
4034
(defn ^:private ->message-with-context [context user-prompt]
4135
(format "%s\nThe user is asking: '%s'" context user-prompt))
4236

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)}))
5850
(with-open [rdr (io/reader body)]
5951
(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

Comments
 (0)