langchain-google-cloud-sql-pg 0.14.1__tar.gz → 0.16.0__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.
- {langchain_google_cloud_sql_pg-0.14.1/src/langchain_google_cloud_sql_pg.egg-info → langchain_google_cloud_sql_pg-0.16.0}/PKG-INFO +33 -16
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/README.rst +21 -1
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/pyproject.toml +12 -15
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/__init__.py +11 -1
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/async_chat_message_history.py +1 -1
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/async_checkpoint.py +5 -3
- langchain_google_cloud_sql_pg-0.16.0/src/langchain_google_cloud_sql_pg/async_vectorstore.py +25 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/engine.py +18 -247
- langchain_google_cloud_sql_pg-0.16.0/src/langchain_google_cloud_sql_pg/indexes.py +27 -0
- langchain_google_cloud_sql_pg-0.16.0/src/langchain_google_cloud_sql_pg/vectorstore.py +167 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/version.py +1 -1
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0/src/langchain_google_cloud_sql_pg.egg-info}/PKG-INFO +33 -16
- langchain_google_cloud_sql_pg-0.16.0/src/langchain_google_cloud_sql_pg.egg-info/requires.txt +21 -0
- langchain_google_cloud_sql_pg-0.16.0/tests/test_async_chatmessagehistory.py +169 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_async_checkpoint.py +111 -42
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_async_loader.py +279 -188
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_async_vectorstore.py +187 -118
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_async_vectorstore_from_methods.py +106 -67
- langchain_google_cloud_sql_pg-0.16.0/tests/test_async_vectorstore_index.py +267 -0
- langchain_google_cloud_sql_pg-0.16.0/tests/test_async_vectorstore_search.py +852 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_checkpoint.py +2 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_engine.py +144 -36
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_standard_test_suite.py +2 -2
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_vectorstore.py +2 -2
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_vectorstore_from_methods.py +2 -4
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_vectorstore_index.py +4 -4
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_vectorstore_search.py +72 -12
- langchain_google_cloud_sql_pg-0.14.1/src/langchain_google_cloud_sql_pg/async_vectorstore.py +0 -1201
- langchain_google_cloud_sql_pg-0.14.1/src/langchain_google_cloud_sql_pg/indexes.py +0 -105
- langchain_google_cloud_sql_pg-0.14.1/src/langchain_google_cloud_sql_pg/vectorstore.py +0 -823
- langchain_google_cloud_sql_pg-0.14.1/src/langchain_google_cloud_sql_pg.egg-info/requires.txt +0 -26
- langchain_google_cloud_sql_pg-0.14.1/tests/test_async_chatmessagehistory.py +0 -123
- langchain_google_cloud_sql_pg-0.14.1/tests/test_async_vectorstore_index.py +0 -143
- langchain_google_cloud_sql_pg-0.14.1/tests/test_async_vectorstore_search.py +0 -343
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/LICENSE +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/setup.cfg +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/async_loader.py +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/chat_message_history.py +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/checkpoint.py +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/loader.py +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg/py.typed +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg.egg-info/SOURCES.txt +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg.egg-info/dependency_links.txt +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/src/langchain_google_cloud_sql_pg.egg-info/top_level.txt +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_chatmessagehistory.py +0 -0
- {langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/tests/test_loader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langchain-google-cloud-sql-pg
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: LangChain integrations for Google Cloud SQL for PostgreSQL
|
|
5
5
|
Author-email: Google LLC <googleapis-packages@google.com>
|
|
6
6
|
License:
|
|
@@ -214,31 +214,28 @@ Classifier: Intended Audience :: Developers
|
|
|
214
214
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
215
215
|
Classifier: Programming Language :: Python
|
|
216
216
|
Classifier: Programming Language :: Python :: 3
|
|
217
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
218
217
|
Classifier: Programming Language :: Python :: 3.10
|
|
219
218
|
Classifier: Programming Language :: Python :: 3.11
|
|
220
219
|
Classifier: Programming Language :: Python :: 3.12
|
|
221
|
-
|
|
220
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
221
|
+
Requires-Python: >=3.10
|
|
222
222
|
Description-Content-Type: text/x-rst
|
|
223
223
|
License-File: LICENSE
|
|
224
224
|
Requires-Dist: cloud-sql-python-connector[asyncpg]<2.0.0,>=1.10.0
|
|
225
|
-
Requires-Dist: langchain-core<1.0.0,>=0.2.36
|
|
226
225
|
Requires-Dist: numpy<3.0.0,>=1.24.4; python_version >= "3.11"
|
|
227
226
|
Requires-Dist: numpy<=2.2.6,>=1.24.4; python_version == "3.10"
|
|
228
|
-
Requires-Dist:
|
|
229
|
-
Requires-Dist: pgvector<1.0.0,>=0.2.5
|
|
230
|
-
Requires-Dist: SQLAlchemy[asyncio]<3.0.0,>=2.0.25
|
|
227
|
+
Requires-Dist: langchain-postgres>=0.0.16
|
|
231
228
|
Provides-Extra: langgraph
|
|
232
|
-
Requires-Dist: langgraph-checkpoint<
|
|
229
|
+
Requires-Dist: langgraph-checkpoint<5.0.0,>=4.0.0; extra == "langgraph"
|
|
233
230
|
Provides-Extra: test
|
|
234
|
-
Requires-Dist: black[jupyter]==
|
|
235
|
-
Requires-Dist: isort==
|
|
236
|
-
Requires-Dist: mypy==1.
|
|
231
|
+
Requires-Dist: black[jupyter]==26.3.1; extra == "test"
|
|
232
|
+
Requires-Dist: isort==9.0.2; extra == "test"
|
|
233
|
+
Requires-Dist: mypy==1.19.1; extra == "test"
|
|
237
234
|
Requires-Dist: pytest-asyncio==0.26.0; extra == "test"
|
|
238
|
-
Requires-Dist: pytest==8.4.
|
|
239
|
-
Requires-Dist: pytest-cov==
|
|
240
|
-
Requires-Dist: langchain-tests==
|
|
241
|
-
Requires-Dist: langgraph
|
|
235
|
+
Requires-Dist: pytest==8.4.2; extra == "test"
|
|
236
|
+
Requires-Dist: pytest-cov==7.0.0; extra == "test"
|
|
237
|
+
Requires-Dist: langchain-tests==1.1.2; extra == "test"
|
|
238
|
+
Requires-Dist: langgraph>=1.2.2; extra == "test"
|
|
242
239
|
Dynamic: license-file
|
|
243
240
|
|
|
244
241
|
Cloud SQL for PostgreSQL for LangChain
|
|
@@ -299,7 +296,7 @@ dependencies.
|
|
|
299
296
|
Supported Python Versions
|
|
300
297
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
301
298
|
|
|
302
|
-
Python >= 3.
|
|
299
|
+
Python >= 3.10
|
|
303
300
|
|
|
304
301
|
Mac/Linux
|
|
305
302
|
^^^^^^^^^
|
|
@@ -354,6 +351,26 @@ Use a Vector Store to store embedded data and perform vector search.
|
|
|
354
351
|
embeddings=embedding_service
|
|
355
352
|
)
|
|
356
353
|
|
|
354
|
+
Hybrid search
|
|
355
|
+
~~~~~~~~~~~~~
|
|
356
|
+
|
|
357
|
+
The `PostgresVectorStore` supports hybrid search (dense vectors + full text) for more comprehensive and relevant search results.
|
|
358
|
+
|
|
359
|
+
.. code-block:: python
|
|
360
|
+
|
|
361
|
+
from langchain_google_cloud_sql_pg import HybridSearchConfig, reciprocal_rank_fusion
|
|
362
|
+
|
|
363
|
+
vs = PostgresVectorStore.create_sync(
|
|
364
|
+
engine=engine,
|
|
365
|
+
table_name=TABLE_NAME,
|
|
366
|
+
embedding_service=embedding,
|
|
367
|
+
hybrid_search_config=HybridSearchConfig(
|
|
368
|
+
fusion_function=reciprocal_rank_fusion
|
|
369
|
+
),
|
|
370
|
+
)
|
|
371
|
+
hybrid_docs = vector_store.similarity_search("products", k=5)
|
|
372
|
+
|
|
373
|
+
|
|
357
374
|
See the full `Vector Store`_ tutorial.
|
|
358
375
|
|
|
359
376
|
.. _`Vector Store`: https://github.com/googleapis/langchain-google-cloud-sql-pg-python/tree/main/docs/vector_store.ipynb
|
|
@@ -56,7 +56,7 @@ dependencies.
|
|
|
56
56
|
Supported Python Versions
|
|
57
57
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
58
58
|
|
|
59
|
-
Python >= 3.
|
|
59
|
+
Python >= 3.10
|
|
60
60
|
|
|
61
61
|
Mac/Linux
|
|
62
62
|
^^^^^^^^^
|
|
@@ -111,6 +111,26 @@ Use a Vector Store to store embedded data and perform vector search.
|
|
|
111
111
|
embeddings=embedding_service
|
|
112
112
|
)
|
|
113
113
|
|
|
114
|
+
Hybrid search
|
|
115
|
+
~~~~~~~~~~~~~
|
|
116
|
+
|
|
117
|
+
The `PostgresVectorStore` supports hybrid search (dense vectors + full text) for more comprehensive and relevant search results.
|
|
118
|
+
|
|
119
|
+
.. code-block:: python
|
|
120
|
+
|
|
121
|
+
from langchain_google_cloud_sql_pg import HybridSearchConfig, reciprocal_rank_fusion
|
|
122
|
+
|
|
123
|
+
vs = PostgresVectorStore.create_sync(
|
|
124
|
+
engine=engine,
|
|
125
|
+
table_name=TABLE_NAME,
|
|
126
|
+
embedding_service=embedding,
|
|
127
|
+
hybrid_search_config=HybridSearchConfig(
|
|
128
|
+
fusion_function=reciprocal_rank_fusion
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
hybrid_docs = vector_store.similarity_search("products", k=5)
|
|
132
|
+
|
|
133
|
+
|
|
114
134
|
See the full `Vector Store`_ tutorial.
|
|
115
135
|
|
|
116
136
|
.. _`Vector Store`: https://github.com/googleapis/langchain-google-cloud-sql-pg-python/tree/main/docs/vector_store.ipynb
|
{langchain_google_cloud_sql_pg-0.14.1 → langchain_google_cloud_sql_pg-0.16.0}/pyproject.toml
RENAMED
|
@@ -4,19 +4,16 @@ dynamic = ["version"]
|
|
|
4
4
|
description = "LangChain integrations for Google Cloud SQL for PostgreSQL"
|
|
5
5
|
readme = "README.rst"
|
|
6
6
|
license = {file = "LICENSE"}
|
|
7
|
-
requires-python = ">=3.
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
8
|
authors = [
|
|
9
9
|
{name = "Google LLC", email = "googleapis-packages@google.com"}
|
|
10
10
|
]
|
|
11
11
|
|
|
12
12
|
dependencies = [
|
|
13
13
|
"cloud-sql-python-connector[asyncpg] >= 1.10.0, <2.0.0",
|
|
14
|
-
"langchain-core>=0.2.36, <1.0.0 ",
|
|
15
14
|
"numpy>=1.24.4, <3.0.0; python_version >= '3.11'",
|
|
16
15
|
"numpy>=1.24.4, <=2.2.6; python_version == '3.10'",
|
|
17
|
-
"
|
|
18
|
-
"pgvector>=0.2.5, <1.0.0",
|
|
19
|
-
"SQLAlchemy[asyncio]>=2.0.25, <3.0.0"
|
|
16
|
+
"langchain-postgres>=0.0.16",
|
|
20
17
|
]
|
|
21
18
|
|
|
22
19
|
classifiers = [
|
|
@@ -24,10 +21,10 @@ classifiers = [
|
|
|
24
21
|
"License :: OSI Approved :: Apache Software License",
|
|
25
22
|
"Programming Language :: Python",
|
|
26
23
|
"Programming Language :: Python :: 3",
|
|
27
|
-
"Programming Language :: Python :: 3.9",
|
|
28
24
|
"Programming Language :: Python :: 3.10",
|
|
29
25
|
"Programming Language :: Python :: 3.11",
|
|
30
26
|
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
31
28
|
]
|
|
32
29
|
|
|
33
30
|
[tool.setuptools.dynamic]
|
|
@@ -41,17 +38,17 @@ Changelog = "https://github.com/googleapis/langchain-google-cloud-sql-pg-python/
|
|
|
41
38
|
|
|
42
39
|
[project.optional-dependencies]
|
|
43
40
|
langgraph = [
|
|
44
|
-
"langgraph-checkpoint>=
|
|
41
|
+
"langgraph-checkpoint>=4.0.0, <5.0.0"
|
|
45
42
|
]
|
|
46
43
|
test = [
|
|
47
|
-
"black[jupyter]==
|
|
48
|
-
"isort==
|
|
49
|
-
"mypy==1.
|
|
44
|
+
"black[jupyter]==26.3.1",
|
|
45
|
+
"isort==9.0.2",
|
|
46
|
+
"mypy==1.19.1",
|
|
50
47
|
"pytest-asyncio==0.26.0",
|
|
51
|
-
"pytest==8.4.
|
|
52
|
-
"pytest-cov==
|
|
53
|
-
"langchain-tests==
|
|
54
|
-
"langgraph
|
|
48
|
+
"pytest==8.4.2",
|
|
49
|
+
"pytest-cov==7.0.0",
|
|
50
|
+
"langchain-tests==1.1.2",
|
|
51
|
+
"langgraph>=1.2.2"
|
|
55
52
|
]
|
|
56
53
|
|
|
57
54
|
[build-system]
|
|
@@ -65,7 +62,7 @@ target-version = ['py39']
|
|
|
65
62
|
profile = "black"
|
|
66
63
|
|
|
67
64
|
[tool.mypy]
|
|
68
|
-
python_version = 3.
|
|
65
|
+
python_version = "3.10"
|
|
69
66
|
warn_unused_configs = true
|
|
70
67
|
disallow_incomplete_defs = true
|
|
71
68
|
|
|
@@ -12,10 +12,17 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from langchain_postgres import Column
|
|
16
|
+
from langchain_postgres.v2.hybrid_search_config import (
|
|
17
|
+
HybridSearchConfig,
|
|
18
|
+
reciprocal_rank_fusion,
|
|
19
|
+
weighted_sum_ranking,
|
|
20
|
+
)
|
|
21
|
+
|
|
15
22
|
from . import indexes
|
|
16
23
|
from .chat_message_history import PostgresChatMessageHistory
|
|
17
24
|
from .checkpoint import PostgresSaver
|
|
18
|
-
from .engine import
|
|
25
|
+
from .engine import PostgresEngine
|
|
19
26
|
from .loader import PostgresDocumentSaver, PostgresLoader
|
|
20
27
|
from .vectorstore import PostgresVectorStore
|
|
21
28
|
from .version import __version__
|
|
@@ -29,5 +36,8 @@ __all__ = [
|
|
|
29
36
|
"PostgresLoader",
|
|
30
37
|
"PostgresDocumentSaver",
|
|
31
38
|
"PostgresSaver",
|
|
39
|
+
"HybridSearchConfig",
|
|
40
|
+
"reciprocal_rank_fusion",
|
|
41
|
+
"weighted_sum_ranking",
|
|
32
42
|
"__version__",
|
|
33
43
|
]
|
|
@@ -98,7 +98,7 @@ class AsyncPostgresChatMessageHistory(BaseChatMessageHistory):
|
|
|
98
98
|
"\n type TEXT NOT NULL"
|
|
99
99
|
"\n);"
|
|
100
100
|
)
|
|
101
|
-
return cls(cls.__create_key, engine._pool, session_id, table_name)
|
|
101
|
+
return cls(cls.__create_key, engine._pool, session_id, table_name, schema_name)
|
|
102
102
|
|
|
103
103
|
async def aadd_message(self, message: BaseMessage) -> None:
|
|
104
104
|
"""Append the message to the record in PostgreSQL"""
|
|
@@ -276,7 +276,9 @@ class AsyncPostgresSaver(BaseCheckpointSaver[str]):
|
|
|
276
276
|
|
|
277
277
|
async with self.pool.connect() as conn:
|
|
278
278
|
type_, serialized_checkpoint = self.serde.dumps_typed(checkpoint)
|
|
279
|
-
serialized_metadata =
|
|
279
|
+
serialized_metadata = json.dumps(metadata, ensure_ascii=False).encode(
|
|
280
|
+
"utf-8", "ignore"
|
|
281
|
+
)
|
|
280
282
|
await conn.execute(
|
|
281
283
|
text(query),
|
|
282
284
|
{
|
|
@@ -409,7 +411,7 @@ class AsyncPostgresSaver(BaseCheckpointSaver[str]):
|
|
|
409
411
|
(value["type"], value["checkpoint"])
|
|
410
412
|
),
|
|
411
413
|
metadata=(
|
|
412
|
-
|
|
414
|
+
json.loads(value["metadata"]) # type: ignore
|
|
413
415
|
if value["metadata"] is not None
|
|
414
416
|
else {}
|
|
415
417
|
),
|
|
@@ -494,7 +496,7 @@ class AsyncPostgresSaver(BaseCheckpointSaver[str]):
|
|
|
494
496
|
},
|
|
495
497
|
checkpoint=self.serde.loads_typed((value["type"], value["checkpoint"])),
|
|
496
498
|
metadata=(
|
|
497
|
-
|
|
499
|
+
json.loads(value["metadata"]) # type: ignore
|
|
498
500
|
if value["metadata"] is not None
|
|
499
501
|
else {}
|
|
500
502
|
),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright 2024 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# TODO: Remove below import when minimum supported Python version is 3.10
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from langchain_postgres.v2.async_vectorstore import AsyncPGVectorStore
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AsyncPostgresVectorStore(AsyncPGVectorStore):
|
|
22
|
+
"""Google Cloud SQL for PostgreSQL Vector Store class"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, *args, **kwargs):
|
|
25
|
+
super().__init__(*args, **kwargs)
|
|
@@ -24,6 +24,7 @@ import aiohttp
|
|
|
24
24
|
import google.auth # type: ignore
|
|
25
25
|
import google.auth.transport.requests # type: ignore
|
|
26
26
|
from google.cloud.sql.connector import Connector, IPTypes, RefreshStrategy
|
|
27
|
+
from langchain_postgres import Column, PGEngine
|
|
27
28
|
from sqlalchemy import MetaData, Table, text
|
|
28
29
|
from sqlalchemy.engine import URL
|
|
29
30
|
from sqlalchemy.exc import InvalidRequestError
|
|
@@ -78,58 +79,10 @@ async def _get_iam_principal_email(
|
|
|
78
79
|
return email.replace(".gserviceaccount.com", "")
|
|
79
80
|
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
class Column:
|
|
83
|
-
name: str
|
|
84
|
-
data_type: str
|
|
85
|
-
nullable: bool = True
|
|
86
|
-
|
|
87
|
-
def __post_init__(self):
|
|
88
|
-
"""Check if initialization parameters are valid.
|
|
89
|
-
|
|
90
|
-
Raises:
|
|
91
|
-
ValueError: Raises error if Column name is not string.
|
|
92
|
-
ValueError: Raises error if data_type is not type string.
|
|
93
|
-
"""
|
|
94
|
-
if not isinstance(self.name, str):
|
|
95
|
-
raise ValueError("Column name must be type string")
|
|
96
|
-
if not isinstance(self.data_type, str):
|
|
97
|
-
raise ValueError("Column data_type must be type string")
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class PostgresEngine:
|
|
82
|
+
class PostgresEngine(PGEngine):
|
|
101
83
|
"""A class for managing connections to a Cloud SQL for Postgres database."""
|
|
102
84
|
|
|
103
85
|
_connector: Optional[Connector] = None
|
|
104
|
-
_default_loop: Optional[asyncio.AbstractEventLoop] = None
|
|
105
|
-
_default_thread: Optional[Thread] = None
|
|
106
|
-
__create_key = object()
|
|
107
|
-
|
|
108
|
-
def __init__(
|
|
109
|
-
self,
|
|
110
|
-
key: object,
|
|
111
|
-
pool: AsyncEngine,
|
|
112
|
-
loop: Optional[asyncio.AbstractEventLoop],
|
|
113
|
-
thread: Optional[Thread],
|
|
114
|
-
):
|
|
115
|
-
"""PostgresEngine constructor.
|
|
116
|
-
|
|
117
|
-
Args:
|
|
118
|
-
key (object): Prevent direct constructor usage.
|
|
119
|
-
pool (AsyncEngine): Async engine connection pool.
|
|
120
|
-
loop (Optional[asyncio.AbstractEventLoop]): Async event loop used to create the engine.
|
|
121
|
-
thread (Optional[Thread]): Thread used to create the engine async.
|
|
122
|
-
|
|
123
|
-
Raises:
|
|
124
|
-
Exception: If the constructor is called directly by the user.
|
|
125
|
-
"""
|
|
126
|
-
if key != PostgresEngine.__create_key:
|
|
127
|
-
raise Exception(
|
|
128
|
-
"Only create class through 'create' or 'create_sync' methods!"
|
|
129
|
-
)
|
|
130
|
-
self._pool = pool
|
|
131
|
-
self._loop = loop
|
|
132
|
-
self._thread = thread
|
|
133
86
|
|
|
134
87
|
@classmethod
|
|
135
88
|
async def _create(
|
|
@@ -219,7 +172,7 @@ class PostgresEngine:
|
|
|
219
172
|
async_creator=getconn,
|
|
220
173
|
**engine_args,
|
|
221
174
|
)
|
|
222
|
-
return cls(
|
|
175
|
+
return cls(PGEngine._PGEngine__create_key, engine, loop, thread) # type: ignore
|
|
223
176
|
|
|
224
177
|
@classmethod
|
|
225
178
|
def __start_background_loop(
|
|
@@ -354,13 +307,22 @@ class PostgresEngine:
|
|
|
354
307
|
return await asyncio.wrap_future(future)
|
|
355
308
|
|
|
356
309
|
@classmethod
|
|
357
|
-
def
|
|
310
|
+
def from_connection_string(
|
|
358
311
|
cls,
|
|
359
|
-
|
|
360
|
-
|
|
312
|
+
url: str | URL,
|
|
313
|
+
**kwargs: Any,
|
|
361
314
|
) -> PostgresEngine:
|
|
362
|
-
"""Create an PostgresEngine instance from
|
|
363
|
-
|
|
315
|
+
"""Create an PostgresEngine instance from arguments. These parameters are pass directly into sqlalchemy's create_async_engine function.
|
|
316
|
+
Args:
|
|
317
|
+
url (Union[str | URL]): the URL used to connect to a database
|
|
318
|
+
**kwargs (Any, optional): sqlalchemy `create_async_engine` arguments
|
|
319
|
+
Raises:
|
|
320
|
+
ValueError: If `postgresql+asyncpg` is not specified as the PG driver
|
|
321
|
+
Returns:
|
|
322
|
+
PostgresEngine
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
return PostgresEngine.from_engine_args(url=url, **kwargs)
|
|
364
326
|
|
|
365
327
|
@classmethod
|
|
366
328
|
def from_engine_args(
|
|
@@ -396,198 +358,7 @@ class PostgresEngine:
|
|
|
396
358
|
raise ValueError("Driver must be type 'postgresql+asyncpg'")
|
|
397
359
|
|
|
398
360
|
engine = create_async_engine(url, **kwargs)
|
|
399
|
-
return cls(
|
|
400
|
-
|
|
401
|
-
async def _run_as_async(self, coro: Awaitable[T]) -> T:
|
|
402
|
-
"""Run an async coroutine asynchronously"""
|
|
403
|
-
# If a loop has not been provided, attempt to run in current thread
|
|
404
|
-
if not self._loop:
|
|
405
|
-
return await coro
|
|
406
|
-
# Otherwise, run in the background thread
|
|
407
|
-
return await asyncio.wrap_future(
|
|
408
|
-
asyncio.run_coroutine_threadsafe(coro, self._loop)
|
|
409
|
-
)
|
|
410
|
-
|
|
411
|
-
def _run_as_sync(self, coro: Awaitable[T]) -> T:
|
|
412
|
-
"""Run an async coroutine synchronously"""
|
|
413
|
-
if not self._loop:
|
|
414
|
-
raise Exception(
|
|
415
|
-
"Engine was initialized without a background loop and cannot call sync methods."
|
|
416
|
-
)
|
|
417
|
-
return asyncio.run_coroutine_threadsafe(coro, self._loop).result()
|
|
418
|
-
|
|
419
|
-
async def close(self) -> None:
|
|
420
|
-
"""Dispose of connection pool"""
|
|
421
|
-
await self._run_as_async(self._pool.dispose())
|
|
422
|
-
|
|
423
|
-
async def _ainit_vectorstore_table(
|
|
424
|
-
self,
|
|
425
|
-
table_name: str,
|
|
426
|
-
vector_size: int,
|
|
427
|
-
schema_name: str = "public",
|
|
428
|
-
content_column: str = "content",
|
|
429
|
-
embedding_column: str = "embedding",
|
|
430
|
-
metadata_columns: list[Column] = [],
|
|
431
|
-
metadata_json_column: str = "langchain_metadata",
|
|
432
|
-
id_column: Union[str, Column] = "langchain_id",
|
|
433
|
-
overwrite_existing: bool = False,
|
|
434
|
-
store_metadata: bool = True,
|
|
435
|
-
) -> None:
|
|
436
|
-
"""
|
|
437
|
-
Create a table for saving of vectors to be used with PostgresVectorStore.
|
|
438
|
-
|
|
439
|
-
Args:
|
|
440
|
-
table_name (str): The Postgres database table name.
|
|
441
|
-
vector_size (int): Vector size for the embedding model to be used.
|
|
442
|
-
schema_name (str): The schema name to store Postgres database table.
|
|
443
|
-
Default: "public".
|
|
444
|
-
content_column (str): Name of the column to store document content.
|
|
445
|
-
Default: "page_content".
|
|
446
|
-
embedding_column (str) : Name of the column to store vector embeddings.
|
|
447
|
-
Default: "embedding".
|
|
448
|
-
metadata_columns (list[Column]): A list of Columns to create for custom
|
|
449
|
-
metadata. Default: []. Optional.
|
|
450
|
-
metadata_json_column (str): The column to store extra metadata in JSON format.
|
|
451
|
-
Default: "langchain_metadata". Optional.
|
|
452
|
-
id_column (Union[str, Column]) : Column to store ids.
|
|
453
|
-
Default: "langchain_id" column name with data type UUID. Optional.
|
|
454
|
-
overwrite_existing (bool): Whether to drop existing table. Default: False.
|
|
455
|
-
store_metadata (bool): Whether to store metadata in the table.
|
|
456
|
-
Default: True.
|
|
457
|
-
Raises:
|
|
458
|
-
:class:`DuplicateTableError <asyncpg.exceptions.DuplicateTableError>`: if table already exists and overwrite flag is not set.
|
|
459
|
-
:class:`UndefinedObjectError <asyncpg.exceptions.UndefinedObjectError>`: if the data type of the id column is not a postgreSQL data type.
|
|
460
|
-
"""
|
|
461
|
-
async with self._pool.connect() as conn:
|
|
462
|
-
await conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
|
|
463
|
-
await conn.commit()
|
|
464
|
-
|
|
465
|
-
if overwrite_existing:
|
|
466
|
-
async with self._pool.connect() as conn:
|
|
467
|
-
await conn.execute(
|
|
468
|
-
text(f'DROP TABLE IF EXISTS "{schema_name}"."{table_name}"')
|
|
469
|
-
)
|
|
470
|
-
await conn.commit()
|
|
471
|
-
|
|
472
|
-
id_data_type = "UUID" if isinstance(id_column, str) else id_column.data_type
|
|
473
|
-
id_column_name = id_column if isinstance(id_column, str) else id_column.name
|
|
474
|
-
|
|
475
|
-
query = f"""CREATE TABLE "{schema_name}"."{table_name}"(
|
|
476
|
-
"{id_column_name}" {id_data_type} PRIMARY KEY,
|
|
477
|
-
"{content_column}" TEXT NOT NULL,
|
|
478
|
-
"{embedding_column}" vector({vector_size}) NOT NULL"""
|
|
479
|
-
for column in metadata_columns:
|
|
480
|
-
nullable = "NOT NULL" if not column.nullable else ""
|
|
481
|
-
query += f',\n"{column.name}" {column.data_type} {nullable}'
|
|
482
|
-
if store_metadata:
|
|
483
|
-
query += f""",\n"{metadata_json_column}" JSON"""
|
|
484
|
-
query += "\n);"
|
|
485
|
-
|
|
486
|
-
async with self._pool.connect() as conn:
|
|
487
|
-
await conn.execute(text(query))
|
|
488
|
-
await conn.commit()
|
|
489
|
-
|
|
490
|
-
async def ainit_vectorstore_table(
|
|
491
|
-
self,
|
|
492
|
-
table_name: str,
|
|
493
|
-
vector_size: int,
|
|
494
|
-
schema_name: str = "public",
|
|
495
|
-
content_column: str = "content",
|
|
496
|
-
embedding_column: str = "embedding",
|
|
497
|
-
metadata_columns: list[Column] = [],
|
|
498
|
-
metadata_json_column: str = "langchain_metadata",
|
|
499
|
-
id_column: Union[str, Column] = "langchain_id",
|
|
500
|
-
overwrite_existing: bool = False,
|
|
501
|
-
store_metadata: bool = True,
|
|
502
|
-
) -> None:
|
|
503
|
-
"""
|
|
504
|
-
Create a table for saving of vectors to be used with PostgresVectorStore.
|
|
505
|
-
|
|
506
|
-
Args:
|
|
507
|
-
table_name (str): The Postgres database table name.
|
|
508
|
-
vector_size (int): Vector size for the embedding model to be used.
|
|
509
|
-
schema_name (str): The schema name to store Postgres database table.
|
|
510
|
-
Default: "public".
|
|
511
|
-
content_column (str): Name of the column to store document content.
|
|
512
|
-
Default: "page_content".
|
|
513
|
-
embedding_column (str) : Name of the column to store vector embeddings.
|
|
514
|
-
Default: "embedding".
|
|
515
|
-
metadata_columns (list[Column]): A list of Columns to create for custom
|
|
516
|
-
metadata. Default: []. Optional.
|
|
517
|
-
metadata_json_column (str): The column to store extra metadata in JSON format.
|
|
518
|
-
Default: "langchain_metadata". Optional.
|
|
519
|
-
id_column (Union[str, Column]) : Column to store ids.
|
|
520
|
-
Default: "langchain_id" column name with data type UUID. Optional.
|
|
521
|
-
overwrite_existing (bool): Whether to drop existing table. Default: False.
|
|
522
|
-
store_metadata (bool): Whether to store metadata in the table.
|
|
523
|
-
Default: True.
|
|
524
|
-
"""
|
|
525
|
-
await self._run_as_async(
|
|
526
|
-
self._ainit_vectorstore_table(
|
|
527
|
-
table_name,
|
|
528
|
-
vector_size,
|
|
529
|
-
schema_name,
|
|
530
|
-
content_column,
|
|
531
|
-
embedding_column,
|
|
532
|
-
metadata_columns,
|
|
533
|
-
metadata_json_column,
|
|
534
|
-
id_column,
|
|
535
|
-
overwrite_existing,
|
|
536
|
-
store_metadata,
|
|
537
|
-
)
|
|
538
|
-
)
|
|
539
|
-
|
|
540
|
-
def init_vectorstore_table(
|
|
541
|
-
self,
|
|
542
|
-
table_name: str,
|
|
543
|
-
vector_size: int,
|
|
544
|
-
schema_name: str = "public",
|
|
545
|
-
content_column: str = "content",
|
|
546
|
-
embedding_column: str = "embedding",
|
|
547
|
-
metadata_columns: list[Column] = [],
|
|
548
|
-
metadata_json_column: str = "langchain_metadata",
|
|
549
|
-
id_column: Union[str, Column] = "langchain_id",
|
|
550
|
-
overwrite_existing: bool = False,
|
|
551
|
-
store_metadata: bool = True,
|
|
552
|
-
) -> None:
|
|
553
|
-
"""
|
|
554
|
-
Create a table for saving of vectors to be used with PostgresVectorStore.
|
|
555
|
-
|
|
556
|
-
Args:
|
|
557
|
-
table_name (str): The Postgres database table name.
|
|
558
|
-
vector_size (int): Vector size for the embedding model to be used.
|
|
559
|
-
schema_name (str): The schema name to store Postgres database table.
|
|
560
|
-
Default: "public".
|
|
561
|
-
content_column (str): Name of the column to store document content.
|
|
562
|
-
Default: "page_content".
|
|
563
|
-
embedding_column (str) : Name of the column to store vector embeddings.
|
|
564
|
-
Default: "embedding".
|
|
565
|
-
metadata_columns (list[Column]): A list of Columns to create for custom
|
|
566
|
-
metadata. Default: []. Optional.
|
|
567
|
-
metadata_json_column (str): The column to store extra metadata in JSON format.
|
|
568
|
-
Default: "langchain_metadata". Optional.
|
|
569
|
-
id_column (Union[str, Column]) : Column to store ids.
|
|
570
|
-
Default: "langchain_id" column name with data type UUID. Optional.
|
|
571
|
-
overwrite_existing (bool): Whether to drop existing table. Default: False.
|
|
572
|
-
store_metadata (bool): Whether to store metadata in the table.
|
|
573
|
-
Default: True.
|
|
574
|
-
Raises:
|
|
575
|
-
:class:`UndefinedObjectError <asyncpg.exceptions.UndefinedObjectError>`: if the `ids` data type does not match that of the `id_column`.
|
|
576
|
-
"""
|
|
577
|
-
self._run_as_sync(
|
|
578
|
-
self._ainit_vectorstore_table(
|
|
579
|
-
table_name,
|
|
580
|
-
vector_size,
|
|
581
|
-
schema_name,
|
|
582
|
-
content_column,
|
|
583
|
-
embedding_column,
|
|
584
|
-
metadata_columns,
|
|
585
|
-
metadata_json_column,
|
|
586
|
-
id_column,
|
|
587
|
-
overwrite_existing,
|
|
588
|
-
store_metadata,
|
|
589
|
-
)
|
|
590
|
-
)
|
|
361
|
+
return cls(PGEngine._PGEngine__create_key, engine, cls._default_loop, cls._default_thread) # type: ignore
|
|
591
362
|
|
|
592
363
|
async def _ainit_chat_history_table(
|
|
593
364
|
self, table_name: str, schema_name: str = "public"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Copyright 2024 Google LLC
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from langchain_postgres.v2.indexes import (
|
|
16
|
+
DEFAULT_DISTANCE_STRATEGY,
|
|
17
|
+
DEFAULT_INDEX_NAME_SUFFIX,
|
|
18
|
+
BaseIndex,
|
|
19
|
+
DistanceStrategy,
|
|
20
|
+
ExactNearestNeighbor,
|
|
21
|
+
HNSWIndex,
|
|
22
|
+
HNSWQueryOptions,
|
|
23
|
+
IVFFlatIndex,
|
|
24
|
+
IVFFlatQueryOptions,
|
|
25
|
+
QueryOptions,
|
|
26
|
+
StrategyMixin,
|
|
27
|
+
)
|