sunholo 0.80.6__py3-none-any.whl → 0.81.0__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.
- sunholo/components/retriever.py +1 -0
- sunholo/database/__init__.py +1 -0
- sunholo/database/alloydb.py +7 -2
- sunholo/database/alloydb_client.py +99 -5
- sunholo/discovery_engine/get_ai_search_chunks.py +1 -1
- sunholo/utils/config_class.py +2 -2
- sunholo/utils/gcp_project.py +1 -0
- {sunholo-0.80.6.dist-info → sunholo-0.81.0.dist-info}/METADATA +2 -2
- {sunholo-0.80.6.dist-info → sunholo-0.81.0.dist-info}/RECORD +13 -13
- {sunholo-0.80.6.dist-info → sunholo-0.81.0.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.80.6.dist-info → sunholo-0.81.0.dist-info}/WHEEL +0 -0
- {sunholo-0.80.6.dist-info → sunholo-0.81.0.dist-info}/entry_points.txt +0 -0
- {sunholo-0.80.6.dist-info → sunholo-0.81.0.dist-info}/top_level.txt +0 -0
sunholo/components/retriever.py
CHANGED
sunholo/database/__init__.py
CHANGED
sunholo/database/alloydb.py
CHANGED
|
@@ -14,6 +14,8 @@ from .alloydb_client import AlloyDBClient
|
|
|
14
14
|
from ..custom_logging import log
|
|
15
15
|
from ..utils.config import load_config_key
|
|
16
16
|
|
|
17
|
+
from typing import List
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
def create_alloydb_engine(vector_name):
|
|
19
21
|
|
|
@@ -231,8 +233,11 @@ async def load_alloydb_sql_async(sql, vector_name):
|
|
|
231
233
|
|
|
232
234
|
return documents
|
|
233
235
|
|
|
234
|
-
def and_or_ilike(sources, search_type="OR", operator="ILIKE"):
|
|
235
|
-
|
|
236
|
+
def and_or_ilike(sources:List[str], search_type:str="OR", operator:str="ILIKE"):
|
|
237
|
+
if not isinstance(sources, list) or not all(isinstance(source, str) for source in sources):
|
|
238
|
+
raise TypeError("The `sources` argument must be a list of strings.")
|
|
239
|
+
|
|
240
|
+
unique_sources = set(sources)
|
|
236
241
|
# Choose the delimiter based on the search_type argument
|
|
237
242
|
delimiter = ' AND ' if search_type.upper() == "AND" else ' OR '
|
|
238
243
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
try:
|
|
2
3
|
import pg8000
|
|
3
4
|
import sqlalchemy
|
|
@@ -9,6 +10,7 @@ except ImportError:
|
|
|
9
10
|
|
|
10
11
|
from .database import get_vector_size
|
|
11
12
|
from ..custom_logging import log
|
|
13
|
+
from ..utils import ConfigManager
|
|
12
14
|
|
|
13
15
|
class AlloyDBClient:
|
|
14
16
|
"""
|
|
@@ -35,11 +37,12 @@ class AlloyDBClient:
|
|
|
35
37
|
"""
|
|
36
38
|
|
|
37
39
|
def __init__(self,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
config:ConfigManager,
|
|
41
|
+
project_id: str=None,
|
|
42
|
+
region: str=None,
|
|
43
|
+
cluster_name:str=None,
|
|
44
|
+
instance_name:str=None,
|
|
45
|
+
user:str=None,
|
|
43
46
|
password=None,
|
|
44
47
|
db="postgres"):
|
|
45
48
|
"""Initializes the AlloyDB client.
|
|
@@ -51,6 +54,23 @@ class AlloyDBClient:
|
|
|
51
54
|
- password (str): The database user's password.
|
|
52
55
|
- db_name (str): The name of the database.
|
|
53
56
|
"""
|
|
57
|
+
if config is None:
|
|
58
|
+
if project_id is None or region is None or cluster_name is None or instance_name is None:
|
|
59
|
+
raise ValueError("Must specify config or project_id, region, cluster_name, instance_name")
|
|
60
|
+
if config:
|
|
61
|
+
alloydb_config = config.vacConfig("alloydb_config")
|
|
62
|
+
if not alloydb_config:
|
|
63
|
+
raise ValueError("Must specify vac.alloydb_config")
|
|
64
|
+
project_id = alloydb_config["project_id"]
|
|
65
|
+
region = alloydb_config["region"]
|
|
66
|
+
cluster_name = alloydb_config["cluster"]
|
|
67
|
+
instance_name = alloydb_config["instance"]
|
|
68
|
+
|
|
69
|
+
ALLOYDB_DB = os.environ.get("ALLOYDB_DB")
|
|
70
|
+
if ALLOYDB_DB is None and alloydb_config.get("database") is None:
|
|
71
|
+
log.warning("Could not locate ALLOYDB_DB environment variable or 'alloydb_config.database'")
|
|
72
|
+
|
|
73
|
+
self.database = alloydb_config.get("database") or ALLOYDB_DB,
|
|
54
74
|
self.connector = Connector()
|
|
55
75
|
self.inst_uri = self._build_instance_uri(project_id, region, cluster_name, instance_name)
|
|
56
76
|
self.engine = self._create_engine(self.inst_uri, user, password, db)
|
|
@@ -100,6 +120,80 @@ class AlloyDBClient:
|
|
|
100
120
|
conn.close()
|
|
101
121
|
|
|
102
122
|
return result
|
|
123
|
+
|
|
124
|
+
async def execute_sql_async(self, sql_statement):
|
|
125
|
+
"""Executes a given SQL statement asynchronously with error handling."""
|
|
126
|
+
sql_ = sqlalchemy.text(sql_statement)
|
|
127
|
+
result = None
|
|
128
|
+
async with self.engine.connect() as conn:
|
|
129
|
+
try:
|
|
130
|
+
log.info(f"Executing SQL statement asynchronously: {sql_}")
|
|
131
|
+
result = await conn.execute(sql_)
|
|
132
|
+
except DatabaseError as e:
|
|
133
|
+
if "already exists" in str(e):
|
|
134
|
+
log.warning(f"Error ignored: {str(e)}. Assuming object already exists.")
|
|
135
|
+
else:
|
|
136
|
+
raise
|
|
137
|
+
finally:
|
|
138
|
+
await conn.close()
|
|
139
|
+
|
|
140
|
+
return result
|
|
141
|
+
|
|
142
|
+
async def get_sources_from_docstore_async(self, sources, vector_name, search_type="OR", just_source_name=False):
|
|
143
|
+
"""Fetches sources from the docstore asynchronously."""
|
|
144
|
+
if just_source_name:
|
|
145
|
+
query = self._list_sources_from_docstore(sources, vector_name=vector_name, search_type=search_type)
|
|
146
|
+
else:
|
|
147
|
+
query = self._get_sources_from_docstore(sources, vector_name=vector_name, search_type=search_type)
|
|
148
|
+
|
|
149
|
+
if not query:
|
|
150
|
+
return []
|
|
151
|
+
|
|
152
|
+
documents = await self.execute_sql_async(query)
|
|
153
|
+
return documents
|
|
154
|
+
|
|
155
|
+
def _get_sources_from_docstore(self, sources, vector_name, search_type="OR"):
|
|
156
|
+
"""Helper function to build the SQL query for fetching sources."""
|
|
157
|
+
if not sources:
|
|
158
|
+
log.warning("No sources found for alloydb fetch")
|
|
159
|
+
return ""
|
|
160
|
+
|
|
161
|
+
table_name = f"{vector_name}_docstore"
|
|
162
|
+
|
|
163
|
+
conditions = self._and_or_ilike(sources, search_type=search_type)
|
|
164
|
+
|
|
165
|
+
query = f"""
|
|
166
|
+
SELECT *
|
|
167
|
+
FROM {table_name}
|
|
168
|
+
WHERE {conditions}
|
|
169
|
+
ORDER BY langchain_metadata->>'objectId' ASC
|
|
170
|
+
LIMIT 500;
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
return query
|
|
174
|
+
|
|
175
|
+
def _list_sources_from_docstore(self, sources, vector_name, search_type="OR"):
|
|
176
|
+
"""Helper function to build the SQL query for listing sources."""
|
|
177
|
+
table_name = f"{vector_name}_docstore"
|
|
178
|
+
|
|
179
|
+
if sources:
|
|
180
|
+
conditions = self._and_or_ilike(sources, search_type=search_type)
|
|
181
|
+
query = f"""
|
|
182
|
+
SELECT DISTINCT langchain_metadata->>'objectId' AS objectId
|
|
183
|
+
FROM {table_name}
|
|
184
|
+
WHERE {conditions}
|
|
185
|
+
ORDER BY langchain_metadata->>'objectId' ASC
|
|
186
|
+
LIMIT 500;
|
|
187
|
+
"""
|
|
188
|
+
else:
|
|
189
|
+
query = f"""
|
|
190
|
+
SELECT DISTINCT langchain_metadata->>'objectId' AS objectId
|
|
191
|
+
FROM {table_name}
|
|
192
|
+
ORDER BY langchain_metadata->>'objectId' ASC
|
|
193
|
+
LIMIT 500;
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
return query
|
|
103
197
|
|
|
104
198
|
@staticmethod
|
|
105
199
|
def _and_or_ilike(sources, search_type="OR", operator="ILIKE"):
|
|
@@ -43,7 +43,7 @@ def get_all_chunks(question:str, config:ConfigManager):
|
|
|
43
43
|
return None
|
|
44
44
|
|
|
45
45
|
def get_chunks(question, vector_name, num_chunks):
|
|
46
|
-
de = DiscoveryEngineClient(vector_name, project_id=get_gcp_project())
|
|
46
|
+
de = DiscoveryEngineClient(vector_name, project_id=get_gcp_project(include_config=True))
|
|
47
47
|
try:
|
|
48
48
|
return de.get_chunks(question, num_previous_chunks=num_chunks, num_next_chunks=num_chunks)
|
|
49
49
|
except Exception as err:
|
sunholo/utils/config_class.py
CHANGED
|
@@ -37,9 +37,10 @@ class ConfigManager:
|
|
|
37
37
|
self.config_folder = os.getenv("VAC_CONFIG_FOLDER", os.getcwd())
|
|
38
38
|
self.local_config_folder = local_config_folder
|
|
39
39
|
self.configs_by_kind = self.load_all_configs()
|
|
40
|
+
self.validate = validate
|
|
40
41
|
|
|
41
42
|
test_agent = self.vacConfig("agent")
|
|
42
|
-
if not test_agent and self.vector_name != "global" and validate:
|
|
43
|
+
if not test_agent and self.vector_name != "global" and self.validate:
|
|
43
44
|
print(f"WARNING: No vacConfig.agent found for {self.vector_name} - are you in right folder? {local_config_folder=} {self.config_folder=}")
|
|
44
45
|
|
|
45
46
|
def load_all_configs(self):
|
|
@@ -125,7 +126,6 @@ class ConfigManager:
|
|
|
125
126
|
else:
|
|
126
127
|
config = yaml.safe_load(file)
|
|
127
128
|
self.config_cache[filename] = (config, datetime.now())
|
|
128
|
-
log.debug(f"Loaded and cached {config_file}")
|
|
129
129
|
if is_local:
|
|
130
130
|
log.warning(f"Local configuration override for {filename} via {self.local_config_folder}")
|
|
131
131
|
return config
|
sunholo/utils/gcp_project.py
CHANGED
|
@@ -24,6 +24,7 @@ def get_gcp_project(include_config=False):
|
|
|
24
24
|
gcp_config = load_config_key("gcp_config", "global", "vacConfig")
|
|
25
25
|
if gcp_config:
|
|
26
26
|
if gcp_config.get('project_id'):
|
|
27
|
+
logging.info("Using project_id from vacConfig.gcp_config.project_id")
|
|
27
28
|
return gcp_config.get('project_id')
|
|
28
29
|
|
|
29
30
|
project_id = get_env_project_id()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.81.0
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.81.0.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -55,11 +55,11 @@ sunholo/cli/swagger.py,sha256=absYKAU-7Yd2eiVNUY-g_WLl2zJfeRUNdWQ0oH8M_HM,1564
|
|
|
55
55
|
sunholo/cli/vertex.py,sha256=8130YCarxHL1UC3aqblNmUwGZTXbkdL4Y_FOnZJsWiI,2056
|
|
56
56
|
sunholo/components/__init__.py,sha256=IDoylb74zFKo6NIS3RQqUl0PDFBGVxM1dfUmO7OJ44U,176
|
|
57
57
|
sunholo/components/llm.py,sha256=5wRVf7lIb7q1vRADNcdQp26L9l4vGHFIvjtUDurZN_s,11488
|
|
58
|
-
sunholo/components/retriever.py,sha256=
|
|
58
|
+
sunholo/components/retriever.py,sha256=bKIVT7_18Ut3OJd0E0jyiISPnD9qkHWVjcQPT4i1_G8,7720
|
|
59
59
|
sunholo/components/vectorstore.py,sha256=xKk7micTRwZckaI7U6PxvFz_ZSjCH48xPTDYiDcv2tc,5913
|
|
60
|
-
sunholo/database/__init__.py,sha256=
|
|
61
|
-
sunholo/database/alloydb.py,sha256=
|
|
62
|
-
sunholo/database/alloydb_client.py,sha256=
|
|
60
|
+
sunholo/database/__init__.py,sha256=bpB5Nk21kwqYj-qdVnvNgXjLsbflnH4g-San7OHMqR4,283
|
|
61
|
+
sunholo/database/alloydb.py,sha256=YH8wNPS8gN-TDZEXQcVHxwd1NScHRfAxma3gK4R6KCk,11740
|
|
62
|
+
sunholo/database/alloydb_client.py,sha256=vZu7m3n1TrGFqQ_F4kGgDEC-v_tnlJfByDGuI_4rrfw,11051
|
|
63
63
|
sunholo/database/database.py,sha256=VqhZdkXUNdvWn8sUcUV3YNby1JDVf7IykPVXWBtxo9U,7361
|
|
64
64
|
sunholo/database/lancedb.py,sha256=DyfZntiFKBlVPaFooNN1Z6Pl-LAs4nxWKKuq8GBqN58,715
|
|
65
65
|
sunholo/database/static_dbs.py,sha256=8cvcMwUK6c32AS2e_WguKXWMkFf5iN3g9WHzsh0C07Q,442
|
|
@@ -74,7 +74,7 @@ sunholo/discovery_engine/__init__.py,sha256=P00bB8aVVWefOZbCQvzHsVMuP_sd-_d_4o5x
|
|
|
74
74
|
sunholo/discovery_engine/chunker_handler.py,sha256=Fv4BLOBi_7ap3AiAy4TlTN48CLZSMurJ3TkvC75Euro,5123
|
|
75
75
|
sunholo/discovery_engine/create_new.py,sha256=NzhSh6nG6nQ5J9gZh8IDph4JiEVT_DC5GGvP0GuwTWs,943
|
|
76
76
|
sunholo/discovery_engine/discovery_engine_client.py,sha256=oORB2SVVqrYrz7E3srPrknyuR6Dl3SJJwaVrbVXJER4,17726
|
|
77
|
-
sunholo/discovery_engine/get_ai_search_chunks.py,sha256=
|
|
77
|
+
sunholo/discovery_engine/get_ai_search_chunks.py,sha256=VPzdYoBP_E6Bko0KpX656QiIfJdwmje4sBnPtZs4JQ4,1963
|
|
78
78
|
sunholo/embedder/__init__.py,sha256=sI4N_CqgEVcrMDxXgxKp1FsfsB4FpjoXgPGkl4N_u4I,44
|
|
79
79
|
sunholo/embedder/embed_chunk.py,sha256=MCbTePWjUbIRVDFFhHJ94BvOZvIom62-mTr0PmfQyt0,6951
|
|
80
80
|
sunholo/gcs/__init__.py,sha256=SZvbsMFDko40sIRHTHppA37IijvJTae54vrhooEF5-4,90
|
|
@@ -118,10 +118,10 @@ sunholo/utils/__init__.py,sha256=Hv02T5L2zYWvCso5hzzwm8FQogwBq0OgtUbN_7Quzqc,89
|
|
|
118
118
|
sunholo/utils/api_key.py,sha256=Ct4bIAQZxzPEw14hP586LpVxBAVi_W9Serpy0BK-7KI,244
|
|
119
119
|
sunholo/utils/big_context.py,sha256=gJIP7_ZL-YSLhOMq8jmFTMqH1wq8eB1NK7oKPeZAq2s,5578
|
|
120
120
|
sunholo/utils/config.py,sha256=aG29MXcL5qzQMtCMqcdy-2ysDCYf9Zn_ZLk5NNOQNSE,8982
|
|
121
|
-
sunholo/utils/config_class.py,sha256=
|
|
121
|
+
sunholo/utils/config_class.py,sha256=3Hzeue_hvN1HR13c9VHCYUVspbvkLBpuIGvlGtxv_H8,9013
|
|
122
122
|
sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
|
|
123
123
|
sunholo/utils/gcp.py,sha256=uueODEpA-P6O15-t0hmcGC9dONLO_hLfzSsSoQnkUss,4854
|
|
124
|
-
sunholo/utils/gcp_project.py,sha256=
|
|
124
|
+
sunholo/utils/gcp_project.py,sha256=Fa0IhCX12bZ1ctF_PKN8PNYd7hihEUfb90kilBfUDjg,1411
|
|
125
125
|
sunholo/utils/parsers.py,sha256=akLSZLdvHf5T9OKVj5C3bo4g3Y8puATd8rxnbB4tWDs,5419
|
|
126
126
|
sunholo/utils/timedelta.py,sha256=BbLabEx7_rbErj_YbNM0MBcaFN76DC4PTe4zD2ucezg,493
|
|
127
127
|
sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
|
|
@@ -134,9 +134,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
|
|
|
134
134
|
sunholo/vertex/memory_tools.py,sha256=pgSahVDh7GPEulu3nl-w0jb5lTClb4TCnVxPnMokNZY,7533
|
|
135
135
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
|
136
136
|
sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
|
|
137
|
-
sunholo-0.
|
|
138
|
-
sunholo-0.
|
|
139
|
-
sunholo-0.
|
|
140
|
-
sunholo-0.
|
|
141
|
-
sunholo-0.
|
|
142
|
-
sunholo-0.
|
|
137
|
+
sunholo-0.81.0.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
138
|
+
sunholo-0.81.0.dist-info/METADATA,sha256=jscapxO2wqyFdzlfqahL6VpisfqyNsETdfmHZwJR7I0,7348
|
|
139
|
+
sunholo-0.81.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
140
|
+
sunholo-0.81.0.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
141
|
+
sunholo-0.81.0.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
142
|
+
sunholo-0.81.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|