Skip to content

Commit a8f1cf4

Browse files
committed
Use same llm_api for sync requests
1 parent ca69324 commit a8f1cf4

File tree

5 files changed

+117
-193
lines changed

5 files changed

+117
-193
lines changed

src/eca/features/chat.clj

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -561,27 +561,28 @@
561561

562562
(when-not (get-in db [:chats chat-id :title])
563563
(future
564-
(when-let [title @(llm-api/simple-prompt
565-
{:provider provider
566-
:model model
567-
:model-capabilities model-capabilities
568-
:instructions (f.prompt/title-prompt)
569-
:user-messages user-messages
570-
:config config
571-
:tools []
572-
:provider-auth provider-auth})]
573-
(let [title (subs title 0 (min (count title) 30))]
574-
(swap! db* assoc-in [:chats chat-id :title] title)
575-
(send-content! chat-ctx :system (assoc-some
576-
{:type :metadata}
577-
:title title))
578-
;; user prompt responded faster than title was generated
579-
(when (= :idle (get-in @db* [:chats chat-id :status]))
580-
(db/update-workspaces-cache! @db* metrics))))))
564+
(when-let [{:keys [result]} (llm-api/sync-prompt!
565+
{:provider provider
566+
:model model
567+
:model-capabilities model-capabilities
568+
:instructions (f.prompt/title-prompt)
569+
:user-messages user-messages
570+
:config config
571+
:tools []
572+
:provider-auth provider-auth})]
573+
(when result
574+
(let [title (subs result 0 (min (count result) 30))]
575+
(swap! db* assoc-in [:chats chat-id :title] title)
576+
(send-content! chat-ctx :system (assoc-some
577+
{:type :metadata}
578+
:title title))
579+
;; user prompt responded faster than title was generated
580+
(when (= :idle (get-in @db* [:chats chat-id :status]))
581+
(db/update-workspaces-cache! @db* metrics)))))))
581582
(send-content! chat-ctx :system {:type :progress
582583
:state :running
583584
:text "Waiting model"})
584-
(llm-api/chat!
585+
(llm-api/async-prompt!
585586
{:model model
586587
:provider provider
587588
:model-capabilities model-capabilities

src/eca/features/completion.clj

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,24 @@
6262
{:keys [line character]} position
6363
input-code (insert-completion-tag doc-text position)
6464
instructions (f.prompt/inline-completion-prompt config)
65-
{:keys [error-message result]} (llm-api/complete!
66-
{:provider provider
67-
:model model
68-
:config config
69-
:input-code input-code
70-
:instructions instructions
71-
:provider-auth provider-auth
72-
:model-capabilities model-capabilities})]
65+
{:keys [error result]} (llm-api/sync-prompt!
66+
{:provider provider
67+
:model model
68+
:config config
69+
:prompt input-code
70+
:instructions instructions
71+
:provider-auth provider-auth
72+
:model-capabilities model-capabilities})]
7373
(cond
74-
error-message
74+
(:message error)
7575
{:error {:type :warning
76-
:message error-message}}
76+
:message (:message error)}}
77+
78+
(:exception error)
79+
(do
80+
(logger/error logger-tag "Error when requesting completion: %s" (:exception error))
81+
{:error {:type :warning
82+
:message (:message (.getMessage ^Exception (:exception error)))}})
7783

