Skip to content

Commit bf1e9a5

Browse files
committed
Fix tests for context aggregators
1 parent 757e3a7 commit bf1e9a5

File tree

3 files changed

+65
-65
lines changed

3 files changed

+65
-65
lines changed

core/.clj-kondo/metosin/malli-types-clj/config.edn

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
transcription? {:arities {1 {:args [:any], :ret :boolean}}},
1414
control-interrupt-stop? {:arities {1 {:args [:any],
1515
:ret :boolean}}},
16+
llm-tool-call-result? {:arities {1 {:args [:any], :ret :boolean}}},
1617
control-interrupt-start {:arities {1 {:args [:boolean],
1718
:ret {:op :keys,
1819
:req {:frame/type :any,
@@ -55,6 +56,11 @@
5556
:req {:frame/type :any,
5657
:frame/data :any,
5758
:frame/ts :any}}}}},
59+
llm-tool-call-chunk {:arities {1 {:args [:any],
60+
:ret {:op :keys,
61+
:req {:frame/type :any,
62+
:frame/data :any,
63+
:frame/ts :any}}}}},
5864
system-config-change? {:arities {1 {:args [:any], :ret :boolean}}},
5965
user-speech-start {:arities {1 {:args [:boolean],
6066
:ret {:op :keys,
@@ -86,11 +92,17 @@
8692
:req {:frame/type :any,
8793
:frame/data :any,
8894
:frame/ts :any}}}}},
95+
llm-tool-call-result {:arities {1 {:args [:any],
96+
:ret {:op :keys,
97+
:req {:frame/type :any,
98+
:frame/data :any,
99+
:frame/ts :any}}}}},
89100
control-bot-interrupt {:arities {1 {:args [:boolean],
90101
:ret {:op :keys,
91102
:req {:frame/type :any,
92103
:frame/data :boolean,
93104
:frame/ts :any}}}}},
105+
llm-tool-call-chunk? {:arities {1 {:args [:any], :ret :boolean}}},
94106
system-start {:arities {1 {:args [:boolean],
95107
:ret {:op :keys,
96108
:req {:frame/type :any,

core/src/voice_fn/processors/llm_context_aggregator.clj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ S: Start, E: End, T: Transcription, I: Interim, X: Text
210210
(t/log! {:level :debug :id id} "START FRAME"))
211211
[(assoc state
212212
:content-aggregation nil
213+
:function-name nil
214+
:function-arguments nil
215+
:tool-call-id nil
213216
:aggregating? true
214217
:seen-start-frame? true
215218
:seen-end-frame? false

core/test/voice_fn/processors/llm_context_aggregator_test.clj

Lines changed: 50 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,7 @@
4545

4646
(facts
4747
"about user speech aggregation"
48-
(let [config {:messages/role "user"
49-
:llm/context {:messages [{:role :assistant :content "You are a helpful assistant"}]}
50-
:aggregator/start-frame? frame/user-speech-start?
51-
:aggregator/end-frame? frame/user-speech-stop?
52-
:aggregator/accumulator-frame? frame/transcription?
53-
:aggregator/interim-results-frame? frame/transcription-interim?
54-
:aggregator/handles-interrupt? false ;; User speaking shouldn't be interrupted
55-
:aggregator/debug? false}
48+
(let [config {:llm/context {:messages [{:role :assistant :content "You are a helpful assistant"}]}}
5649
state (partial merge config)
5750
sstate (state {:aggregating? true
5851
:aggregation ""
@@ -85,10 +78,10 @@
8578
:seen-start-frame? false})]
8679

8780
(fact "S T E -> X"
88-
(sut/aggregator-transform config nil
89-
(frame/user-speech-start true)) => [sstate]
90-
(sut/aggregator-transform sstate nil (frame/transcription "Hello there")) => [ststate]
91-
(let [[next-state {:keys [out]}] (sut/aggregator-transform ststate nil (frame/user-speech-stop true))
81+
(sut/user-aggregator-transform config nil
82+
(frame/user-speech-start true)) => [sstate]
83+
(sut/user-aggregator-transform sstate nil (frame/transcription "Hello there")) => [ststate]
84+
(let [[next-state {:keys [out]}] (sut/user-aggregator-transform ststate nil (frame/user-speech-stop true))
9285
frame (first out)]
9386
next-state => stestate
9487
(:frame/type frame) => :frame.llm/context
@@ -101,103 +94,92 @@
10194
:seen-end-frame? true
10295
:seen-interim-results? false
10396
:seen-start-frame? false})]
104-
(sut/aggregator-transform sstate nil (frame/user-speech-stop true)) => [sestate]
97+
(sut/user-aggregator-transform sstate nil (frame/user-speech-stop true)) => [sestate]
10598

106-
(let [[next-state {:keys [out]}] (sut/aggregator-transform sestate nil (frame/transcription "Hello there"))
99+
(let [[next-state {:keys [out]}] (sut/user-aggregator-transform sestate nil (frame/transcription "Hello there"))
107100
frame (first out)]
108101
next-state => (state stestate)
109102
(:frame/type frame) => :frame.llm/context
110103
(:frame/data frame) => {:messages [{:content "You are a helpful assistant" :role :assistant}
111104
{:content "Hello there" :role "user"}]})))
112105
(fact "S I T E -> X"
113-
(sut/aggregator-transform sstate nil (frame/transcription-interim "Hello there")) => [sistate]
114-
(sut/aggregator-transform sistate nil (frame/transcription "Hello there")) => [ststate])
106+
(sut/user-aggregator-transform sstate nil (frame/transcription-interim "Hello there")) => [sistate]
107+
(sut/user-aggregator-transform sistate nil (frame/transcription "Hello there")) => [ststate])
115108

116109
(fact "S I E I T -> X"
117-
(sut/aggregator-transform sistate nil (frame/user-speech-stop true)) => [siestate]
118-
(sut/aggregator-transform siestate nil (frame/transcription-interim "Hello, there")) => [siestate]
119-
(let [[next-state {:keys [out]}] (sut/aggregator-transform siestate nil (frame/transcription "Hello there"))
110+
(sut/user-aggregator-transform sistate nil (frame/user-speech-stop true)) => [siestate]
111+
(sut/user-aggregator-transform siestate nil (frame/transcription-interim "Hello, there")) => [siestate]
112+
(let [[next-state {:keys [out]}] (sut/user-aggregator-transform siestate nil (frame/transcription "Hello there"))
120113
frame (first out)]
121114
next-state => (state stestate)
122115
(:frame/type frame) => :frame.llm/context
123116
(:frame/data frame) => {:messages [{:content "You are a helpful assistant" :role :assistant}
124117
{:content "Hello there" :role "user"}]}))
125-
(fact "updates current context if a frame is received"
118+
(fact "updates current context if a context frame is received"
126119
(let [new-context {:messages [{:content "You are a helpful assistant" :role :assistant}
127120
{:content "Hello there" :role "user"}
128121
{:content "How can I help" :role :assistant}]}]
129-
(sut/aggregator-transform ststate nil (frame/llm-context new-context)) => [(assoc ststate :llm/context new-context)]))))
122+
(sut/user-aggregator-transform ststate nil (frame/llm-context new-context)) => [(assoc ststate :llm/context new-context) nil]))))
130123

131124
(facts
132125
"about assistant response aggregation"
133-
(let [config {:messages/role "assistant"
134-
:llm/context {:messages [{:role "assistant" :content "You are a helpful assistant"}
135-
{:role "user" :content "Hello there"}]}
136-
:aggregator/start-frame? frame/llm-full-response-start?
137-
:aggregator/end-frame? frame/llm-full-response-end?
138-
:aggregator/accumulator-frame? frame/llm-text-chunk?}
126+
(let [config {:llm/context {:messages [{:role "assistant" :content "You are a helpful assistant"}
127+
{:role "user" :content "Hello there"}]}}
139128
state (partial merge config)
140129
;; State after start frame
141130
sstate (state {:aggregating? true
142-
:aggregation ""
131+
:function-arguments nil
132+
:function-name nil
133+
:tool-call-id nil
134+
:content-aggregation nil
143135
:seen-end-frame? false
144136
:seen-interim-results? false
145137
:seen-start-frame? true})
146138
;; State after text accumulation
147139
ststate (state {:aggregating? true
148-
:aggregation "Hi! How can I help you?"
140+
:content-aggregation "Hi! How can I help you?"
141+
:function-arguments nil
142+
:function-name nil
143+
:tool-call-id nil
149144
:seen-end-frame? false
150145
:seen-interim-results? false
151146
:seen-start-frame? true})
152147
;; State after complete sequence (final state)
153148
stestate (state {:aggregating? false
154-
:aggregation ""
149+
:content-aggregation nil
150+
:function-arguments nil
151+
:function-name nil
152+
:tool-call-id nil
155153
:seen-end-frame? false
156154
:seen-interim-results? false
157155
:seen-start-frame? false
158156
:llm/context {:messages [{:role "assistant" :content "You are a helpful assistant"}
159157
{:role "user" :content "Hello there"}
160-
{:role "assistant" :content "Hi! How can I help you?"}]}})]
158+
{:role :assistant
159+
:content [{:text "Hi! How can I help you?" :type :text}]}]}})]
161160

162161
(fact "S T E -> X"
163-
(sut/aggregator-transform config nil
164-
(frame/llm-full-response-start true)) => [sstate]
165-
(sut/aggregator-transform sstate nil
166-
(frame/llm-text-chunk "Hi! How can I help you?")) => [ststate]
167-
(let [[next-state {:keys [out]}] (sut/aggregator-transform ststate nil
168-
(frame/llm-full-response-end true))
162+
(sut/assistant-aggregator-transform config nil
163+
(frame/llm-full-response-start true)) => [sstate]
164+
(sut/assistant-aggregator-transform sstate nil
165+
(frame/llm-text-chunk "Hi! How can I help you?")) => [ststate]
166+
(let [[next-state {:keys [out]}] (sut/assistant-aggregator-transform ststate nil
167+
(frame/llm-full-response-end true))
169168
frame (first out)]
170169
next-state => stestate
171170
(:frame/type frame) => :frame.llm/context
172171
(:frame/data frame) => {:messages [{:role "assistant" :content "You are a helpful assistant"}
173172
{:role "user" :content "Hello there"}
174-
{:role "assistant" :content "Hi! How can I help you?"}]}))
175-
176-
(fact "S E T -> X"
177-
(let [sestate (state {:aggregating? true
178-
:aggregation ""
179-
:seen-end-frame? true
180-
:seen-interim-results? false
181-
:seen-start-frame? false})]
182-
(sut/aggregator-transform sstate nil
183-
(frame/llm-full-response-end true)) => [sestate]
184-
185-
(let [[next-state {:keys [out]}] (sut/aggregator-transform sestate nil
186-
(frame/llm-text-chunk "Hi! How can I help you?"))
187-
frame (first out)]
188-
next-state => stestate
189-
(:frame/type frame) => :frame.llm/context
190-
(:frame/data frame) => {:messages [{:role "assistant" :content "You are a helpful assistant"}
191-
{:role "user" :content "Hello there"}
192-
{:role "assistant" :content "Hi! How can I help you?"}]})))
173+
{:role :assistant
174+
:content [{:text "Hi! How can I help you?" :type :text}]}]}))
193175

194176
(fact "S T T T T T E -> X (streaming tokens pattern)"
195177
(let [token-chunks ["Hi" "!" " How" " can" " I" " help" " you" "?"]
196178
expected-response "Hi! How can I help you?"
197179

198180
;; Accumulate all token chunks
199181
final-state (reduce (fn [current-state frame]
200-
(let [[next-state] (sut/aggregator-transform
182+
(let [[next-state] (sut/assistant-aggregator-transform
201183
current-state
202184
nil
203185
frame)]
@@ -206,38 +188,41 @@
206188
(map frame/llm-text-chunk token-chunks))
207189

208190
;; Final state after end frame
209-
[next-state {:keys [out]}] (sut/aggregator-transform
191+
[next-state {:keys [out]}] (sut/assistant-aggregator-transform
210192
final-state
211193
nil
212194
(frame/llm-full-response-end true))
213195
frame (first out)]
214196

215197
;; Verify intermediate state has accumulated all tokens
216-
(get final-state :aggregation) => expected-response
198+
(get final-state :content-aggregation) => expected-response
217199

218200
;; Verify final state and output
219201
next-state => (state {:aggregating? false
220-
:aggregation ""
202+
:content-aggregation nil
203+
:function-arguments nil
204+
:function-name nil
205+
:tool-call-id nil
221206
:seen-end-frame? false
222207
:seen-interim-results? false
223208
:seen-start-frame? false
224209
:llm/context {:messages [{:role "assistant"
225210
:content "You are a helpful assistant"}
226211
{:role "user"
227212
:content "Hello there"}
228-
{:role "assistant"
229-
:content expected-response}]}})
213+
{:role :assistant
214+
:content [{:text expected-response :type :text}]}]}})
230215

231216
(:frame/type frame) => :frame.llm/context
232217
(:frame/data frame) => {:messages [{:role "assistant"
233218
:content "You are a helpful assistant"}
234219
{:role "user"
235220
:content "Hello there"}
236-
{:role "assistant"
237-
:content expected-response}]}))
221+
{:role :assistant
222+
:content [{:text expected-response :type :text}]}]}))
238223

239224
(fact "updates current context if a frame is received"
240225
(let [new-context {:messages [{:content "You are a helpful assistant" :role :assistant}
241226
{:content "Hello there" :role "user"}
242227
{:content "How can I help" :role :assistant}]}]
243-
(sut/aggregator-transform ststate nil (frame/llm-context new-context)) => [(assoc ststate :llm/context new-context)]))))
228+
(sut/assistant-aggregator-transform ststate nil (frame/llm-context new-context)) => [(assoc ststate :llm/context new-context)]))))

0 commit comments

Comments
 (0)