(
user_id: str,
query: str,
node_type: Optional[str] = None,
limit: int = 20,
)
| 579 | |
| 580 | |
| 581 | def vector_search_nodes( |
| 582 | user_id: str, |
| 583 | query: str, |
| 584 | node_type: Optional[str] = None, |
| 585 | limit: int = 20, |
| 586 | ) -> List[Dict[str, Any]]: |
| 587 | init_wiki_schema() |
| 588 | conn = db_ops.get_connection() |
| 589 | params: List[Any] = [user_id] |
| 590 | type_filter = "" |
| 591 | if node_type: |
| 592 | type_filter = " AND node_type = ?" |
| 593 | params.append(node_type) |
| 594 | rows = conn.execute( |
| 595 | f""" |
| 596 | SELECT * FROM wiki_nodes |
| 597 | WHERE user_id = ? |
| 598 | AND embedding IS NOT NULL |
| 599 | {type_filter} |
| 600 | """, |
| 601 | params, |
| 602 | ).fetchall() |
| 603 | conn.close() |
| 604 | if not rows: |
| 605 | return [] |
| 606 | |
| 607 | from paperflow.providers import build_embedding_provider |
| 608 | |
| 609 | provider = build_embedding_provider() |
| 610 | query_vector = np.array(provider.embed(query), dtype=np.float32) |
| 611 | query_norm = float(np.linalg.norm(query_vector)) |
| 612 | if query_norm > 0: |
| 613 | query_vector = query_vector / query_norm |
| 614 | |
| 615 | scored: List[Dict[str, Any]] = [] |
| 616 | for row in rows: |
| 617 | node = _row_to_node(row) |
| 618 | vector = _blob_to_vector(row["embedding"]) |
| 619 | if vector.size == 0: |
| 620 | continue |
| 621 | dim = min(vector.size, query_vector.size) |
| 622 | if dim <= 0: |
| 623 | continue |
| 624 | score = float(np.dot(vector[:dim], query_vector[:dim])) |
| 625 | node["vector_score"] = score |
| 626 | scored.append(node) |
| 627 | scored.sort(key=lambda item: float(item.get("vector_score", 0.0)), reverse=True) |
| 628 | return scored[: max(1, int(limit))] |
| 629 | |
| 630 | |
| 631 | def search_nodes( |
no test coverage detected