synapse-framework 0.2.4__py3-none-any.whl

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.
Files changed (54) hide show
  1. synapse/__init__.py +207 -0
  2. synapse/app.py +942 -0
  3. synapse/cli.py +88 -0
  4. synapse/config.py +103 -0
  5. synapse/connectors/__init__.py +29 -0
  6. synapse/connectors/base.py +222 -0
  7. synapse/connectors/factory.py +202 -0
  8. synapse/connectors/gmail.py +292 -0
  9. synapse/connectors/mcp_wrapper.py +153 -0
  10. synapse/connectors/notion.py +161 -0
  11. synapse/connectors/photos.py +141 -0
  12. synapse/database/__init__.py +19 -0
  13. synapse/database/base.py +63 -0
  14. synapse/database/chroma.py +175 -0
  15. synapse/database/memory.py +132 -0
  16. synapse/database/pgvector.py +99 -0
  17. synapse/database/qdrant.py +138 -0
  18. synapse/embeddings/__init__.py +21 -0
  19. synapse/embeddings/base.py +262 -0
  20. synapse/export/__init__.py +14 -0
  21. synapse/export/mcp_exporter.py +202 -0
  22. synapse/graph/__init__.py +21 -0
  23. synapse/graph/base.py +130 -0
  24. synapse/graph/memory.py +20 -0
  25. synapse/graph/neo4j_store.py +176 -0
  26. synapse/graph/networkx_store.py +221 -0
  27. synapse/inspector/__init__.py +5 -0
  28. synapse/inspector/template.py +530 -0
  29. synapse/models/__init__.py +73 -0
  30. synapse/models/base.py +95 -0
  31. synapse/models/gemini.py +328 -0
  32. synapse/models/ollama.py +322 -0
  33. synapse/models/openai.py +289 -0
  34. synapse/oauth/__init__.py +7 -0
  35. synapse/oauth/google.py +194 -0
  36. synapse/oauth/notion.py +35 -0
  37. synapse/rag/__init__.py +8 -0
  38. synapse/rag/chunker.py +219 -0
  39. synapse/rag/hybrid_rag.py +122 -0
  40. synapse/resource/__init__.py +5 -0
  41. synapse/resource/resource.py +304 -0
  42. synapse/resources/__init__.py +5 -0
  43. synapse/skills/__init__.py +5 -0
  44. synapse/skills/skill.py +321 -0
  45. synapse/storage/__init__.py +24 -0
  46. synapse/storage/graph_exporter.py +624 -0
  47. synapse/storage/graph_store.py +162 -0
  48. synapse/storage/vector_store.py +103 -0
  49. synapse_framework-0.2.4.dist-info/METADATA +415 -0
  50. synapse_framework-0.2.4.dist-info/RECORD +54 -0
  51. synapse_framework-0.2.4.dist-info/WHEEL +5 -0
  52. synapse_framework-0.2.4.dist-info/entry_points.txt +2 -0
  53. synapse_framework-0.2.4.dist-info/licenses/LICENSE +21 -0
  54. synapse_framework-0.2.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,141 @@
