@@ -88,12 +88,12 @@ func (g *GeminiAdapter) GenerateStreamContent(
88
88
iter := cs .SendMessageStream (ctx , messages [len (messages )- 1 ].Parts ... )
89
89
90
90
dataChan := make (chan string )
91
- go handleStreamIter (g .model , iter , dataChan )
91
+ go handleStreamIter (g .model , iter , dataChan , req . StreamOptions . IncludeUsage )
92
92
93
93
return dataChan , nil
94
94
}
95
95
96
- func handleStreamIter (model string , iter * genai.GenerateContentResponseIterator , dataChan chan string ) {
96
+ func handleStreamIter (model string , iter * genai.GenerateContentResponseIterator , dataChan chan string , sendUsage bool ) {
97
97
defer close (dataChan )
98
98
99
99
respID := util .GetUUID ()
@@ -157,6 +157,28 @@ func handleStreamIter(model string, iter *genai.GenerateContentResponseIterator,
157
157
dataChan <- string (resp )
158
158
}
159
159
160
+ sendUsageMetadata := func (usage * genai.UsageMetadata ) {
161
+ if usage == nil || ! sendUsage {
162
+ return
163
+ }
164
+ openaiResp := & CompletionResponse {
165
+ ID : fmt .Sprintf ("chatcmpl-%s" , respID ),
166
+ Object : "chat.completion.chunk" ,
167
+ Created : created ,
168
+ Model : GetMappedModel (model ),
169
+ Choices : []CompletionChoice {},
170
+ Usage : openai.Usage {
171
+ PromptTokens : int (usage .PromptTokenCount ),
172
+ CompletionTokens : int (usage .CandidatesTokenCount ),
173
+ TotalTokens : int (usage .TotalTokenCount ),
174
+ },
175
+ }
176
+ resp , _ := json .Marshal (openaiResp )
177
+ dataChan <- string (resp )
178
+ }
179
+
180
+ var usageMetadata * genai.UsageMetadata
181
+
160
182
for {
161
183
genaiResp , err := iter .Next ()
162
184
if err == iterator .Done {
@@ -165,6 +187,9 @@ func handleStreamIter(model string, iter *genai.GenerateContentResponseIterator,
165
187
// Send all remaining text at once when done
166
188
sendFullText (textBuffer )
167
189
}
190
+ // per https://community.openai.com/t/usage-stats-now-available-when-using-streaming-with-the-chat-completions-api-or-completions-api/738156
191
+ // the usage is sent after everything else
192
+ sendUsageMetadata (usageMetadata )
168
193
break
169
194
}
170
195
@@ -208,6 +233,8 @@ func handleStreamIter(model string, iter *genai.GenerateContentResponseIterator,
208
233
dataChan <- string (resp )
209
234
break
210
235
}
236
+ // gemini returns the usage data on each response, adding to it each time, so always get the latest
237
+ usageMetadata = genaiResp .UsageMetadata
211
238
212
239
// Process each candidate's text content
213
240
for _ , candidate := range genaiResp .Candidates {
0 commit comments