WP06a #5
|
|
@ -2,7 +2,7 @@
|
||||||
app/core/retriever.py — Hybrider Such-Algorithmus
|
app/core/retriever.py — Hybrider Such-Algorithmus
|
||||||
|
|
||||||
Version:
|
Version:
|
||||||
0.5.2 (WP-05 Fix: Pass content in QueryHit source)
|
0.5.3 (WP-06 Fix: Populate 'payload' in QueryHit for meta-data access)
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
@ -127,7 +127,9 @@ def _build_explanation(
|
||||||
node_key: Optional[str]
|
node_key: Optional[str]
|
||||||
) -> Explanation:
|
) -> Explanation:
|
||||||
"""Erstellt ein Explanation-Objekt."""
|
"""Erstellt ein Explanation-Objekt."""
|
||||||
sem_w, edge_w, cent_w = _get_scoring_weights()
|
sem_w, _edge_w, _cent_w = _get_scoring_weights()
|
||||||
|
# Scoring weights erneut laden für Reason-Details
|
||||||
|
_, edge_w_cfg, cent_w_cfg = _get_scoring_weights()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
type_weight = float(payload.get("retriever_weight", 1.0))
|
type_weight = float(payload.get("retriever_weight", 1.0))
|
||||||
|
|
@ -138,8 +140,8 @@ def _build_explanation(
|
||||||
|
|
||||||
breakdown = ScoreBreakdown(
|
breakdown = ScoreBreakdown(
|
||||||
semantic_contribution=(sem_w * semantic_score * type_weight),
|
semantic_contribution=(sem_w * semantic_score * type_weight),
|
||||||
edge_contribution=(edge_w * edge_bonus),
|
edge_contribution=(edge_w_cfg * edge_bonus),
|
||||||
centrality_contribution=(cent_w * cent_bonus),
|
centrality_contribution=(cent_w_cfg * cent_bonus),
|
||||||
raw_semantic=semantic_score,
|
raw_semantic=semantic_score,
|
||||||
raw_edge_bonus=edge_bonus,
|
raw_edge_bonus=edge_bonus,
|
||||||
raw_centrality=cent_bonus,
|
raw_centrality=cent_bonus,
|
||||||
|
|
@ -179,7 +181,7 @@ def _build_explanation(
|
||||||
|
|
||||||
all_edges = sorted(edges_dto, key=lambda e: e.weight, reverse=True)
|
all_edges = sorted(edges_dto, key=lambda e: e.weight, reverse=True)
|
||||||
for top_edge in all_edges[:3]:
|
for top_edge in all_edges[:3]:
|
||||||
impact = edge_w * top_edge.weight
|
impact = edge_w_cfg * top_edge.weight
|
||||||
dir_txt = "Verweist auf" if top_edge.direction == "out" else "Referenziert von"
|
dir_txt = "Verweist auf" if top_edge.direction == "out" else "Referenziert von"
|
||||||
tgt_txt = top_edge.target if top_edge.direction == "out" else top_edge.source
|
tgt_txt = top_edge.target if top_edge.direction == "out" else top_edge.source
|
||||||
reasons.append(Reason(kind="edge", message=f"{dir_txt} '{tgt_txt}' via '{top_edge.kind}'", score_impact=impact, details={"kind": top_edge.kind}))
|
reasons.append(Reason(kind="edge", message=f"{dir_txt} '{tgt_txt}' via '{top_edge.kind}'", score_impact=impact, details={"kind": top_edge.kind}))
|
||||||
|
|
@ -261,7 +263,6 @@ def _build_hits_from_semantic(
|
||||||
node_key=payload.get("chunk_id") or payload.get("note_id")
|
node_key=payload.get("chunk_id") or payload.get("note_id")
|
||||||
)
|
)
|
||||||
|
|
||||||
# FIX: Hier holen wir jetzt den Textinhalt (text, content oder page_content) aus dem Payload
|
|
||||||
text_content = payload.get("page_content") or payload.get("text") or payload.get("content")
|
text_content = payload.get("page_content") or payload.get("text") or payload.get("content")
|
||||||
|
|
||||||
results.append(QueryHit(
|
results.append(QueryHit(
|
||||||
|
|
@ -275,8 +276,10 @@ def _build_hits_from_semantic(
|
||||||
source={
|
source={
|
||||||
"path": payload.get("path"),
|
"path": payload.get("path"),
|
||||||
"section": payload.get("section") or payload.get("section_title"),
|
"section": payload.get("section") or payload.get("section_title"),
|
||||||
"text": text_content # WICHTIG: Inhalt durchreichen
|
"text": text_content
|
||||||
},
|
},
|
||||||
|
# --- FIX: Wir füllen das payload-Feld explizit ---
|
||||||
|
payload=payload,
|
||||||
explanation=explanation_obj
|
explanation=explanation_obj
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ class QueryHit(BaseModel):
|
||||||
total_score: float
|
total_score: float
|
||||||
paths: Optional[List[List[Dict]]] = None
|
paths: Optional[List[List[Dict]]] = None
|
||||||
source: Optional[Dict] = None
|
source: Optional[Dict] = None
|
||||||
payload: Optional[Dict] = None # Added for flexibility
|
payload: Optional[Dict] = None # Added for flexibility & WP-06 meta-data
|
||||||
explanation: Optional[Explanation] = None
|
explanation: Optional[Explanation] = None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,11 @@ def _build_enriched_context(hits: List[QueryHit]) -> str:
|
||||||
"[Kein Text]"
|
"[Kein Text]"
|
||||||
)
|
)
|
||||||
title = hit.note_id or "Unbekannt"
|
title = hit.note_id or "Unbekannt"
|
||||||
note_type = source.get("type", "unknown").upper()
|
|
||||||
|
# FIX: Wir holen den Typ aus Payload oder Source (Fallback)
|
||||||
|
payload = hit.payload or {}
|
||||||
|
note_type = payload.get("type") or source.get("type", "unknown")
|
||||||
|
note_type = str(note_type).upper()
|
||||||
|
|
||||||
entry = (
|
entry = (
|
||||||
f"### QUELLE {i}: {title}\n"
|
f"### QUELLE {i}: {title}\n"
|
||||||
|
|
@ -214,7 +218,7 @@ async def chat_endpoint(
|
||||||
sources=hits,
|
sources=hits,
|
||||||
latency_ms=duration_ms,
|
latency_ms=duration_ms,
|
||||||
intent=intent,
|
intent=intent,
|
||||||
intent_source=intent_source # NEU: Source durchreichen
|
intent_source=intent_source # Source durchreichen
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user