pgvector-template 0.4__tar.gz → 0.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pgvector_template-0.4 → pgvector_template-0.5}/PKG-INFO +1 -1
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/core/search.py +31 -24
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/models/search.py +14 -6
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template.egg-info/PKG-INFO +1 -1
- {pgvector_template-0.4 → pgvector_template-0.5}/pyproject.toml +1 -1
- {pgvector_template-0.4 → pgvector_template-0.5}/LICENSE +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/README.md +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/__init__.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/core/__init__.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/core/document.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/core/embedder.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/core/manager.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/db/__init__.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/db/connection.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/db/document_db.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/models/__init__.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/service/__init__.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/service/document_service.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/types.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/utils/__init__.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/utils/metadata_filter.py +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template.egg-info/SOURCES.txt +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template.egg-info/dependency_links.txt +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template.egg-info/requires.txt +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template.egg-info/top_level.txt +0 -0
- {pgvector_template-0.4 → pgvector_template-0.5}/setup.cfg +0 -0
|
@@ -69,38 +69,43 @@ class BaseSearchClient:
|
|
|
69
69
|
query: Search query containing text, metadata filters, and pagination.
|
|
70
70
|
|
|
71
71
|
Returns:
|
|
72
|
-
List of retrieval results matching the search criteria.
|
|
72
|
+
List of retrieval results matching the search criteria. Each result's `score`
|
|
73
|
+
is a float in [0, 1] when `query.text` is set (1.0 = most similar), or `None`
|
|
74
|
+
for keyword/metadata-only queries.
|
|
73
75
|
"""
|
|
74
|
-
|
|
76
|
+
distance_expr: ColumnElement | None = None
|
|
75
77
|
|
|
76
78
|
if query.text:
|
|
77
|
-
|
|
79
|
+
distance_expr = self._build_distance_expr(query)
|
|
80
|
+
db_query = select(self.config.document_cls, distance_expr).order_by(distance_expr)
|
|
81
|
+
else:
|
|
82
|
+
db_query = select(self.config.document_cls)
|
|
83
|
+
|
|
78
84
|
db_query = self._apply_keyword_search(db_query, query)
|
|
79
85
|
if query.metadata_filters:
|
|
80
86
|
db_query = self._apply_metadata_filters(db_query, query)
|
|
81
87
|
db_query = db_query.limit(query.limit)
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
if distance_expr is not None:
|
|
90
|
+
rows = self.session.execute(db_query).all()
|
|
91
|
+
return self._convert_to_retrieval_results(rows)
|
|
92
|
+
else:
|
|
93
|
+
results = self.session.scalars(db_query).all()
|
|
94
|
+
return self._convert_to_retrieval_results([(doc, None) for doc in results])
|
|
86
95
|
|
|
87
|
-
def
|
|
88
|
-
"""
|
|
89
|
-
`embedding_provider` must be provided at instantiation, or an `ValueError` will be raised.
|
|
90
|
-
In PGVector, `<=>` operator is used to compare cosine distance. Lower = more similar.
|
|
96
|
+
def _build_distance_expr(self, search_query: SearchQuery) -> ColumnElement:
|
|
97
|
+
"""Build a labeled cosine-distance expression for the given query text.
|
|
91
98
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
search_query: The search query containing the text to search for.
|
|
99
|
+
`embedding_provider` must be provided at instantiation, or a `ValueError` is raised.
|
|
100
|
+
In PGVector, `<=>` computes cosine distance (0 = identical, up to 2 = opposite).
|
|
95
101
|
|
|
96
102
|
Returns:
|
|
97
|
-
|
|
103
|
+
A SQLAlchemy labeled column expression suitable for SELECT and ORDER BY.
|
|
98
104
|
"""
|
|
99
|
-
|
|
100
|
-
return db_query
|
|
105
|
+
assert search_query.text is not None
|
|
101
106
|
query_embedding = self.embedding_provider.embed_text(search_query.text)
|
|
102
|
-
return
|
|
103
|
-
|
|
107
|
+
return self.config.document_cls.embedding.cosine_distance(query_embedding).label(
|
|
108
|
+
"_score_distance"
|
|
104
109
|
)
|
|
105
110
|
|
|
106
111
|
def _apply_keyword_search(self, db_query: Select, search_query: SearchQuery) -> Select:
|
|
@@ -199,16 +204,18 @@ class BaseSearchClient:
|
|
|
199
204
|
raise ValueError(f"Unsupported condition: {filter_obj.condition}")
|
|
200
205
|
|
|
201
206
|
def _convert_to_retrieval_results(self, results: Sequence[Any]) -> list[RetrievalResult]:
|
|
202
|
-
"""Convert
|
|
207
|
+
"""Convert (document, distance | None) pairs to RetrievalResult objects.
|
|
203
208
|
|
|
204
209
|
Args:
|
|
205
|
-
results:
|
|
206
|
-
|
|
210
|
+
results: Sequence of (document, cosine_distance) tuples. Pass distance=None
|
|
211
|
+
for keyword/metadata-only queries that have no semantic ranking.
|
|
207
212
|
|
|
208
213
|
Returns:
|
|
209
|
-
List of RetrievalResult objects.
|
|
214
|
+
List of RetrievalResult objects with score = max(0.0, 1.0 - distance),
|
|
215
|
+
or score=None when distance is None.
|
|
210
216
|
"""
|
|
211
217
|
retrieval_results = []
|
|
212
|
-
for
|
|
213
|
-
|
|
218
|
+
for document, distance in results:
|
|
219
|
+
score = max(0.0, 1.0 - distance / 2.0) if distance is not None else None
|
|
220
|
+
retrieval_results.append(RetrievalResult(document=document, score=score))
|
|
214
221
|
return retrieval_results
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from dataclasses import dataclass, asdict
|
|
2
|
-
from datetime import datetime
|
|
3
2
|
from typing import Any, Literal
|
|
4
3
|
|
|
5
4
|
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
@@ -38,7 +37,13 @@ class SearchQuery(BaseModel):
|
|
|
38
37
|
text: str | None = None
|
|
39
38
|
"""String to match against using in a semantic search, i.e. using vector distance."""
|
|
40
39
|
keywords: list[str] = []
|
|
41
|
-
"""
|
|
40
|
+
"""
|
|
41
|
+
List of keywords for a case-insensitive **substring** search (SQL `ILIKE '%keyword%'`).
|
|
42
|
+
An entry matches if **any** keyword appears anywhere in its content (OR-combined).
|
|
43
|
+
Pass multiple variants, synonyms, or spellings to increase recall — e.g.
|
|
44
|
+
["run", "running", "ran"] will match entries containing any of those forms.
|
|
45
|
+
Note: substring matching means "cat" also matches "category"; prefer distinctive stems.
|
|
46
|
+
"""
|
|
42
47
|
metadata_filters: list[MetadataFilter] = Field(
|
|
43
48
|
default=[],
|
|
44
49
|
json_schema_extra={"metadata_schema": BaseDocumentMetadata.model_json_schema()},
|
|
@@ -47,8 +52,6 @@ class SearchQuery(BaseModel):
|
|
|
47
52
|
List of metadata conditions that must be matched.
|
|
48
53
|
Refer to `metadata_schema` for the expected schema, as it exists in the database.
|
|
49
54
|
"""
|
|
50
|
-
date_range: tuple[datetime, datetime] | None = None
|
|
51
|
-
"""Retrieve/limit results based on created_at & updated_at timestamps (i.e. database operations)"""
|
|
52
55
|
limit: int = Field(
|
|
53
56
|
...,
|
|
54
57
|
ge=1,
|
|
@@ -62,7 +65,7 @@ class SearchQuery(BaseModel):
|
|
|
62
65
|
|
|
63
66
|
@model_validator(mode="after")
|
|
64
67
|
def ensure_criterion(self):
|
|
65
|
-
if not any([self.text, self.keywords, self.metadata_filters
|
|
68
|
+
if not any([self.text, self.keywords, self.metadata_filters]):
|
|
66
69
|
raise ValueError("At least one search criterion is required")
|
|
67
70
|
return self
|
|
68
71
|
|
|
@@ -72,7 +75,12 @@ class RetrievalResult:
|
|
|
72
75
|
"""Standardized result structure for all retrieval operations"""
|
|
73
76
|
|
|
74
77
|
document: BaseDocument
|
|
75
|
-
score: float
|
|
78
|
+
score: float | None
|
|
79
|
+
"""
|
|
80
|
+
Semantic similarity score in [0, 1] when a `text` query was provided (1.0 = identical,
|
|
81
|
+
0.0 = maximally distant). `None` when the search had no semantic component (keywords /
|
|
82
|
+
metadata filters only) — results are still filtered correctly but have no meaningful ranking.
|
|
83
|
+
"""
|
|
76
84
|
|
|
77
85
|
def to_dict(self) -> dict[str, Any]:
|
|
78
86
|
return asdict(self)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pgvector-template"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5"
|
|
8
8
|
description = "Template library for flexible PGVector RAG implementations"
|
|
9
9
|
authors = [{ name="DL", email="v49t9zpqd@mozmail.com" }]
|
|
10
10
|
license = { text = "MIT" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template/service/document_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pgvector_template-0.4 → pgvector_template-0.5}/pgvector_template.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|