15
15
*/
16
16
17
17
import { StreamingCallback , z } from '@genkit-ai/core' ;
18
+ import { Channel } from '@genkit-ai/core/async' ;
18
19
import {
19
20
ATTR_PREFIX ,
20
21
SPAN_TYPE_ATTR ,
@@ -30,7 +31,6 @@ import {
30
31
MessageData ,
31
32
Part ,
32
33
generate ,
33
- generateStream ,
34
34
} from './index.js' ;
35
35
import {
36
36
BaseGenerateOptions ,
@@ -154,23 +154,12 @@ export class Chat {
154
154
} ,
155
155
} ,
156
156
async ( metadata ) => {
157
- let resolvedOptions : ChatGenerateOptions < O , CustomOptions > ;
157
+ let resolvedOptions = resolveSendOptions ( options ) ;
158
158
let streamingCallback :
159
159
| StreamingCallback < GenerateResponseChunk >
160
160
| undefined = undefined ;
161
161
162
- // string
163
- if ( typeof options === 'string' ) {
164
- resolvedOptions = {
165
- prompt : options ,
166
- } as ChatGenerateOptions < O , CustomOptions > ;
167
- } else if ( Array . isArray ( options ) ) {
168
- // Part[]
169
- resolvedOptions = {
170
- prompt : options ,
171
- } as ChatGenerateOptions < O , CustomOptions > ;
172
- } else {
173
- resolvedOptions = options as ChatGenerateOptions < O , CustomOptions > ;
162
+ if ( resolvedOptions . onChunk || resolvedOptions . streamingCallback ) {
174
163
streamingCallback =
175
164
resolvedOptions . onChunk ?? resolvedOptions . streamingCallback ;
176
165
}
@@ -204,66 +193,23 @@ export class Chat {
204
193
CustomOptions extends z . ZodTypeAny = typeof GenerationCommonConfigSchema ,
205
194
> (
206
195
options : string | Part [ ] | GenerateStreamOptions < O , CustomOptions >
207
- ) : Promise < GenerateStreamResponse < z . infer < O > > > {
208
- return runWithSession ( this . session . registry , this . session , ( ) =>
209
- runInNewSpan (
210
- this . session . registry ,
211
- {
212
- metadata : { name : 'send' } ,
213
- labels : {
214
- [ SPAN_TYPE_ATTR ] : 'helper' ,
215
- [ SESSION_ID_ATTR ] : this . session . id ,
216
- [ THREAD_NAME_ATTR ] : this . threadName ,
217
- } ,
218
- } ,
219
- async ( metadata ) => {
220
- let resolvedOptions ;
221
-
222
- // string
223
- if ( typeof options === 'string' ) {
224
- resolvedOptions = {
225
- prompt : options ,
226
- } as GenerateStreamOptions < O , CustomOptions > ;
227
- } else if ( Array . isArray ( options ) ) {
228
- // Part[]
229
- resolvedOptions = {
230
- prompt : options ,
231
- } as GenerateStreamOptions < O , CustomOptions > ;
232
- } else {
233
- resolvedOptions = options as GenerateStreamOptions <
234
- O ,
235
- CustomOptions
236
- > ;
237
- }
238
- metadata . input = resolvedOptions ;
239
-
240
- const { response, stream } = await generateStream (
241
- this . session . registry ,
242
- {
243
- ...( await this . requestBase ) ,
244
- messages : this . messages ,
245
- ...resolvedOptions ,
246
- }
247
- ) ;
196
+ ) : GenerateStreamResponse < z . infer < O > > {
197
+ let channel = new Channel < GenerateResponseChunk > ( ) ;
198
+ let resolvedOptions = resolveSendOptions ( options ) ;
248
199
249
- return {
250
- response : response . finally ( async ( ) => {
251
- const resolvedResponse = await response ;
252
- this . requestBase = Promise . resolve ( {
253
- ...( await this . requestBase ) ,
254
- // these things may get changed by tools calling within generate.
255
- tools : resolvedResponse ?. request ?. tools ,
256
- toolChoice : resolvedResponse ?. request ?. toolChoice ,
257
- config : resolvedResponse ?. request ?. config ,
258
- } ) ;
259
- this . updateMessages ( resolvedResponse . messages ) ;
260
- metadata . output = JSON . stringify ( resolvedResponse ) ;
261
- } ) ,
262
- stream,
263
- } ;
264
- }
265
- )
200
+ const sent = this . send ( {
201
+ ...resolvedOptions ,
202
+ onChunk : ( chunk ) => channel . send ( chunk ) ,
203
+ } ) ;
204
+ sent . then (
205
+ ( ) => channel . close ( ) ,
206
+ ( err ) => channel . error ( err )
266
207
) ;
208
+
209
+ return {
210
+ response : sent ,
211
+ stream : channel ,
212
+ } ;
267
213
}
268
214
269
215
get messages ( ) : MessageData [ ] {
@@ -287,3 +233,27 @@ function getPreamble(msgs?: MessageData[]) {
287
233
function stripPreamble ( msgs ?: MessageData [ ] ) {
288
234
return msgs ?. filter ( ( m ) => ! m . metadata ?. preamble ) ;
289
235
}
236
+
237
+ function resolveSendOptions <
238
+ O extends z . ZodTypeAny ,
239
+ CustomOptions extends z . ZodTypeAny ,
240
+ > (
241
+ options : string | Part [ ] | ChatGenerateOptions < O , CustomOptions >
242
+ ) : ChatGenerateOptions < O , CustomOptions > {
243
+ let resolvedOptions : ChatGenerateOptions < O , CustomOptions > ;
244
+
245
+ // string
246
+ if ( typeof options === 'string' ) {
247
+ resolvedOptions = {
248
+ prompt : options ,
249
+ } as ChatGenerateOptions < O , CustomOptions > ;
250
+ } else if ( Array . isArray ( options ) ) {
251
+ // Part[]
252
+ resolvedOptions = {
253
+ prompt : options ,
254
+ } as ChatGenerateOptions < O , CustomOptions > ;
255
+ } else {
256
+ resolvedOptions = options as ChatGenerateOptions < O , CustomOptions > ;
257
+ }
258
+ return resolvedOptions ;
259
+ }
0 commit comments