fix(docs): map live VectorRAG result shapes (#5960)

* fix(docs): map live VectorRAG result shapes

* fix(docs): normalize optional VectorRAG fields

---------

Co-authored-by: Alexandre Teixeira <alexandremagteixeira@gmail.com>
This commit is contained in:
RaresKeY
2026-08-17 00:07:12 +01:00
committed by GitHub
co-authored by Alexandre Teixeira
parent ee252e7cd9
commit 8cb8b074a4
2 changed files with 111 additions and 12 deletions
+41 -11
View File
@@ -50,16 +50,46 @@ class DocsService:
List of DocChunk objects List of DocChunk objects
""" """
results = self.rag.search(query, k=top_k) results = self.rag.search(query, k=top_k)
return [ chunks = []
DocChunk(
text=r.get("text", r.get("content", "")), for result in results:
source=r.get("source", r.get("metadata", {}).get("source", "unknown")), if not isinstance(result, dict):
score=r.get("score", 0.0), continue
metadata=r.get("metadata"),
metadata = result.get("metadata")
if not isinstance(metadata, dict):
metadata = {}
text = result.get("document")
if text is None:
text = result.get("text")
if text is None:
text = result.get("content")
if text is None:
text = ""
source = result.get("source")
if source is None:
source = metadata.get("source")
if source is None:
source = "unknown"
score = result.get("similarity")
if score is None:
score = result.get("score")
if score is None:
score = 0.0
chunks.append(
DocChunk(
text=text,
source=source,
score=score,
metadata=metadata,
)
) )
for r in results
if isinstance(r, dict) return chunks
]
async def index(self, directory: str) -> IndexResult: async def index(self, directory: str) -> IndexResult:
""" """
@@ -73,8 +103,8 @@ class DocsService:
""" """
result = self.rag.index_personal_documents(directory) result = self.rag.index_personal_documents(directory)
return IndexResult( return IndexResult(
indexed=result.get("indexed", 0), indexed=result.get("indexed_count", result.get("indexed", 0)),
failed=result.get("failed", 0), failed=result.get("failed_count", result.get("failed", 0)),
errors=result.get("errors", []), errors=result.get("errors", []),
) )
+70 -1
View File
@@ -9,11 +9,18 @@ class _FakeRag:
def search(self, query, k=5): def search(self, query, k=5):
return [ return [
{"text": "alpha", "source": "a.txt", "score": 0.9}, {
"document": "alpha",
"metadata": {"source": "a.txt"},
"similarity": 0.9,
},
"corrupt-row", "corrupt-row",
None, None,
] ]
def index_personal_documents(self, directory):
return {"indexed_count": 7, "failed_count": 2, "errors": ["bad.pdf"]}
def test_query_skips_non_dict_rag_rows(): def test_query_skips_non_dict_rag_rows():
# Bypass __init__ (it builds a real RAGManager / Chroma client) and inject # Bypass __init__ (it builds a real RAGManager / Chroma client) and inject
@@ -24,3 +31,65 @@ def test_query_skips_non_dict_rag_rows():
# old code called r.get(...) on the str/None rows and raised AttributeError. # old code called r.get(...) on the str/None rows and raised AttributeError.
assert [c.text for c in out] == ["alpha"] assert [c.text for c in out] == ["alpha"]
assert out[0].source == "a.txt" assert out[0].source == "a.txt"
assert out[0].score == 0.9
def test_index_maps_live_vectorrag_result_shape():
svc = DocsService.__new__(DocsService)
svc.rag = _FakeRag()
out = asyncio.run(svc.index("/documents"))
assert out.indexed == 7
assert out.failed == 2
assert out.errors == ["bad.pdf"]
def test_query_normalizes_null_canonical_fields_and_malformed_metadata():
class _MalformedRag:
def search(self, query, k=5):
return [
{
"document": None,
"text": "legacy text",
"source": None,
"similarity": None,
"score": 0.4,
"metadata": "not-a-dict",
},
{
"document": "canonical zero",
"similarity": 0.0,
"metadata": {"source": "nested.txt"},
},
{
"document": None,
"text": None,
"content": "content fallback",
"similarity": 0.2,
"metadata": ["unexpected"],
},
]
svc = DocsService.__new__(DocsService)
svc.rag = _MalformedRag()
out = asyncio.run(svc.query("query"))
assert [chunk.text for chunk in out] == [
"legacy text",
"canonical zero",
"content fallback",
]
assert out[0].source == "unknown"
assert out[0].score == 0.4
assert out[0].metadata == {}
assert out[1].source == "nested.txt"
assert out[1].score == 0.0
assert out[1].metadata == {"source": "nested.txt"}
assert out[2].source == "unknown"
assert out[2].score == 0.2
assert out[2].metadata == {}