@@ -116,3 +116,50 @@ async def fake_acompletion(**kwargs):
116116 assert [m ["role" ] for m in sent_msgs ] == ["user" , "assistant" ]
117117 assert [m .role for m in out .messages ] == ["user" , "assistant" , "assistant" ]
118118 assert out .messages [- 1 ].content == "Hello again"
119+
120+
121+ @pytest .mark .asyncio
122+ async def test_single_turn_handles_missing_usage_block (monkeypatch ):
123+ row = EvaluationRow (messages = [Message (role = "user" , content = "Describe the picture" )])
124+
125+ import eval_protocol .pytest .default_single_turn_rollout_process as mod
126+
127+ class StubChoices :
128+ pass
129+
130+ class StubModelResponse :
131+ def __init__ (self , text : str ):
132+ self .choices = [StubChoices ()]
133+ self .choices [0 ].message = SimpleNamespace (content = text , tool_calls = None )
134+ self .usage = None
135+
136+ async def fake_acompletion (** kwargs ):
137+ return StubModelResponse (text = "It looks like creme brulee" )
138+
139+ class StubLogger :
140+ def __init__ (self ):
141+ self .logged = []
142+
143+ def log (self , row ):
144+ self .logged .append (row )
145+
146+ def read (self , rollout_id = None ):
147+ return list (self .logged )
148+
149+ stub_logger = StubLogger ()
150+
151+ monkeypatch .setattr (mod , "ModelResponse" , StubModelResponse , raising = True )
152+ monkeypatch .setattr (mod , "Choices" , StubChoices , raising = True )
153+ monkeypatch .setattr (mod , "acompletion" , fake_acompletion , raising = True )
154+ monkeypatch .setattr (mod , "default_logger" , stub_logger , raising = False )
155+
156+ processor = SingleTurnRolloutProcessor ()
157+ config = _DummyConfig ()
158+
159+ tasks = processor ([row ], config )
160+ out = await tasks [0 ]
161+
162+ assert [m .role for m in out .messages ] == ["user" , "assistant" ]
163+ assert out .messages [- 1 ].content == "It looks like creme brulee"
164+ # Usage should remain unset when the provider omits it
165+ assert out .execution_metadata .usage is None
0 commit comments