Skip to content

Commit 7c44989

Browse files
test: add logprobs handling tests for chat completions
1 parent 9738475 commit 7c44989

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

tests/unit/test_openai_compat.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,86 @@ def test_generate_chat_reasoning_fallback() -> None:
123123
res = asyncio.run(backend.generate(prompt))
124124
assert res.text == "Just thinking"
125125
assert res.tokens == ["Just", "thinking"]
126+
127+
128+
def test_generate_chat_with_logprobs() -> None:
129+
backend = OpenAICompatBackend(base_url="http://127.0.0.1:8000", model_id="dummy", chat=True)
130+
prompt = Prompt(id="p1", text="Hello", max_tokens=10)
131+
132+
mock_response = httpx.Response(
133+
200,
134+
json={
135+
"choices": [
136+
{
137+
"message": {"content": "world"},
138+
"logprobs": {
139+
"content": [
140+
{
141+
"token": "world",
142+
"logprob": -0.1,
143+
"top_logprobs": [
144+
{"token": "world", "logprob": -0.1},
145+
{"token": "earth", "logprob": -2.0},
146+
],
147+
}
148+
]
149+
},
150+
}
151+
],
152+
"usage": {"completion_tokens": 1},
153+
},
154+
request=httpx.Request("POST", "http://127.0.0.1:8000/v1/chat/completions"),
155+
)
156+
157+
with patch("httpx.AsyncClient.post", return_value=mock_response):
158+
res = asyncio.run(backend.generate(prompt))
159+
assert res.text == "world"
160+
assert res.tokens == ["world"]
161+
assert res.logprobs == [-0.1]
162+
# top_logprobs are sorted by token: earth (-2.0), world (-0.1)
163+
assert res.distributions == [[-2.0, -0.1]]
164+
assert res.distribution_metadata == [{"id_0": "earth", "id_1": "world"}]
165+
166+
167+
def test_generate_chat_with_logprobs_nan_and_missing() -> None:
168+
backend = OpenAICompatBackend(base_url="http://127.0.0.1:8000", model_id="dummy", chat=True)
169+
prompt = Prompt(id="p1", text="Hello", max_tokens=10)
170+
171+
mock_response = httpx.Response(
172+
200,
173+
content=b"{}",
174+
request=httpx.Request("POST", "http://127.0.0.1:8000/v1/chat/completions"),
175+
)
176+
177+
# Use patch to return NaN for the raw logprob values to avoid JSON serialization issues in httpx.Response
178+
with (
179+
patch("httpx.AsyncClient.post", return_value=mock_response),
180+
patch(
181+
"httpx.Response.json",
182+
return_value={
183+
"choices": [
184+
{
185+
"message": {"content": "world"},
186+
"logprobs": {
187+
"content": [
188+
{
189+
"token": "world",
190+
"logprob": float("nan"),
191+
"top_logprobs": [
192+
{"token": "world", "logprob": float("nan")},
193+
{"token": "earth"},
194+
],
195+
}
196+
]
197+
},
198+
}
199+
],
200+
"usage": {"completion_tokens": 1},
201+
},
202+
),
203+
):
204+
res = asyncio.run(backend.generate(prompt))
205+
assert res.logprobs == [-9999.0]
206+
# top_logprobs sorted by token: earth (-9999.0), world (-9999.0)
207+
assert res.distributions == [[-9999.0, -9999.0]]
208+
assert res.distribution_metadata == [{"id_0": "earth", "id_1": "world"}]

0 commit comments

Comments
 (0)