@@ -398,5 +398,124 @@ var _ = Describe("ComputeChoices", func() {
398398 Expect (choices ).To (HaveLen (1 ))
399399 Expect (streamedTokens ).To (Equal ([]string {"Hello" , " world" }))
400400 })
401+
402+ It ("should pass chat deltas through TokenUsage during streaming" , func () {
403+ var receivedDeltas [][]* pb.ChatDelta
404+ backend .ModelInferenceFunc = func (
405+ ctx context.Context , s string , messages schema.Messages ,
406+ images , videos , audios []string ,
407+ loader * model.ModelLoader , c * config.ModelConfig , cl * config.ModelConfigLoader ,
408+ o * config.ApplicationConfig ,
409+ tokenCallback func (string , backend.TokenUsage ) bool ,
410+ tools , toolChoice string ,
411+ logprobs , topLogprobs * int ,
412+ logitBias map [string ]float64 ,
413+ metadata map [string ]string ,
414+ ) (func () (backend.LLMResponse , error ), error ) {
415+ predFunc := func () (backend.LLMResponse , error ) {
416+ if tokenCallback != nil {
417+ // Simulate C++ autoparser sending reasoning in chat deltas
418+ tokenCallback ("<|channel>thought\n thinking\n <channel|>" , backend.TokenUsage {
419+ Prompt : 5 ,
420+ ChatDeltas : []* pb.ChatDelta {
421+ {ReasoningContent : "thinking" },
422+ },
423+ })
424+ tokenCallback ("Hello!" , backend.TokenUsage {
425+ Prompt : 5 , Completion : 3 ,
426+ ChatDeltas : []* pb.ChatDelta {
427+ {Content : "Hello!" },
428+ },
429+ })
430+ }
431+ return backend.LLMResponse {
432+ Response : "<|channel>thought\n thinking\n <channel|>Hello!" ,
433+ Usage : backend.TokenUsage {Prompt : 5 , Completion : 3 },
434+ ChatDeltas : []* pb.ChatDelta {
435+ {ReasoningContent : "thinking" },
436+ {Content : "Hello!" },
437+ },
438+ }, nil
439+ }
440+ return predFunc , nil
441+ }
442+
443+ choices , _ , deltas , err := ComputeChoices (
444+ makeReq (), "test" , cfg , nil , appCfg , nil ,
445+ func (s string , c * []schema.Choice ) {
446+ * c = append (* c , schema.Choice {Text : s })
447+ },
448+ func (s string , usage backend.TokenUsage ) bool {
449+ // Capture chat deltas received per-chunk
450+ if len (usage .ChatDeltas ) > 0 {
451+ receivedDeltas = append (receivedDeltas , usage .ChatDeltas )
452+ }
453+ return true
454+ },
455+ )
456+ Expect (err ).ToNot (HaveOccurred ())
457+ Expect (choices ).To (HaveLen (1 ))
458+
459+ // Verify per-chunk deltas were received during streaming
460+ Expect (receivedDeltas ).To (HaveLen (2 ))
461+ Expect (receivedDeltas [0 ][0 ].ReasoningContent ).To (Equal ("thinking" ))
462+ Expect (receivedDeltas [1 ][0 ].Content ).To (Equal ("Hello!" ))
463+
464+ // Verify final accumulated deltas are also returned
465+ Expect (deltas ).To (HaveLen (2 ))
466+ Expect (deltas [0 ].ReasoningContent ).To (Equal ("thinking" ))
467+ Expect (deltas [1 ].Content ).To (Equal ("Hello!" ))
468+ })
469+
470+ It ("should prefer chat deltas over raw text when HasChatDeltaContent is true" , func () {
471+ // Verify that the callback can distinguish between
472+ // chunks with and without chat deltas
473+ var withDeltas , withoutDeltas int
474+ backend .ModelInferenceFunc = func (
475+ ctx context.Context , s string , messages schema.Messages ,
476+ images , videos , audios []string ,
477+ loader * model.ModelLoader , c * config.ModelConfig , cl * config.ModelConfigLoader ,
478+ o * config.ApplicationConfig ,
479+ tokenCallback func (string , backend.TokenUsage ) bool ,
480+ tools , toolChoice string ,
481+ logprobs , topLogprobs * int ,
482+ logitBias map [string ]float64 ,
483+ metadata map [string ]string ,
484+ ) (func () (backend.LLMResponse , error ), error ) {
485+ predFunc := func () (backend.LLMResponse , error ) {
486+ if tokenCallback != nil {
487+ // Chunk with chat deltas (C++ autoparser active)
488+ tokenCallback ("raw-text" , backend.TokenUsage {
489+ ChatDeltas : []* pb.ChatDelta {{Content : "parsed-content" }},
490+ })
491+ // Chunk without chat deltas (fallback)
492+ tokenCallback ("fallback-text" , backend.TokenUsage {})
493+ }
494+ return backend.LLMResponse {Response : "raw-textfallback-text" }, nil
495+ }
496+ return predFunc , nil
497+ }
498+
499+ _ , _ , _ , err := ComputeChoices (
500+ makeReq (), "test" , cfg , nil , appCfg , nil ,
501+ func (s string , c * []schema.Choice ) {
502+ * c = append (* c , schema.Choice {Text : s })
503+ },
504+ func (s string , usage backend.TokenUsage ) bool {
505+ if usage .HasChatDeltaContent () {
506+ withDeltas ++
507+ r , c := usage .ChatDeltaReasoningAndContent ()
508+ Expect (c ).To (Equal ("parsed-content" ))
509+ Expect (r ).To (BeEmpty ())
510+ } else {
511+ withoutDeltas ++
512+ }
513+ return true
514+ },
515+ )
516+ Expect (err ).ToNot (HaveOccurred ())
517+ Expect (withDeltas ).To (Equal (1 ))
518+ Expect (withoutDeltas ).To (Equal (1 ))
519+ })
401520 })
402521})
0 commit comments