Skip to content

Commit 7ddc6dd

Browse files
committed
Support openai o models reason text when available.
1 parent ca5514a commit 7ddc6dd

File tree

3 files changed

+36
-24
lines changed

3 files changed

+36
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Fix reason-id on openai models afecting chat thoughts messages.
6+
- Support openai o models reason text when available.
67

78
## 0.14.2
89

src/eca/handlers.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
(fn [m model]
2020
(assoc m
2121
(str (name provider) "/" model)
22+
;; TODO avoid hardcoding these capabilities
2223
{:tools true
2324
:web-search true
2425
:custom-provider? true

src/eca/llm_providers/openai.clj

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,30 @@
4141
(on-error {:exception e})))))
4242

4343
(defn ^:private normalize-messages [past-messages]
44-
(keep (fn [{:keys [role content] :as msg}]
45-
(case role
46-
"tool_call" {:type "function_call"
47-
:name (:name content)
48-
:call_id (:id content)
49-
:arguments (json/generate-string (:arguments content))}
50-
"tool_call_output"
51-
{:type "function_call_output"
52-
:call_id (:id content)
53-
:output (llm-util/stringfy-tool-result content)}
54-
"reason" nil
55-
(update msg :content (fn [c]
56-
(if (string? c)
57-
c
58-
(mapv #(if (= "text" (name (:type %)))
59-
(assoc % :type (if (= "user" role)
60-
"input_text"
61-
"output_text"))
62-
%) c))))))
63-
past-messages))
44+
(keep-indexed (fn [i {:keys [role content] :as msg}]
45+
(case role
46+
"tool_call" {:type "function_call"
47+
:name (:name content)
48+
:call_id (:id content)
49+
:arguments (json/generate-string (:arguments content))}
50+
"tool_call_output"
51+
{:type "function_call_output"
52+
:call_id (:id content)
53+
:output (llm-util/stringfy-tool-result content)}
54+
;; TODO include reason blocks
55+
"reason" nil
56+
(update msg :content (fn [c]
57+
(if (string? c)
58+
c
59+
(mapv #(if (= "text" (name (:type %)))
60+
(assoc % :type (if (= "user" role)
61+
"input_text"
62+
"output_text"))
63+
%) c))))))
64+
past-messages))
6465

65-
(defn completion! [{:keys [model user-messages instructions temperature api-key api-url
66-
max-output-tokens past-messages tools web-search]
67-
:or {temperature 1.0}}
66+
(defn completion! [{:keys [model user-messages instructions reason? temperature api-key api-url
67+
max-output-tokens past-messages tools web-search]}
6868
{:keys [on-message-received on-error on-prepare-tool-call on-tool-called on-reason]}]
6969
(let [input (concat (normalize-messages past-messages)
7070
(normalize-messages user-messages))
@@ -76,8 +76,12 @@
7676
;; TODO support parallel
7777
:parallel_tool_calls false
7878
:instructions instructions
79+
;; TODO allow user specify custom temperature (default 1.0)
7980
:temperature temperature
8081
:tools tools
82+
:reasoning (when reason?
83+
{:effort "medium"
84+
:summary "detailed"})
8185
:stream true
8286
:max_output_tokens max-output-tokens}
8387
mcp-call-by-item-id* (atom {})
@@ -111,7 +115,8 @@
111115
:on-response handle-response})
112116
(swap! mcp-call-by-item-id* dissoc (-> data :item :id)))
113117
"reasoning" (on-reason {:status :finished
114-
:id (-> data :item :id)})
118+
:id (-> data :item :id)
119+
:external-id (-> data :item :id)})
115120
nil)
116121

117122
;; URL mentioned
@@ -124,6 +129,11 @@
124129
nil)
125130

126131
;; reasoning / tools
132+
"response.reasoning_summary_text.delta"
133+
(on-reason {:status :thinking
134+
:id (:item_id data)
135+
:text (:delta data)})
136+
127137
"response.output_item.added"
128138
(case (-> data :item :type)
129139
"reasoning" (on-reason {:status :started

0 commit comments

Comments
 (0)