pgvector-template 0.3.3__tar.gz → 0.3.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.3.3 → pgvector_template-0.3.5}/PKG-INFO +3 -2
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/__init__.py +1 -1
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/core/__init__.py +5 -1
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/core/document.py +1 -1
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/core/manager.py +20 -9
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/db/connection.py +16 -6
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/db/document_db.py +4 -2
- pgvector_template-0.3.5/pgvector_template/models/__init__.py +5 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/models/search.py +1 -1
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/service/document_service.py +1 -2
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/utils/metadata_filter.py +3 -3
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/PKG-INFO +3 -2
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/requires.txt +2 -1
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pyproject.toml +8 -4
- pgvector_template-0.3.3/pgvector_template/models/__init__.py +0 -1
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/LICENSE +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/README.md +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/core/embedder.py +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/core/search.py +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/db/__init__.py +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/service/__init__.py +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/types.py +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/utils/__init__.py +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/SOURCES.txt +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/dependency_links.txt +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/top_level.txt +0 -0
- {pgvector_template-0.3.3 → pgvector_template-0.3.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pgvector-template
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Template library for flexible PGVector RAG implementations
|
|
5
5
|
Author-email: DL <v49t9zpqd@mozmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -21,7 +21,8 @@ Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
|
21
21
|
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
22
22
|
Requires-Dist: python-dotenv>=1.0.0; extra == "test"
|
|
23
23
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist:
|
|
24
|
+
Requires-Dist: ruff>=0.9.0; extra == "dev"
|
|
25
|
+
Requires-Dist: ty>=0.0.1a0; extra == "dev"
|
|
25
26
|
Provides-Extra: dist
|
|
26
27
|
Requires-Dist: build>=1.2.2; extra == "dist"
|
|
27
28
|
Requires-Dist: twine>=6.1.0; extra == "dist"
|
|
@@ -3,4 +3,4 @@ from pgvector_template.db.connection import DatabaseManager
|
|
|
3
3
|
from pgvector_template.db.document_db import DocumentDatabaseManager
|
|
4
4
|
|
|
5
5
|
# Re-export at the top level
|
|
6
|
-
__all__ = ["DatabaseManager", "DocumentDatabaseManager"]
|
|
6
|
+
__all__ = ["DatabaseManager", "DocumentDatabaseManager"]
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
from pgvector_template.core.document import
|
|
1
|
+
from pgvector_template.core.document import (
|
|
2
|
+
BaseDocument,
|
|
3
|
+
BaseDocumentMetadata,
|
|
4
|
+
BaseDocumentOptionalProps,
|
|
5
|
+
)
|
|
2
6
|
from pgvector_template.core.embedder import BaseEmbeddingProvider
|
|
3
7
|
from pgvector_template.core.manager import BaseCorpusManager, BaseCorpusManagerConfig, Corpus
|
|
4
8
|
from pgvector_template.core.search import BaseSearchClientConfig, BaseSearchClient
|
|
@@ -2,7 +2,7 @@ from datetime import datetime
|
|
|
2
2
|
from typing import Any, Type, TypeVar
|
|
3
3
|
from uuid import uuid4, UUID as UuidLiteral
|
|
4
4
|
|
|
5
|
-
from pydantic import BaseModel, Field, field_validator
|
|
5
|
+
from pydantic import BaseModel, Field, field_validator
|
|
6
6
|
from sqlalchemy import (
|
|
7
7
|
Column,
|
|
8
8
|
String,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from abc import ABC
|
|
1
|
+
from abc import ABC
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from logging import getLogger
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Type
|
|
5
5
|
from uuid import UUID, uuid4
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
@@ -88,7 +88,7 @@ class BaseCorpusManager(ABC):
|
|
|
88
88
|
self.session.query(self.config.document_cls)
|
|
89
89
|
.filter(
|
|
90
90
|
self.config.document_cls.corpus_id == corpus_id,
|
|
91
|
-
self.config.document_cls.is_deleted == False,
|
|
91
|
+
self.config.document_cls.is_deleted == False, # noqa: E712
|
|
92
92
|
)
|
|
93
93
|
.order_by(self.config.document_cls.chunk_index)
|
|
94
94
|
.all()
|
|
@@ -105,6 +105,15 @@ class BaseCorpusManager(ABC):
|
|
|
105
105
|
documents=chunks,
|
|
106
106
|
)
|
|
107
107
|
|
|
108
|
+
def _generate_corpus_id(
|
|
109
|
+
self, corpus_id: UUID | str | None = None, content: str | None = None
|
|
110
|
+
) -> UUID | str:
|
|
111
|
+
"""
|
|
112
|
+
Helper to generate a corpus_id if not provided.
|
|
113
|
+
Override this method to provide a consistent way to generate.
|
|
114
|
+
"""
|
|
115
|
+
return corpus_id if corpus_id else uuid4()
|
|
116
|
+
|
|
108
117
|
def insert_corpus(
|
|
109
118
|
self,
|
|
110
119
|
content: str,
|
|
@@ -126,8 +135,7 @@ class BaseCorpusManager(ABC):
|
|
|
126
135
|
Returns:
|
|
127
136
|
int: The number of **documents** inserted for the provided corpus
|
|
128
137
|
"""
|
|
129
|
-
|
|
130
|
-
corpus_id = uuid4()
|
|
138
|
+
corpus_id = self._generate_corpus_id(corpus_id)
|
|
131
139
|
document_contents = self._split_corpus(content)
|
|
132
140
|
document_embeddings = self.embedding_provider.embed_batch(document_contents)
|
|
133
141
|
return self.insert_documents(
|
|
@@ -214,9 +222,12 @@ class BaseCorpusManager(ABC):
|
|
|
214
222
|
|
|
215
223
|
def _delete_existing_corpus(self, corpus_id: UUID | str) -> None:
|
|
216
224
|
"""Delete all existing documents for the given corpus_id"""
|
|
217
|
-
self.session.query(self.config.document_cls).filter(
|
|
225
|
+
query = self.session.query(self.config.document_cls).filter(
|
|
218
226
|
self.config.document_cls.corpus_id == corpus_id
|
|
219
|
-
)
|
|
227
|
+
)
|
|
228
|
+
if count := query.count():
|
|
229
|
+
logger.warning(f"Deleting {count} existing documents for corpus_id: {corpus_id}")
|
|
230
|
+
query.delete()
|
|
220
231
|
|
|
221
232
|
def _split_corpus(self, content: str, **kwargs) -> list[str]:
|
|
222
233
|
"""
|
|
@@ -244,9 +255,9 @@ class BaseCorpusManager(ABC):
|
|
|
244
255
|
logger.warning(
|
|
245
256
|
"Using default _join_documents. Override this method to improve functionality."
|
|
246
257
|
)
|
|
247
|
-
documents.sort(key=lambda d: d.chunk_index)
|
|
258
|
+
documents.sort(key=lambda d: d.chunk_index)
|
|
248
259
|
# since _split_corpus performs a simple split on every 1000 chars, we can simply call `join`
|
|
249
|
-
corpus_content = "".join(d.content for d in documents) #
|
|
260
|
+
corpus_content = "".join(d.content for d in documents) # ty: ignore[no-matching-overload]
|
|
250
261
|
corpus_metadata = self._infer_corpus_metadata(documents)
|
|
251
262
|
return corpus_content, corpus_metadata
|
|
252
263
|
|
|
@@ -2,7 +2,7 @@ from contextlib import contextmanager
|
|
|
2
2
|
from logging import getLogger
|
|
3
3
|
from typing import Generator, Type
|
|
4
4
|
|
|
5
|
-
from sqlalchemy import create_engine, text
|
|
5
|
+
from sqlalchemy import Engine, create_engine, text
|
|
6
6
|
from sqlalchemy.orm import sessionmaker, Session
|
|
7
7
|
from sqlalchemy.ext.declarative import DeclarativeMeta
|
|
8
8
|
|
|
@@ -12,21 +12,29 @@ class DatabaseManager:
|
|
|
12
12
|
|
|
13
13
|
def __init__(self, database_url: str):
|
|
14
14
|
self.database_url = database_url
|
|
15
|
-
self.engine = None
|
|
15
|
+
self.engine: Engine | None = None
|
|
16
16
|
self.SessionLocal = None
|
|
17
17
|
self.logger = getLogger(self.__class__.__name__)
|
|
18
18
|
|
|
19
|
+
def _require_engine(self) -> Engine:
|
|
20
|
+
if self.engine is None:
|
|
21
|
+
raise RuntimeError("DatabaseManager not initialized. Call initialize() first.")
|
|
22
|
+
return self.engine
|
|
23
|
+
|
|
19
24
|
def initialize(self):
|
|
20
25
|
"""Initialize database connection and session factory"""
|
|
21
26
|
self.engine = create_engine(
|
|
22
|
-
self.database_url,
|
|
27
|
+
self.database_url,
|
|
28
|
+
pool_pre_ping=True,
|
|
29
|
+
pool_recycle=300,
|
|
30
|
+
echo=False, # Set to True for SQL debugging
|
|
23
31
|
)
|
|
24
32
|
self.SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=self.engine)
|
|
25
33
|
self._ensure_pgvector_extension()
|
|
26
34
|
|
|
27
35
|
def create_schema(self, schema_name: str) -> None:
|
|
28
36
|
"""Create a new schema for a collection type"""
|
|
29
|
-
with self.
|
|
37
|
+
with self._require_engine().connect() as conn:
|
|
30
38
|
conn.execute(text(f"CREATE SCHEMA IF NOT EXISTS {schema_name}"))
|
|
31
39
|
conn.commit()
|
|
32
40
|
|
|
@@ -37,12 +45,12 @@ class DatabaseManager:
|
|
|
37
45
|
# Ensure all tables in this base class use the specified schema
|
|
38
46
|
for table in base_class.metadata.tables.values():
|
|
39
47
|
table.schema = schema_name
|
|
40
|
-
base_class.metadata.create_all(self.
|
|
48
|
+
base_class.metadata.create_all(self._require_engine(), checkfirst=True)
|
|
41
49
|
self.logger.info(f"Created tables for schema: {schema_name}")
|
|
42
50
|
|
|
43
51
|
def _ensure_pgvector_extension(self):
|
|
44
52
|
"""Ensure pgvector extension is available"""
|
|
45
|
-
with self.
|
|
53
|
+
with self._require_engine().connect() as conn:
|
|
46
54
|
conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
|
|
47
55
|
conn.commit()
|
|
48
56
|
|
|
@@ -56,6 +64,8 @@ class DatabaseManager:
|
|
|
56
64
|
# do stuff with the Session here
|
|
57
65
|
```
|
|
58
66
|
"""
|
|
67
|
+
if self.SessionLocal is None:
|
|
68
|
+
raise RuntimeError("DatabaseManager not initialized. Call initialize() first.")
|
|
59
69
|
session = self.SessionLocal()
|
|
60
70
|
try:
|
|
61
71
|
yield session
|
|
@@ -23,7 +23,9 @@ class DocumentDatabaseManager(DatabaseManager):
|
|
|
23
23
|
|
|
24
24
|
SCHEMA_PREFIX = "knowledge_base_"
|
|
25
25
|
|
|
26
|
-
def __init__(
|
|
26
|
+
def __init__(
|
|
27
|
+
self, database_url: str, schema_suffix: str, document_classes: List[Type[BaseDocument]]
|
|
28
|
+
):
|
|
27
29
|
"""
|
|
28
30
|
Initialize a document-oriented database manager
|
|
29
31
|
|
|
@@ -79,7 +81,7 @@ class TempDocumentDatabaseManager(DocumentDatabaseManager):
|
|
|
79
81
|
if not schema_name.startswith("temp_"):
|
|
80
82
|
raise ValueError("Can only drop schemas with 'temp_' prefix for safety")
|
|
81
83
|
|
|
82
|
-
with self.
|
|
84
|
+
with self._require_engine().connect() as conn:
|
|
83
85
|
conn.execute(text(f"DROP SCHEMA IF EXISTS {schema_name} CASCADE"))
|
|
84
86
|
conn.commit()
|
|
85
87
|
|
{pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/service/document_service.py
RENAMED
|
@@ -3,8 +3,7 @@ Document service layer combining corpus management and search capabilities.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from logging import getLogger
|
|
6
|
-
from typing import
|
|
7
|
-
from uuid import UUID
|
|
6
|
+
from typing import Generic, Type, TypeVar
|
|
8
7
|
|
|
9
8
|
from pydantic import BaseModel, Field
|
|
10
9
|
from sqlalchemy.orm import Session
|
{pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template/utils/metadata_filter.py
RENAMED
|
@@ -66,9 +66,9 @@ def validate_condition_compatibility(field_type: Type, condition: str) -> None:
|
|
|
66
66
|
if origin is list:
|
|
67
67
|
field_type = list
|
|
68
68
|
elif len(args) > 0:
|
|
69
|
-
field_type = args[0] #
|
|
69
|
+
field_type = args[0] # ty: ignore[index-out-of-bounds]
|
|
70
70
|
|
|
71
|
-
valid_conditions = {
|
|
71
|
+
valid_conditions: dict[type, set[str]] = {
|
|
72
72
|
str: {"eq", "gt", "gte", "lt", "lte", "in", "exists"},
|
|
73
73
|
int: {"eq", "gt", "gte", "lt", "lte", "exists"},
|
|
74
74
|
float: {"eq", "gt", "gte", "lt", "lte", "exists"},
|
|
@@ -76,6 +76,6 @@ def validate_condition_compatibility(field_type: Type, condition: str) -> None:
|
|
|
76
76
|
list: {"contains", "in", "exists"},
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
allowed = valid_conditions.get(field_type, {"eq", "exists"})
|
|
79
|
+
allowed: set[str] = valid_conditions.get(field_type, {"eq", "exists"})
|
|
80
80
|
if condition not in allowed:
|
|
81
81
|
raise ValueError(f"Condition '{condition}' not valid for field type {field_type.__name__}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pgvector-template
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Template library for flexible PGVector RAG implementations
|
|
5
5
|
Author-email: DL <v49t9zpqd@mozmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -21,7 +21,8 @@ Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
|
21
21
|
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
22
22
|
Requires-Dist: python-dotenv>=1.0.0; extra == "test"
|
|
23
23
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist:
|
|
24
|
+
Requires-Dist: ruff>=0.9.0; extra == "dev"
|
|
25
|
+
Requires-Dist: ty>=0.0.1a0; extra == "dev"
|
|
25
26
|
Provides-Extra: dist
|
|
26
27
|
Requires-Dist: build>=1.2.2; extra == "dist"
|
|
27
28
|
Requires-Dist: twine>=6.1.0; extra == "dist"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pgvector-template"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.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" }
|
|
@@ -30,7 +30,8 @@ test = [
|
|
|
30
30
|
"python-dotenv>=1.0.0",
|
|
31
31
|
]
|
|
32
32
|
dev = [
|
|
33
|
-
"
|
|
33
|
+
"ruff>=0.9.0",
|
|
34
|
+
"ty>=0.0.1a0",
|
|
34
35
|
]
|
|
35
36
|
dist = [
|
|
36
37
|
"build>=1.2.2",
|
|
@@ -46,6 +47,9 @@ where = ["."] # Look for packages in the root directory
|
|
|
46
47
|
include = ["pgvector_template*"] # Include all packages starting with pgvector_template
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
[tool.
|
|
50
|
+
[tool.ruff]
|
|
50
51
|
line-length = 100
|
|
51
|
-
target-version =
|
|
52
|
+
target-version = "py311"
|
|
53
|
+
|
|
54
|
+
[tool.ty.src]
|
|
55
|
+
exclude = []
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from pgvector_template.models.search import *
|
|
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.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{pgvector_template-0.3.3 → pgvector_template-0.3.5}/pgvector_template.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|