Do not duplicate metadata items in inspector

This commit is contained in:
Lawrence Akka 2026-08-18 12:20:56 +02:00
parent 47feeb32ee
commit b221b4ac03
2 changed files with 60 additions and 16 deletions

View file

@ -4,7 +4,7 @@ from textual.app import ComposeResult
from textual.containers import VerticalScroll from textual.containers import VerticalScroll
from textual.widgets import Markdown, Static from textual.widgets import Markdown, Static
from haiku.rag.store.models import Chunk, Document, SearchResult from haiku.rag.store.models import Chunk, ChunkMetadata, Document, SearchResult
class ProvenanceData(Protocol): class ProvenanceData(Protocol):
@ -50,6 +50,21 @@ class DetailView(VerticalScroll):
parts.append(f"**DocItem Refs:** `{refs_str}`") parts.append(f"**DocItem Refs:** `{refs_str}`")
return parts return parts
def _format_extra_metadata(self, metadata: dict) -> list[str]:
"""Format raw metadata keys not already shown by `_format_provenance`.
`ChunkMetadata`'s own fields (page_numbers, headings, labels,
doc_item_refs) are excluded here since `_format_provenance` already
renders them, with its own truncation for long ref lists.
"""
extra = {
k: v for k, v in metadata.items() if k not in ChunkMetadata.model_fields
}
if not extra:
return []
metadata_str = "\n".join(f" - {k}: {v}" for k, v in extra.items())
return [f"**Metadata:**\n{metadata_str}"]
async def show_document(self, document: Document) -> None: async def show_document(self, document: Document) -> None:
"""Display document details.""" """Display document details."""
title = document.title or document.uri or "Untitled Document" title = document.title or document.uri or "Untitled Document"
@ -92,10 +107,7 @@ class DetailView(VerticalScroll):
chunk_meta = chunk.get_chunk_metadata() chunk_meta = chunk.get_chunk_metadata()
content_parts.extend(self._format_provenance(chunk_meta)) content_parts.extend(self._format_provenance(chunk_meta))
content_parts.extend(self._format_extra_metadata(chunk.metadata))
if chunk.metadata:
metadata_str = "\n".join(f" - {k}: {v}" for k, v in chunk.metadata.items())
content_parts.append(f"**Metadata:**\n{metadata_str}")
if chunk.embedding: if chunk.embedding:
content_parts.append(f"**Embedding:** {len(chunk.embedding)} dimensions") content_parts.append(f"**Embedding:** {len(chunk.embedding)} dimensions")
@ -124,12 +136,7 @@ class DetailView(VerticalScroll):
content_parts.append(f"**Score:** {search_result.score:.4f}") content_parts.append(f"**Score:** {search_result.score:.4f}")
content_parts.extend(self._format_provenance(search_result)) content_parts.extend(self._format_provenance(search_result))
content_parts.extend(self._format_extra_metadata(search_result.chunk_meta))
if search_result.chunk_meta:
metadata_str = "\n".join(
f" - {k}: {v}" for k, v in search_result.chunk_meta.items()
)
content_parts.append(f"**Metadata:**\n{metadata_str}")
if chunk.embedding: if chunk.embedding:
content_parts.append(f"**Embedding:** {len(chunk.embedding)} dimensions") content_parts.append(f"**Embedding:** {len(chunk.embedding)} dimensions")

View file

@ -167,8 +167,9 @@ async def test_document_list_tracks_has_more():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_detail_view_shows_chunk_metadata(): async def test_detail_view_shows_chunk_metadata():
"""show_chunk renders the raw chunk.metadata dict verbatim, not just the """show_chunk renders metadata keys _format_provenance doesn't already
typed provenance fields _format_provenance already covers.""" cover, but not a duplicate of the standard fields it does (headings,
page_numbers, labels, doc_item_refs)."""
from textual.app import App from textual.app import App
from haiku.rag.inspector.widgets.detail_view import DetailView from haiku.rag.inspector.widgets.detail_view import DetailView
@ -191,12 +192,40 @@ async def test_detail_view_shows_chunk_metadata():
source = detail_view.content_widget.source source = detail_view.content_widget.source
assert "**Metadata:**" in source assert "**Metadata:**" in source
assert "para_no: 12" in source assert "para_no: 12" in source
assert "headings:" not in source # already shown as **Section:**
@pytest.mark.asyncio
async def test_detail_view_omits_metadata_block_when_only_standard_fields():
"""No **Metadata:** block at all when chunk.metadata holds nothing
beyond what _format_provenance already renders."""
from textual.app import App
from haiku.rag.inspector.widgets.detail_view import DetailView
chunk = Chunk(
id="chunk-1",
document_id="doc-1",
content="raw chunk text",
metadata={"headings": ["Chapter 1"], "page_numbers": [1]},
)
class TestApp(App):
def compose(self):
yield DetailView(id="detail")
app = TestApp()
async with app.run_test():
detail_view = app.query_one(DetailView)
await detail_view.show_chunk(chunk)
source = detail_view.content_widget.source
assert "**Metadata:**" not in source
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_detail_view_shows_search_result_chunk_meta(): async def test_detail_view_shows_search_result_chunk_meta():
"""show_search_result renders SearchResult.chunk_meta, the anchor """show_search_result renders SearchResult.chunk_meta's non-standard
chunk's raw metadata carried through search/expansion.""" keys, the anchor chunk's own metadata carried through search/expansion."""
from textual.app import App from textual.app import App
from haiku.rag.inspector.widgets.detail_view import DetailView from haiku.rag.inspector.widgets.detail_view import DetailView
@ -206,7 +235,11 @@ async def test_detail_view_shows_search_result_chunk_meta():
content="raw chunk text", content="raw chunk text",
score=0.5, score=0.5,
chunk_id="chunk-1", chunk_id="chunk-1",
chunk_meta={"para_no": "12"}, doc_item_refs=[f"#/texts/{i}" for i in range(7)],
chunk_meta={
"para_no": "12",
"doc_item_refs": [f"#/texts/{i}" for i in range(7)],
},
) )
class TestApp(App): class TestApp(App):
@ -220,6 +253,10 @@ async def test_detail_view_shows_search_result_chunk_meta():
source = detail_view.content_widget.source source = detail_view.content_widget.source
assert "**Metadata:**" in source assert "**Metadata:**" in source
assert "para_no: 12" in source assert "para_no: 12" in source
# _format_provenance's own 5-item truncation for doc_item_refs is
# untouched by the filtered-out duplicate in chunk_meta.
assert "+2 more" in source
assert "doc_item_refs:" not in source
@pytest.mark.asyncio @pytest.mark.asyncio