@@ -133,6 +133,33 @@ func TestInFlightLoadProducer_Produce(t *testing.T) {
133133 require .False (t , ok , "InFlightLoad should not be populated by Produce" )
134134}
135135
136+ func TestInFlightLoadProducer_ProduceUsesLiteralCachedBlocks (t * testing.T ) {
137+ t .Parallel ()
138+
139+ // Initialize our load producer.
140+ producer := newTestProducer (t )
141+ // Disable output token estimation so we can test input tokens cleanly (output = 0).
142+ producer .addEstimatedOutputTokens = false
143+
144+ // Create a stub endpoint representing our model-serving pod.
145+ endpoint := newStubSchedulingEndpoint ("precise-cache-endpoint" )
146+ // Inject mock prefix cache information onto this endpoint.
147+ // matchBlocks = 1 (weighted), cachedBlockCount = 2 (literal), totalBlocks = 2, blockSizeTokens = 4.
148+ endpoint .Put (
149+ attrprefix .PrefixCacheMatchInfoDataKey .String (),
150+ attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 4 ).WithCachedBlockCount (2 ),
151+ )
152+
153+ // Trigger the Produce logic with an 8-token request.
154+ err := producer .Produce (context .Background (), makeTokenRequest ("req-precise" , 8 ), []fwksched.Endpoint {endpoint })
155+ require .NoError (t , err )
156+
157+ // Assert the produced output is exactly 0 uncached tokens.
158+ value , ok := endpoint .Get (producer .uncachedRequestTokensDk .String ())
159+ require .True (t , ok )
160+ require .Equal (t , int64 (0 ), value .(* attrconcurrency.UncachedRequestTokens ).Tokens )
161+ }
162+
136163func TestInFlightLoadProducer_Extract (t * testing.T ) {
137164 t .Parallel ()
138165
@@ -648,23 +675,27 @@ func TestInFlightLoadProducer_ExcludeOutputTokens_SingleChunk(t *testing.T) {
648675}
649676
650677// TestInFlightLoadProducer_PrefixCacheDiscount verifies that when PrefixCacheMatchInfo
651- // is published on the endpoint, the matched prefix is excluded from the tracked input
652- // tokens, and that release subtracts the same (discounted) amount.
678+ // is published on the endpoint, the literal cached prefix is excluded from the tracked
679+ // input tokens, and that release subtracts the same (discounted) amount.
653680func TestInFlightLoadProducer_PrefixCacheDiscount (t * testing.T ) {
654681 t .Parallel ()
655682
683+ // Setup the tracker database and context.
656684 producer := newTestProducer (t )
657685 ctx := context .Background ()
658686 endpointName := "prefix-cache-endpoint"
659687 endpointID := fullEndpointName (endpointName )
660688
661689 // 8 input tokens. Output = 8 * 1.5 = 12.
662- // With block_size=4, total=2 blocks, matched=1 block (4 tokens cached):
663- // uncached_input = (2-1)*4 + max(0, 8-2*4) = 4
664- // total tokens = 4 + 12 = 16
690+ // With block_size=4 and total=2 blocks, the tier-weighted match is 1 block,
691+ // but both blocks are cached. The tracked total therefore contains only output.
665692 endpoint := newStubSchedulingEndpoint (endpointName )
666- endpoint .Put (attrprefix .PrefixCacheMatchInfoDataKey .String (), attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 4 ))
693+ endpoint .Put (
694+ attrprefix .PrefixCacheMatchInfoDataKey .String (),
695+ attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 4 ).WithCachedBlockCount (2 ),
696+ )
667697
698+ // Create an 8-token input request (with 12 estimated output tokens).
668699 req := makeTokenRequest ("req-prefix" , 8 )
669700 res := & fwksched.SchedulingResult {
670701 PrimaryProfileName : "default" ,
@@ -673,10 +704,11 @@ func TestInFlightLoadProducer_PrefixCacheDiscount(t *testing.T) {
673704 },
674705 }
675706
707+ // Simulate dispatch (PreRequest Phase) adding request weight to trackers.
676708 producer .PreRequest (ctx , req , res )
677709 require .Equal (t , int64 (1 ), producer .requestTracker .get (endpointID ))
678- require .Equal (t , int64 (16 ), producer .tokenTracker .get (endpointID ),
679- "only uncached input (4) plus output (12) should be tracked" )
710+ require .Equal (t , int64 (12 ), producer .tokenTracker .get (endpointID ),
711+ "only output tokens should be tracked for a fully cached input " )
680712
681713 // Release uses the exact stored value, returning to zero.
682714 req .SchedulingResult = res
@@ -915,23 +947,95 @@ func TestInFlightLoadProducer_AtomicTokenRelease_Concurrent(t *testing.T) {
915947 require .Equal (t , int64 (0 ), producer .requestTracker .get (endpointID ))
916948}
917949
918- func TestUncachedInputTokens_Overestimate (t * testing.T ) {
919- // Setup:
920- // inputTokens (estimated) = 5
921- // PrefixCacheMatchInfo: matchBlocks=1, totalBlocks=2, blockSizeTokens=4
922- // indexedTokens = 2 * 4 = 8
923- // matchedTokens = 1 * 4 = 4
924-
925- endpoint := newStubSchedulingEndpoint ("test-ep" )
926- endpoint .Put (attrprefix .PrefixCacheMatchInfoDataKey .String (), attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 4 ))
950+ func TestUncachedInputTokens (t * testing.T ) {
951+ t .Parallel ()
927952
928- inputTokens := int64 (5 )
953+ const key = "prefix-match-info"
954+ tests := []struct {
955+ name string
956+ inputTokens int64
957+ info datalayer.Cloneable
958+ noEndpoint bool
959+ want int64
960+ }{
961+ // Case: Missing/nil components should default back to treating the entire prompt as uncached.
962+ {name : "nil endpoint" , inputTokens : 8 , noEndpoint : true , want : 8 },
963+ {name : "negative input without endpoint" , inputTokens : - 1 , noEndpoint : true , want : 0 },
964+ {name : "missing prefix information" , inputTokens : 8 , want : 8 },
965+ {name : "wrong prefix information type" , inputTokens : 8 , info : & attrconcurrency.InFlightLoad {}, want : 8 },
966+ // Case: Literal count differs from weighted match (our big fix for offloaded caches).
967+ {
968+ name : "literal count differs from weighted match" ,
969+ inputTokens : 4096 ,
970+ info : attrprefix .NewPrefixCacheMatchInfo (204 , 256 , 16 ).
971+ WithCachedBlockCount (256 ),
972+ want : 0 ,
973+ },
974+ // Case: Partially cached precise prefix.
975+ {
976+ name : "partially cached precise prefix" ,
977+ inputTokens : 4096 ,
978+ info : attrprefix .NewPrefixCacheMatchInfo (128 , 256 , 16 ).
979+ WithCachedBlockCount (192 ),
980+ want : 1024 ,
981+ },
982+ // Case: Unindexed tail (prompt length exceeds maximum indexed range).
983+ {
984+ name : "unindexed tail" ,
985+ inputTokens : 4096 ,
986+ info : attrprefix .NewPrefixCacheMatchInfo (128 , 128 , 16 ).
987+ WithCachedBlockCount (128 ),
988+ want : 2048 ,
989+ },
990+ {
991+ name : "partial final block" ,
992+ inputTokens : 10 ,
993+ info : attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 4 ),
994+ want : 6 ,
995+ },
996+ // Case: Backward compatibility test (defaults cached count to match blocks).
997+ {
998+ name : "approximate producer compatibility" ,
999+ inputTokens : 4096 ,
1000+ info : attrprefix .NewPrefixCacheMatchInfo (128 , 256 , 16 ),
1001+ want : 2048 ,
1002+ },
1003+ {
1004+ name : "invalid block size" ,
1005+ inputTokens : 8 ,
1006+ info : attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 0 ),
1007+ want : 8 ,
1008+ },
1009+ // Case: Clamped bounds safety check.
1010+ {
1011+ name : "cached count above total blocks" ,
1012+ inputTokens : 8 ,
1013+ info : attrprefix .NewPrefixCacheMatchInfo (2 , 2 , 4 ).
1014+ WithCachedBlockCount (3 ),
1015+ want : 0 ,
1016+ },
1017+ {
1018+ name : "prefix count trusted over smaller estimate" ,
1019+ inputTokens : 5 ,
1020+ info : attrprefix .NewPrefixCacheMatchInfo (1 , 2 , 4 ),
1021+ want : 4 ,
1022+ },
1023+ }
9291024
930- uncached := uncachedInputTokens (endpoint , inputTokens , attrprefix .PrefixCacheMatchInfoDataKey .String ())
1025+ for _ , tt := range tests {
1026+ t .Run (tt .name , func (t * testing.T ) {
1027+ var endpoint fwksched.Endpoint
1028+ if ! tt .noEndpoint {
1029+ stub := newStubSchedulingEndpoint ("test-endpoint" )
1030+ if tt .info != nil {
1031+ stub .Put (key , tt .info )
1032+ }
1033+ endpoint = stub
1034+ }
9311035
932- // When the prefix cache says 4 tokens are definitely uncached in the indexed portion (8-4),
933- // we trust that over the smaller (approximate) estimate of 5.
934- require . Equal ( t , int64 ( 4 ), uncached , "should trust the prefix cache's uncached count (indexed-matched) over the smaller estimate" )
1036+ require . Equal ( t , tt . want , uncachedInputTokens ( endpoint , tt . inputTokens , key ))
1037+ })
1038+ }
9351039}
9361040
9371041func TestInFlightLoadProducer_PanicSafety (t * testing.T ) {
0 commit comments