Skip to content

Commit 06cf60f

Browse files
authored
fix(types): make RetrievalResult.score Optional[float] to match API null return (#27)
* feat: add optional decision_trace field to RetrievalQueryResponse and update tests * fix(types): make RetrievalResult.score Optional[float] to match API null return The agentic retrieval route now returns null for score when no real score is available (navigation-only chunks). Previously the SDK model declared score as float which would fail Pydantic validation on null. score: float → Optional[float] = None
1 parent d439490 commit 06cf60f

2 files changed

Lines changed: 17 additions & 4 deletions

File tree

src/knowhere/types/retrieval.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
from typing import Literal, Optional, TypedDict
5+
from typing import Any, Literal, Optional, TypedDict
66

77
from pydantic import BaseModel, Field
88

@@ -31,7 +31,7 @@ class RetrievalResult(BaseModel):
3131

3232
chunk_type: str
3333
content: str
34-
score: float
34+
score: Optional[float] = None
3535
asset_url: Optional[str] = None
3636
source: RetrievalSource
3737

@@ -51,8 +51,11 @@ class RetrievalReferencedChunk(BaseModel):
5151
class RetrievalQueryResponse(BaseModel):
5252
"""Response from ``POST /v1/retrieval/query``.
5353
54-
Agentic retrieval may also include ``evidence_text``, ``stop_reason``,
55-
and ``failure_reason`` when the server returns workflow diagnostics.
54+
Three PRIMARY output fields for downstream agent consumption:
55+
56+
- ``evidence_text``: hierarchical evidence tree for LLM context
57+
- ``decision_trace``: per-step navigation decisions (includes stop/failure)
58+
- ``referenced_chunks``: structured chunk citations for follow-up queries
5659
"""
5760

5861
namespace: str
@@ -64,3 +67,4 @@ class RetrievalQueryResponse(BaseModel):
6467
stop_reason: Optional[str] = None
6568
failure_reason: Optional[str] = None
6669
results: list[RetrievalResult]
70+
decision_trace: Optional[list[dict[str, Any]]] = None

tests/test_retrieval.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ def _make_retrieval_response() -> Dict[str, Any]:
2424
"evidence_text": "Rendered retrieval evidence",
2525
"stop_reason": "answer_done",
2626
"failure_reason": "insufficient evidence",
27+
"decision_trace": [
28+
{"phase": "discovery", "action": "select_documents", "selected": ["doc_123"]},
29+
{"phase": "terminal", "action": "complete", "stop_reason": "answer_done", "failure_reason": "insufficient evidence"},
30+
],
2731
"referenced_chunks": [
2832
{
2933
"chunk_id": "chunk_001",
@@ -228,6 +232,10 @@ def test_agentic_response_fields(self, sync_client: Any) -> None:
228232
assert response.evidence_text == "Rendered retrieval evidence"
229233
assert response.stop_reason == "answer_done"
230234
assert response.failure_reason == "insufficient evidence"
235+
assert response.decision_trace is not None
236+
assert len(response.decision_trace) == 2
237+
assert response.decision_trace[0]["phase"] == "discovery"
238+
assert response.decision_trace[-1]["phase"] == "terminal"
231239

232240
@respx.mock
233241
def test_legacy_response_without_agentic_fields(self, sync_client: Any) -> None:
@@ -242,3 +250,4 @@ def test_legacy_response_without_agentic_fields(self, sync_client: Any) -> None:
242250

243251
assert response.answer_text is None
244252
assert response.referenced_chunks == []
253+
assert response.decision_trace is None

0 commit comments

Comments
 (0)