1
+ """Google Photos connector for the Synapse framework."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ from synapse.connectors.base import BaseConnector
9
+ from synapse.oauth.google import GoogleOAuthService
10
+
11
+ PHOTOS_READONLY_SCOPE = (
12
+ "https://www.googleapis.com/auth/photoslibrary.readonly"
13
+ )
14
+
15
+
16
+ class GooglePhotosConnector(BaseConnector):
17
+ """Google Photos connector for searching and referencing photo media items.
18
+
19
+ Attributes:
20
+ oauth: Reusable GoogleOAuthService managing Google Photos scopes.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ credentials_path: str | Path = "credentials.json",
26
+ token_path: str | Path = "token.json", # nosec B107
27
+ oauth_service: GoogleOAuthService | None = None,
28
+ scopes: list[str] | None = None,
29
+ ) -> None:
30
+ """Initializes the GooglePhotosConnector.
31
+
32
+ Args:
33
+ credentials_path: Path to OAuth client secrets JSON.
34
+ token_path: Path to cached token JSON.
35
+ oauth_service: Optional pre-configured GoogleOAuthService instance.
36
+ scopes: Optional list of OAuth scopes.
37
+ """
38
+ super().__init__(
39
+ name="photos",
40
+ description="Google Photos media library, photos, albums, and image metadata",
41
+ intent_regex=(
42
+ r"\b(photo|photos|image|images|picture|pictures|album|albums|"
43
+ r"snapshot|snapshots|gallery|google\s+photos)\b"
44
+ ),
45
+ default_tool="search_photos",
46
+ )
47
+
48
+ active_scopes = list(scopes or [PHOTOS_READONLY_SCOPE])
49
+ if oauth_service:
50
+ self.oauth = oauth_service
51
+ self.oauth.add_scopes(active_scopes)
52
+ else:
53
+ self.oauth = GoogleOAuthService(
54
+ credentials_path=credentials_path,
55
+ token_path=token_path,
56
+ scopes=active_scopes,
57
+ )
58
+
59
+ def is_authenticated(self) -> bool:
60
+ """Checks if a valid OAuth token exists for Google Photos."""
61
+ return self.oauth.is_authenticated()
62
+
63
+ async def list_tools(self) -> list[dict[str, Any]]:
64
+ """Returns the Google Photos tool schemas."""
65
+ return [
66
+ {
67
+ "server": self.name,
68
+ "name": "search_photos",
69
+ "description": "Search photos and media items in user's Google Photos library.",
70
+ "inputSchema": {
71
+ "type": "object",
72
+ "properties": {
73
+ "query": {
74
+ "type": "string",
75
+ "default": "",
76
+ "description": "Optional search filter or category description.",
77
+ },
78
+ "max_results": {
79
+ "type": "integer",
80
+ "default": 10,
81
+ "description": "Maximum number of photos to return.",
82
+ },
83
+ },
84
+ },
85
+ }
86
+ ]
87
+
88
+ async def call_tool(
89
+ self,
90
+ tool_name: str,
91
+ arguments: dict[str, Any] | None = None,
92
+ ) -> Any:
93
+ """Executes a Google Photos tool."""
94
+ args = arguments or {}
95
+ if tool_name == "search_photos":
96
+ query = str(args.get("query", ""))
97
+ max_results = int(args.get("max_results", 10))
98
+ return self.search_photos(query=query, max_results=max_results)
99
+ raise ValueError(
100
+ f"Unknown tool '{tool_name}' for connector '{self.name}'"
101
+ )
102
+
103
+ def search_photos(
104
+ self,
105
+ query: str = "",
106
+ max_results: int = 10,
107
+ ) -> list[dict[str, Any]]:
108
+ """Searches media items via Google Photos Library API."""
109
+ if not self.is_authenticated():
110
+ return []
111
+
112
+ try:
113
+ service = self.oauth.get_service(
114
+ api_name="photoslibrary",
115
+ version="v1",
116
+ scopes=[PHOTOS_READONLY_SCOPE],
117
+ )
118
+ body: dict[str, Any] = {"pageSize": max(1, min(max_results, 50))}
119
+ response = service.mediaItems().search(body=body).execute()
120
+ items = response.get("mediaItems", [])
121
+
122
+ results: list[dict[str, Any]] = []
123
+ for item in items:
124
+ results.append({
125
+ "id": item.get("id", ""),
126
+ "title": item.get("filename", "Photo"),
127
+ "url": item.get("productUrl", ""),
128
+ "mime_type": item.get("mimeType", ""),
129
+ "date": (
130
+ item.get("mediaMetadata", {}).get("creationTime", "")
131
+ ),
132
+ "description": item.get("description", ""),
133
+ "type": "Photo",
134
+ })
135
+ return results
136
+ except Exception:
137
+ return []
138
+
139
+
140
+ # Developer-friendly alias matching user request
141
+ GooglePhotosConnectors = GooglePhotosConnector
@@ -0,0 +1,19 @@
1
+ """Pluggable vector database backends for Synapse."""
2
+
3
+ from synapse.database.base import BaseVectorDB
4
+ from synapse.database.chroma import ChromaDB, chromadb
5
+ from synapse.database.memory import InMemoryDB, in_memory
6
+ from synapse.database.pgvector import PGVectorDB, pgvector
7
+ from synapse.database.qdrant import QdrantDB, qdrant
8
+
9
+ __all__ = [
10
+ "BaseVectorDB",
11
+ "ChromaDB",
12
+ "InMemoryDB",
13
+ "PGVectorDB",
14
+ "QdrantDB",
15
+ "chromadb",
16
+ "in_memory",
17
+ "pgvector",
18
+ "qdrant",
19
+ ]
@@ -0,0 +1,63 @@
1
+ """Abstract base interface for pluggable vector databases in Synapse."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import Any
7
+
8
+ from langchain_core.documents import Document
9
+
10
+
11
+ class BaseVectorDB(ABC):
12
+ """Abstract interface that all Synapse vector database backends must implement.
13
+
14
+ Ensures seamless interchangeability between local ChromaDB, in-memory storage,
15
+ Qdrant, pgvector, or remote hosted vector databases.
16
+ """
17
+
18
+ @abstractmethod
19
+ def add_documents(
20
+ self,
21
+ documents: list[Document],
22
+ embeddings: list[list[float]] | None = None,
23
+ ) -> list[str]:
24
+ """Upserts a list of LangChain Document objects into the vector database.
25
+
26
+ Args:
27
+ documents: List of Document instances with page_content and metadata.
28
+ embeddings: Optional precomputed vector embeddings.
29
+
30
+ Returns:
31
+ List of generated or assigned document ID strings.
32
+ """
33
+
34
+ @abstractmethod
35
+ def similarity_search(
36
+ self,
37
+ query: str,
38
+ k: int = 4,
39
+ filter_dict: dict[str, Any] | None = None,
40
+ query_embedding: list[float] | None = None,
41
+ ) -> list[Document]:
42
+ """Performs semantic similarity search for a query string.
43
+
44
+ Args:
45
+ query: Natural language query string.
46
+ k: Maximum number of nearest neighbors to return.
47
+ filter_dict: Optional metadata filter dictionary.
48
+ query_embedding: Optional precomputed query embedding vector.
49
+
50
+ Returns:
51
+ List of top-k closest Document instances.
52
+ """
53
+
54
+ @abstractmethod
55
+ def count(self) -> int:
56
+ """Returns the total number of document chunks currently indexed."""
57
+
58
+ @abstractmethod
59
+ def clear(self) -> None:
60
+ """Clears all records in the collection/index."""
61
+
62
+
63
+ __all__ = ["BaseVectorDB"]
@@ -0,0 +1,175 @@
1
+ """ChromaDB vector database provider for Synapse."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import chromadb as native_chromadb
9
+ from langchain_chroma import Chroma
10
+ from langchain_core.documents import Document
11
+
12
+ from synapse.config import (
13
+ DEFAULT_CHROMA_COLLECTION,
14
+ DEFAULT_CHROMA_DIR,
15
+ )
16
+ from synapse.database.base import BaseVectorDB
17
+ from synapse.embeddings import resolve_embedding
18
+
19
+
20
+ class ChromaDB(BaseVectorDB):
21
+ """ChromaDB vector database adapter supporting local disk, in-memory, or remote HTTP."""
22
+
23
+ def __init__(
24
+ self,
25
+ path: str | Path | None = None,
26
+ host: str | None = None,
27
+ port: int | None = None,
28
+ ssl: bool = False,
29
+ headers: dict[str, str] | None = None,
30
+ in_memory: bool = False,
31
+ collection_name: str = DEFAULT_CHROMA_COLLECTION,
32
+ embedding: str | Any | None = None,
33
+ embedding_model: str | None = None,
34
+ embedding_function: Any | None = None,
35
+ **kwargs: Any,
36
+ ) -> None:
37
+ """Initializes ChromaDB adapter.
38
+
39
+ Args:
40
+ path: Local storage path. If ':memory:' or in_memory=True, runs purely in RAM.
41
+ host: Hostname for online/remote ChromaDB server (e.g. 'localhost' or 'api.chroma.io').
42
+ port: Port for remote ChromaDB server (e.g. 8000).
43
+ ssl: Whether to use HTTPS for remote ChromaDB server.
44
+ headers: Optional HTTP headers for remote ChromaDB server (e.g. auth tokens).
45
+ in_memory: If True, operates in ephemeral RAM with zero disk writes.
46
+ collection_name: ChromaDB collection name. Defaults to 'synapse_memory'.
47
+ embedding: Embedding model name ('fastembed', 'minilm', 'openai', etc.) or Embeddings object.
48
+ embedding_model: Backward-compatible alias for embedding model name.
49
+ embedding_function: Optional custom embedding function.
50
+ **kwargs: Extra parameters forwarded to the embedding resolver.
51
+ """
52
+ self.collection_name = collection_name
53
+ self.embedding_function = resolve_embedding(
54
+ embedding=embedding or embedding_function or embedding_model,
55
+ **kwargs,
56
+ )
57
+
58
+ if host is not None:
59
+ # Online / remote ChromaDB server
60
+ self.client = native_chromadb.HttpClient(
61
+ host=host,
62
+ port=port or 8000,
63
+ ssl=ssl,
64
+ headers=headers,
65
+ )
66
+ elif in_memory or path == ":memory:":
67
+ # Pure in-memory ephemeral client (0 disk writes)
68
+ self.client = native_chromadb.EphemeralClient()
69
+ else:
70
+ # Local persistent on-disk ChromaDB
71
+ resolved_path = Path(path or DEFAULT_CHROMA_DIR).resolve()
72
+ resolved_path.mkdir(parents=True, exist_ok=True)
73
+ self.client = native_chromadb.PersistentClient(path=str(resolved_path))
74
+
75
+ self.store = Chroma(
76
+ client=self.client,
77
+ collection_name=collection_name,
78
+ embedding_function=self.embedding_function,
79
+ )
80
+
81
+ def add_documents(
82
+ self,
83
+ documents: list[Document],
84
+ embeddings: list[list[float]] | None = None,
85
+ ) -> list[str]:
86
+ """Upserts documents into ChromaDB."""
87
+ if not documents:
88
+ return []
89
+
90
+ ids: list[str] | None = None
91
+ has_chunk_ids = all("chunk_id" in doc.metadata for doc in documents)
92
+ if has_chunk_ids:
93
+ ids = [str(doc.metadata["chunk_id"]) for doc in documents]
94
+
95
+ return self.store.add_documents(documents=documents, ids=ids)
96
+
97
+ def similarity_search(
98
+ self,
99
+ query: str,
100
+ k: int = 4,
101
+ filter_dict: dict[str, Any] | None = None,
102
+ query_embedding: list[float] | None = None,
103
+ ) -> list[Document]:
104
+ """Performs semantic search in ChromaDB."""
105
+ return self.store.similarity_search(query=query, k=k, filter=filter_dict)
106
+
107
+ def count(self) -> int:
108
+ """Returns total document count in the collection."""
109
+ try:
110
+ col = self.client.get_collection(self.collection_name)
111
+ return col.count()
112
+ except Exception:
113
+ return 0
114
+
115
+ def clear(self) -> None:
116
+ """Deletes and recreates the collection."""
117
+ try:
118
+ self.client.delete_collection(self.collection_name)
119
+ except Exception:
120
+ pass # nosec B110
121
+ self.store = Chroma(
122
+ client=self.client,
123
+ collection_name=self.collection_name,
124
+ embedding_function=self.embedding_function,
125
+ )
126
+
127
+
128
+ def chromadb(
129
+ path: str | Path | None = None,
130
+ host: str | None = None,
131
+ port: int | None = None,
132
+ ssl: bool = False,
133
+ headers: dict[str, str] | None = None,
134
+ in_memory: bool = False,
135
+ collection_name: str = DEFAULT_CHROMA_COLLECTION,
136
+ embedding: str | Any | None = None,
137
+ embedding_model: str | None = None,
138
+ embedding_function: Any | None = None,
139
+ **kwargs: Any,
140
+ ) -> ChromaDB:
141
+ """Factory helper to configure a ChromaDB vector database instance.
142
+
143
+ Example:
144
+ ```python
145
+ from synapse.database import chromadb
146
+ from synapse.storage import vectorStorage
147
+
148
+ # Local persistent with MiniLM:
149
+ db = chromadb("data/chroma_db", embedding="minilm")
150
+
151
+ # In-memory ephemeral with FastEmbed BGE:
152
+ db = chromadb(in_memory=True, embedding="fastembed")
153
+
154
+ # Online remote server with OpenAI embeddings:
155
+ db = chromadb(host="my-chroma.internal", port=8000, embedding="openai")
156
+
157
+ storage = vectorStorage(database=db)
158
+ ```
159
+ """
160
+ return ChromaDB(
161
+ path=path,
162
+ host=host,
163
+ port=port,
164
+ ssl=ssl,
165
+ headers=headers,
166
+ in_memory=in_memory,
167
+ collection_name=collection_name,
168
+ embedding=embedding,
169
+ embedding_model=embedding_model,
170
+ embedding_function=embedding_function,
171
+ **kwargs,
172
+ )
173
+
174
+
175
+ __all__ = ["ChromaDB", "chromadb"]
@@ -0,0 +1,132 @@
1
+ """Pure in-memory vector database backend with zero disk dependencies."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ import uuid
7
+ from typing import Any, Union
8
+
9
+ from langchain_core.documents import Document
10
+
11
+ from synapse.database.base import BaseVectorDB
12
+ from synapse.embeddings import resolve_embedding
13
+
14
+
15
+ class InMemoryDB(BaseVectorDB):
16
+ """Pure in-memory vector database using cosine similarity in RAM."""
17
+
18
+ def __init__(
19
+ self,
20
+ embedding: Union[str, Any] | None = None,
21
+ embedding_model: str | None = None,
22
+ embedding_function: Any | None = None,
23
+ **kwargs: Any,
24
+ ) -> None:
25
+ """Initializes the in-memory vector database."""
26
+ self.embedding_function = resolve_embedding(
27
+ embedding=embedding or embedding_function or embedding_model,
28
+ **kwargs,
29
+ )
30
+ self._entries: list[tuple[str, list[float], Document]] = []
31
+
32
+ def _cosine_similarity(self, a: list[float], b: list[float]) -> float:
33
+ """Calculates cosine similarity between two vector embeddings."""
34
+ dot = sum(x * y for x, y in zip(a, b))
35
+ norm_a = math.sqrt(sum(x * x for x in a))
36
+ norm_b = math.sqrt(sum(y * y for y in b))
37
+ if norm_a == 0.0 or norm_b == 0.0:
38
+ return 0.0
39
+ return dot / (norm_a * norm_b)
40
+
41
+ def add_documents(
42
+ self,
43
+ documents: list[Document],
44
+ embeddings: list[list[float]] | None = None,
45
+ ) -> list[str]:
46
+ """Upserts documents into memory."""
47
+ if not documents:
48
+ return []
49
+
50
+ texts = [doc.page_content for doc in documents]
51
+ vecs = embeddings or self.embedding_function.embed_documents(texts)
52
+ assigned_ids: list[str] = []
53
+
54
+ for doc, vec in zip(documents, vecs):
55
+ doc_id = str(doc.metadata.get("chunk_id") or uuid.uuid4())
56
+ # Replace if same ID exists
57
+ self._entries = [e for e in self._entries if e[0] != doc_id]
58
+ self._entries.append((doc_id, vec, doc))
59
+ assigned_ids.append(doc_id)
60
+
61
+ return assigned_ids
62
+
63
+ def similarity_search(
64
+ self,
65
+ query: str,
66
+ k: int = 4,
67
+ filter_dict: dict[str, Any] | None = None,
68
+ query_embedding: list[float] | None = None,
69
+ ) -> list[Document]:
70
+ """Performs nearest-neighbor search in RAM using cosine similarity."""
71
+ if not self._entries:
72
+ return []
73
+
74
+ q_vec = query_embedding or self.embedding_function.embed_query(query)
75
+ scored: list[tuple[float, Document]] = []
76
+
77
+ for _, vec, doc in self._entries:
78
+ # Check optional metadata filter
79
+ if filter_dict:
80
+ match = all(
81
+ doc.metadata.get(kf) == vf for kf, vf in filter_dict.items()
82
+ )
83
+ if not match:
84
+ continue
85
+
86
+ score = self._cosine_similarity(q_vec, vec)
87
+ scored.append((score, doc))
88
+
89
+ # Sort descending by cosine similarity score
90
+ scored.sort(key=lambda x: x[0], reverse=True)
91
+ return [doc for _, doc in scored[:k]]
92
+
93
+ def count(self) -> int:
94
+ """Returns the number of documents stored in RAM."""
95
+ return len(self._entries)
96
+
97
+ def clear(self) -> None:
98
+ """Clears all in-memory entries."""
99
+ self._entries.clear()
100
+
101
+
102
+ def in_memory(
103
+ embedding: Union[str, Any] | None = None,
104
+ embedding_model: str | None = None,
105
+ embedding_function: Any | None = None,
106
+ **kwargs: Any,
107
+ ) -> InMemoryDB:
108
+ """Factory helper creating an ephemeral in-memory vector database.
109
+
110
+ Example:
111
+ ```python
112
+ from synapse.database import in_memory
113
+ from synapse.storage import vectorStorage
114
+
115
+ # In-memory with MiniLM:
116
+ db = in_memory(embedding="minilm")
117
+
118
+ # In-memory with FastEmbed BGE:
119
+ db = in_memory(embedding="fastembed")
120
+
121
+ storage = vectorStorage(database=db)
122
+ ```
123
+ """
124
+ return InMemoryDB(
125
+ embedding=embedding,
126
+ embedding_model=embedding_model,
127
+ embedding_function=embedding_function,
128
+ **kwargs,
129
+ )
130
+
131
+
132
+ __all__ = ["InMemoryDB", "in_memory"]
@@ -0,0 +1,99 @@
1
+ """PostgreSQL PGVector database provider for Synapse."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Union
6
+
7
+ from langchain_core.documents import Document
8
+
9
+ from synapse.database.base import BaseVectorDB
10
+ from synapse.embeddings import resolve_embedding
11
+
12
+
13
+ class PGVectorDB(BaseVectorDB):
14
+ """PostgreSQL pgvector database adapter for enterprise deployments."""
15
+
16
+ def __init__(
17
+ self,
18
+ connection_string: str,
19
+ collection_name: str = "synapse_embeddings",
20
+ embedding: Union[str, Any] | None = None,
21
+ embedding_model: str | None = None,
22
+ embedding_function: Any | None = None,
23
+ **kwargs: Any,
24
+ ) -> None:
25
+ self.connection_string = connection_string
26
+ self.collection_name = collection_name
27
+ self.embedding_function = resolve_embedding(
28
+ embedding=embedding or embedding_function or embedding_model,
29
+ **kwargs,
30
+ )
31
+
32
+ try:
33
+ from langchain_community.vectorstores import PGVector
34
+
35
+ self.store = PGVector(
36
+ connection_string=connection_string,
37
+ collection_name=collection_name,
38
+ embedding_function=self.embedding_function,
39
+ )
40
+ except ImportError:
41
+ from synapse.database.memory import InMemoryDB
42
+ self._fallback = InMemoryDB(
43
+ embedding_model=embedding_model,
44
+ embedding_function=self.embedding_function,
45
+ )
46
+ self.store = None
47
+
48
+ def add_documents(
49
+ self,
50
+ documents: list[Document],
51
+ embeddings: list[list[float]] | None = None,
52
+ ) -> list[str]:
53
+ if self.store:
54
+ return self.store.add_documents(documents)
55
+ return self._fallback.add_documents(documents, embeddings)
56
+
57
+ def similarity_search(
58
+ self,
59
+ query: str,
60
+ k: int = 4,
61
+ filter_dict: dict[str, Any] | None = None,
62
+ query_embedding: list[float] | None = None,
63
+ ) -> list[Document]:
64
+ if self.store:
65
+ return self.store.similarity_search(query=query, k=k)
66
+ return self._fallback.similarity_search(query=query, k=k, filter_dict=filter_dict)
67
+
68
+ def count(self) -> int:
69
+ if self.store:
70
+ return 0
71
+ return self._fallback.count()
72
+
73
+ def clear(self) -> None:
74
+ if self.store:
75
+ pass
76
+ else:
77
+ self._fallback.clear()
78
+
79
+
80
+ def pgvector(
81
+ connection_string: str,
82
+ collection_name: str = "synapse_embeddings",
83
+ embedding: Union[str, Any] | None = None,
84
+ embedding_model: str | None = None,
85
+ embedding_function: Any | None = None,
86
+ **kwargs: Any,
87
+ ) -> PGVectorDB:
88
+ """Factory helper to configure a PostgreSQL PGVector database instance."""
89
+ return PGVectorDB(
90
+ connection_string=connection_string,
91
+ collection_name=collection_name,
92
+ embedding=embedding,
93
+ embedding_model=embedding_model,
94
+ embedding_function=embedding_function,
95
+ **kwargs,
96
+ )
97
+
98
+
99
+ __all__ = ["PGVectorDB", "pgvector"]