7884
(not result)
7985
{:error {:type :info

src/eca/llm_api.clj

Lines changed: 71 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -69,36 +69,11 @@
6969
(defn ^:private real-model-name [model model-capabilities]
7070
(or (:model-name model-capabilities) model))
7171

72-
(defn chat!
73-
[{:keys [provider model model-capabilities instructions user-messages config on-first-response-received
72+
(defn ^:private prompt!
73+
[{:keys [provider model model-capabilities instructions user-messages config
7474
on-message-received on-error on-prepare-tool-call on-tools-called on-reason on-usage-updated
75-
past-messages tools provider-auth]
76-
:or {on-first-response-received identity
77-
on-message-received identity
78-
on-error identity
79-
on-prepare-tool-call identity
80-
on-tools-called identity
81-
on-reason identity
82-
on-usage-updated identity}}]
83-
(let [first-response-received* (atom false)
84-
emit-first-message-fn (fn [& args]
85-
(when-not @first-response-received*
86-
(reset! first-response-received* true)
87-
(apply on-first-response-received args)))
88-
on-message-received-wrapper (fn [& args]
89-
(apply emit-first-message-fn args)
90-
(apply on-message-received args))
91-
on-reason-wrapper (fn [& args]
92-
(apply emit-first-message-fn args)
93-
(apply on-reason args))
94-
on-prepare-tool-call-wrapper (fn [& args]
95-
(apply emit-first-message-fn args)
96-
(apply on-prepare-tool-call args))
97-
on-error-wrapper (fn [{:keys [exception] :as args}]
98-
(when-not (:silent? (ex-data exception))
99-
(logger/error args)
100-
(on-error args)))
101-
real-model (real-model-name model model-capabilities)
75+
past-messages tools provider-auth sync?]}]
76+
(let [real-model (real-model-name model model-capabilities)
10277
tools (when (:tools model-capabilities)
10378
(mapv tool->llm-tool tools))
10479
reason? (:reason? model-capabilities)
@@ -111,12 +86,13 @@
11186
api-key (llm-util/provider-api-key provider provider-auth config)
11287
api-url (llm-util/provider-api-url provider config)
11388
provider-auth-type (:type provider-auth)
114-
callbacks {:on-message-received on-message-received-wrapper
115-
:on-error on-error-wrapper
116-
:on-prepare-tool-call on-prepare-tool-call-wrapper
117-
:on-tools-called on-tools-called
118-
:on-reason on-reason-wrapper
119-
:on-usage-updated on-usage-updated}]
89+
callbacks (when-not sync?
90+
{:on-message-received on-message-received
91+
:on-error on-error
92+
:on-prepare-tool-call on-prepare-tool-call
93+
:on-tools-called on-tools-called
94+
:on-reason on-reason
95+
:on-usage-updated on-usage-updated})]
12096
(try
12197
(when-not api-url (throw (ex-info (format "API url not found.\nMake sure you have provider '%s' configured properly." provider) {})))
12298
(cond
@@ -215,7 +191,7 @@
215191
"openai") llm-providers.openai/create-response!
216192
"anthropic" llm-providers.anthropic/chat!
217193
"openai-chat" llm-providers.openai-chat/chat-completion!
218-
(on-error-wrapper {:message (format "Unknown model %s for provider %s" (:api provider-config) provider)}))
194+
(on-error {:message (format "Unknown model %s for provider %s" (:api provider-config) provider)}))
219195
url-relative-path (:completionUrlRelativePath provider-config)]
220196
(provider-fn
221197
{:model real-model
@@ -234,127 +210,69 @@
234210
callbacks))
235211

236212
:else
237-
(on-error-wrapper {:message (format "ECA Unsupported model %s for provider %s" real-model provider)}))
213+
(on-error {:message (format "ECA Unsupported model %s for provider %s" real-model provider)}))
238214
(catch Exception e
239-
(on-error-wrapper {:exception e})))))
215+
(on-error {:exception e})))))
240216

