mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-10 10:12:20 +02:00
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:
co-authored by
Alexandre Teixeira
parent
ee252e7cd9
commit
8cb8b074a4
+41
-11
@@ -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", []),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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 == {}
|
||||||
|
|||||||
Reference in New Issue
Block a user