Erweiterung der Kanten um Abschnittsinformationen
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 4s
This commit is contained in:
parent
876ee898d8
commit
c5f29ab4ae
|
|
@ -200,14 +200,20 @@ class GraphExplorerService:
|
||||||
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=note_ids)))
|
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=note_ids)))
|
||||||
|
|
||||||
# Case C: Edge zeigt auf unseren Titel (Wikilinks) - auch wenn note_title None ist, versuchen wir es mit den Titeln der Notes
|
# Case C: Edge zeigt auf unseren Titel (Wikilinks) - auch wenn note_title None ist, versuchen wir es mit den Titeln der Notes
|
||||||
|
# WICHTIG: Wir müssen auch nach "Titel#Abschnitt" Format suchen!
|
||||||
|
note_titles_to_search = []
|
||||||
if note_title:
|
if note_title:
|
||||||
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=note_title)))
|
note_titles_to_search.append(note_title)
|
||||||
else:
|
else:
|
||||||
# Fallback: Lade Titel der Notes, wenn note_title nicht übergeben wurde
|
# Fallback: Lade Titel der Notes, wenn note_title nicht übergeben wurde
|
||||||
for nid in note_ids:
|
for nid in note_ids:
|
||||||
note = self._fetch_note_cached(nid)
|
note = self._fetch_note_cached(nid)
|
||||||
if note and note.get("title"):
|
if note and note.get("title"):
|
||||||
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=note.get("title"))))
|
note_titles_to_search.append(note.get("title"))
|
||||||
|
|
||||||
|
# Für jeden Titel: Suche nach exaktem Match
|
||||||
|
for title in note_titles_to_search:
|
||||||
|
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=title)))
|
||||||
|
|
||||||
if shoulds:
|
if shoulds:
|
||||||
in_filter = models.Filter(
|
in_filter = models.Filter(
|
||||||
|
|
@ -218,6 +224,34 @@ class GraphExplorerService:
|
||||||
res_in, _ = self.client.scroll(self.edges_col, scroll_filter=in_filter, limit=2000, with_payload=True)
|
res_in, _ = self.client.scroll(self.edges_col, scroll_filter=in_filter, limit=2000, with_payload=True)
|
||||||
results.extend(res_in)
|
results.extend(res_in)
|
||||||
|
|
||||||
|
# Case D: ZUSÄTZLICHE Suche für "Titel#Abschnitt" Format
|
||||||
|
# Da Qdrant keine Wildcard-Suche hat, müssen wir breiter suchen und clientseitig filtern
|
||||||
|
# Wir suchen nach allen Kanten, die mit einem unserer Titel beginnen
|
||||||
|
if note_titles_to_search:
|
||||||
|
# Erweiterte Suche: Lade alle relevanten Kanten und filtere clientseitig
|
||||||
|
# Dies ist notwendig, weil "Titel#Abschnitt" nicht exakt mit "Titel" übereinstimmt
|
||||||
|
# OPTIMIERUNG: Nur wenn wir Titel haben, und mit begrenztem Limit
|
||||||
|
extended_filter = models.Filter(
|
||||||
|
must=[models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))]
|
||||||
|
)
|
||||||
|
# Lade Kanten für die clientseitige Filterung (Limit basierend auf Anzahl der Titel)
|
||||||
|
# Für jeden Titel könnten mehrere "Titel#Abschnitt" Varianten existieren
|
||||||
|
res_extended, _ = self.client.scroll(self.edges_col, scroll_filter=extended_filter, limit=3000, with_payload=True)
|
||||||
|
|
||||||
|
# Clientseitige Filterung: Finde Kanten, deren target_id mit einem unserer Titel beginnt
|
||||||
|
# Erstelle Set der bereits gefundenen Edge-IDs für schnelle Deduplizierung
|
||||||
|
existing_edge_ids = {r.id for r in results}
|
||||||
|
|
||||||
|
for edge in res_extended:
|
||||||
|
tgt_id = edge.payload.get("target_id", "")
|
||||||
|
if tgt_id and edge.id not in existing_edge_ids:
|
||||||
|
# Prüfe, ob target_id mit einem unserer Titel beginnt (für "Titel#Abschnitt" Format)
|
||||||
|
for title in note_titles_to_search:
|
||||||
|
if tgt_id.startswith(title + "#") or tgt_id == title:
|
||||||
|
results.append(edge)
|
||||||
|
existing_edge_ids.add(edge.id)
|
||||||
|
break # Nur einmal hinzufügen, auch wenn mehrere Titel passen
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def _find_connected_edges_batch(self, note_ids):
|
def _find_connected_edges_batch(self, note_ids):
|
||||||
|
|
@ -296,10 +330,10 @@ class GraphExplorerService:
|
||||||
"""Löst eine ID (Chunk, Note oder Titel) zu einer Note Payload auf."""
|
"""Löst eine ID (Chunk, Note oder Titel) zu einer Note Payload auf."""
|
||||||
if not ref_str: return None
|
if not ref_str: return None
|
||||||
|
|
||||||
# Fall A: Chunk ID (enthält #)
|
# Fall A: Chunk ID oder Titel#Abschnitt (enthält #)
|
||||||
if "#" in ref_str:
|
if "#" in ref_str:
|
||||||
try:
|
try:
|
||||||
# Versuch 1: Chunk ID direkt
|
# Versuch 1: Chunk ID direkt (Format: note_id#c01)
|
||||||
res = self.client.retrieve(self.chunks_col, ids=[ref_str], with_payload=True)
|
res = self.client.retrieve(self.chunks_col, ids=[ref_str], with_payload=True)
|
||||||
if res and res[0].payload:
|
if res and res[0].payload:
|
||||||
note_id = res[0].payload.get("note_id")
|
note_id = res[0].payload.get("note_id")
|
||||||
|
|
@ -309,11 +343,26 @@ class GraphExplorerService:
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Versuch 2: NoteID#Section (Hash abtrennen)
|
# Versuch 2: NoteID#Section (Hash abtrennen und als Note-ID versuchen)
|
||||||
possible_note_id = ref_str.split("#")[0]
|
possible_note_id = ref_str.split("#")[0]
|
||||||
note = self._fetch_note_cached(possible_note_id)
|
note = self._fetch_note_cached(possible_note_id)
|
||||||
if note: return note
|
if note: return note
|
||||||
|
|
||||||
|
# Versuch 3: Titel#Abschnitt (Hash abtrennen und als Titel suchen)
|
||||||
|
# Dies ist wichtig für Wikilinks im Format [[Titel#Abschnitt]]
|
||||||
|
possible_title = ref_str.split("#")[0]
|
||||||
|
try:
|
||||||
|
res, _ = self.client.scroll(
|
||||||
|
collection_name=self.notes_col,
|
||||||
|
scroll_filter=models.Filter(must=[models.FieldCondition(key="title", match=models.MatchValue(value=possible_title))]),
|
||||||
|
limit=1, with_payload=True
|
||||||
|
)
|
||||||
|
if res and res[0].payload:
|
||||||
|
self._note_cache[res[0].payload['note_id']] = res[0].payload
|
||||||
|
return res[0].payload
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# Fall B: Note ID direkt
|
# Fall B: Note ID direkt
|
||||||
note = self._fetch_note_cached(ref_str)
|
note = self._fetch_note_cached(ref_str)
|
||||||
if note: return note
|
if note: return note
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user