241-
(defn complete!
242-
[{:keys [provider model model-capabilities instructions input-code config provider-auth]}]
243-
(let [reason? (:reason? model-capabilities)
244-
provider-config (get-in config [:providers provider])
245-
model-config (get-in provider-config [:models model])
246-
real-model (real-model-name model model-capabilities)
247-
max-output-tokens (:max-output-tokens model-capabilities)
248-
extra-payload (:extraPayload model-config)
249-
api-key (llm-util/provider-api-key provider provider-auth config)
250-
api-url (llm-util/provider-api-url provider config)
251-
provider-auth-type (:type provider-auth)
252-
user-messages [{:role "user" :content [{:type :text :text input-code}]}]]
253-
(try
254-
(when-not api-url (throw (ex-info (format "API url not found.\nMake sure you have provider '%s' configured properly." provider) {})))
255-
(cond
256-
(= "openai" provider)
257-
(llm-providers.openai/create-response!
258-
{:model real-model
259-
:instructions instructions
260-
:user-messages user-messages
261-
:past-messages []
262-
:tools []
263-
:web-search false
264-
:max-output-tokens max-output-tokens
265-
:reason? reason?
266-
:extra-payload extra-payload
267-
:api-url api-url
268-
:api-key api-key
269-
:auth-type provider-auth-type}
270-
nil)
271-
272-
(= "github-copilot" provider)
273-
(llm-providers.openai-chat/chat-completion!
274-
{:model real-model
275-
:instructions instructions
276-
:user-messages user-messages
277-
:past-messages []
278-
:tools []
279-
:max-output-tokens max-output-tokens
280-
:reason? reason?
281-
:extra-payload extra-payload
282-
:api-url api-url
283-
:api-key api-key
284-
:extra-headers {"openai-intent" "conversation-panel"
285-
"x-request-id" (str (random-uuid))
286-
"vscode-sessionid" ""
287-
"vscode-machineid" ""
288-
"Copilot-Vision-Request" "true"
289-
"copilot-integration-id" "vscode-chat"}}
290-
nil)
291-
292-
(= "google" provider)
293-
(llm-providers.openai-chat/chat-completion!
294-
{:model real-model
295-
:instructions instructions
296-
:user-messages user-messages
297-
:max-output-tokens max-output-tokens
298-
:reason? reason?
299-
:past-messages []
300-
:tools []
301-
:thinking-tag "thought"
302-
:extra-payload (merge {:parallel_tool_calls false}
303-
(when reason?
304-
{:extra_body {:google {:thinking_config {:include_thoughts true}}}})
305-
extra-payload)
306-
:api-url api-url
307-
:api-key api-key}
308-
nil)
309-
310-
model-config
311-
(let [provider-fn (case (:api provider-config)
312-
"openai-responses" llm-providers.openai/create-response!
313-
"openai-chat" llm-providers.openai-chat/chat-completion!
314-
{:error-message (format "Unknown model %s for provider %s" (:api provider-config) provider)})
315-
url-relative-path (:completionUrlRelativePath provider-config)]
316-
(provider-fn
317-
{:model real-model
318-
:instructions instructions
319-
:web-search false
320-
:max-output-tokens max-output-tokens
321-
:user-messages user-messages
322-
:past-messages []
323-
:tools []
324-
:reason? reason?
325-
:extra-payload extra-payload
326-
:url-relative-path url-relative-path
327-
:api-url api-url
328-
:api-key api-key}
329-
nil))
330-
331-
:else
332-
{:error-message (format "ECA Unsupported model %s for provider %s" model provider)})
333-
(catch Exception e
334-
(logger/warn logger-tag "Error completing: %s" (.getMessage e))
335-
{:error-message (.getMessage e)}))))
336-
337-
(defn simple-prompt
338-
[{:keys [provider model model-capabilities instructions
339-
prompt user-messages config tools provider-auth]}]
340-
(let [result-p (promise)
341-
output* (atom "")]
342-
(chat!
343-
{:provider provider
217+
(defn async-prompt! [{:keys [provider model model-capabilities instructions user-messages config on-first-response-received
218+
on-message-received on-error on-prepare-tool-call on-tools-called on-reason on-usage-updated
219+
past-messages tools provider-auth]
220+
:or {on-first-response-received identity
221+
on-message-received identity
222+
on-error identity
223+
on-prepare-tool-call identity
224+
on-tools-called identity
225+
on-reason identity
226+
on-usage-updated identity}}]
227+
(let [first-response-received* (atom false)
228+
emit-first-message-fn (fn [& args]
229+
(when-not @first-response-received*
230+
(reset! first-response-received* true)
231+
(apply on-first-response-received args)))
232+
on-message-received-wrapper (fn [& args]
233+
(apply emit-first-message-fn args)
234+
(apply on-message-received args))
235+
on-reason-wrapper (fn [& args]
236+
(apply emit-first-message-fn args)
237+
(apply on-reason args))
238+
on-prepare-tool-call-wrapper (fn [& args]
239+
(apply emit-first-message-fn args)
240+
(apply on-prepare-tool-call args))
241+
on-error-wrapper (fn [{:keys [exception] :as args}]
242+
(when-not (:silent? (ex-data exception))
243+
(logger/error args)
244+
(on-error args)))]
245+
(prompt!
246+
{:sync? false
247+
:provider provider
344248
:model model
345249
:model-capabilities model-capabilities
346250
:instructions instructions
347251
:tools tools
348252
:provider-auth provider-auth
349-
:past-messages []
350-
:user-messages (or user-messages
351-
[{:role "user" :content [{:type :text :text prompt}]}])
352-
:config config
353-
:on-message-received (fn [{:keys [type] :as msg}]
354-
(case type
355-
:text (swap! output* str (:text msg))
356-
:finish (deliver result-p @output*)
357-
nil))
358-
:on-error (fn [_]
359-
(deliver result-p nil))})
360-
result-p))
253+
:past-messages past-messages
254+
:user-messages user-messages
255+
:on-message-received on-message-received-wrapper
256+
:on-prepare-tool-call on-prepare-tool-call-wrapper
257+
:on-tools-called on-tools-called
258+
:on-usage-updated on-usage-updated
259+
:on-reason on-reason-wrapper
260+
:on-error on-error-wrapper
261+
:config config})))
262+
263+
(defn sync-prompt!
264+
[{:keys [provider model model-capabilities instructions
265+
prompt past-messages user-messages config tools provider-auth]}]
266+
(prompt!
267+
{:sync? true
268+
:provider provider
269+
:model model
270+
:model-capabilities model-capabilities
271+
:instructions instructions
272+
:tools tools
273+
:provider-auth provider-auth
274+
:past-messages past-messages
275+
:user-messages (or user-messages
276+
[{:role "user" :content [{:type :text :text prompt}]}])
277+
:config config
278+
:on-error identity}))

src/eca/llm_providers/openai_chat.clj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,7 @@
283283
[{:keys [model user-messages instructions temperature api-key api-url url-relative-path
284284
past-messages tools extra-payload extra-headers supports-image?
285285
thinking-tag]
286-
:or {temperature 1.0
287-
thinking-tag "think"}}
286+
:or {thinking-tag "think"}}
288287
{:keys [on-message-received on-error on-prepare-tool-call on-tools-called on-reason on-usage-updated] :as callbacks}]
289288
(let [thinking-start-tag (str "<" thinking-tag ">")
290289
thinking-end-tag (str "</" thinking-tag ">")

0 commit comments

Comments
 (0)