sunholo 0.96.2__py3-none-any.whl → 0.96.5__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/database/alloydb_client.py +1 -1
- sunholo/invoke/direct_vac_func.py +158 -2
- {sunholo-0.96.2.dist-info → sunholo-0.96.5.dist-info}/METADATA +2 -2
- {sunholo-0.96.2.dist-info → sunholo-0.96.5.dist-info}/RECORD +8 -8
- {sunholo-0.96.2.dist-info → sunholo-0.96.5.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.96.2.dist-info → sunholo-0.96.5.dist-info}/WHEEL +0 -0
- {sunholo-0.96.2.dist-info → sunholo-0.96.5.dist-info}/entry_points.txt +0 -0
- {sunholo-0.96.2.dist-info → sunholo-0.96.5.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from ..custom_logging import log
|
|
2
|
-
from ..agents import send_to_qa
|
|
2
|
+
from ..agents import send_to_qa, send_to_qa_async
|
|
3
3
|
from ..qna.parsers import parse_output
|
|
4
4
|
from ..streaming import generate_proxy_stream
|
|
5
5
|
from ..utils import ConfigManager
|
|
6
6
|
from ..utils.api_key import has_multivac_api_key
|
|
7
|
+
import asyncio
|
|
8
|
+
from threading import Thread
|
|
7
9
|
|
|
8
10
|
def direct_vac(vac_input: dict, vac_name: str, chat_history=[]):
|
|
9
11
|
"""
|
|
@@ -66,6 +68,76 @@ def direct_vac(vac_input: dict, vac_name: str, chat_history=[]):
|
|
|
66
68
|
|
|
67
69
|
return answer
|
|
68
70
|
|
|
71
|
+
async def async_direct_vac(vac_input: dict, vac_name: str, chat_history=[]):
|
|
72
|
+
"""
|
|
73
|
+
Asynchronous version of direct_vac using send_to_qa_async.
|
|
74
|
+
Allows VACs to call other VAC Q&A endpoints without blocking the event loop.
|
|
75
|
+
"""
|
|
76
|
+
log.info(f"Invoking VAC Q&A endpoints for {vac_name}")
|
|
77
|
+
|
|
78
|
+
if 'user_input' not in vac_input:
|
|
79
|
+
raise ValueError(f'vac_input must contain at least "user_input" key - got {vac_input}')
|
|
80
|
+
|
|
81
|
+
global_config = ConfigManager('global')
|
|
82
|
+
config = ConfigManager(vac_name)
|
|
83
|
+
|
|
84
|
+
agent_name = config.vacConfig('agent')
|
|
85
|
+
agent_url = config.vacConfig("agent_url")
|
|
86
|
+
|
|
87
|
+
if agent_url:
|
|
88
|
+
log.info(f"Found agent_url within vacConfig: {agent_url}")
|
|
89
|
+
|
|
90
|
+
# Via public cloud endpoints - assumes no gcloud auth
|
|
91
|
+
override_endpoint = None
|
|
92
|
+
if has_multivac_api_key():
|
|
93
|
+
print("Found MULTIVAC_API_KEY")
|
|
94
|
+
gcp_config = global_config.vacConfig("gcp_config")
|
|
95
|
+
endpoints_base_url = gcp_config.get("endpoints_base_url")
|
|
96
|
+
if not endpoints_base_url:
|
|
97
|
+
raise ValueError("MULTIVAC_API_KEY env var is set but no config.gcp_config.endpoints_base_url can be found")
|
|
98
|
+
|
|
99
|
+
override_endpoint = f"{endpoints_base_url}/v1/{agent_name}"
|
|
100
|
+
|
|
101
|
+
override_endpoint = agent_url or override_endpoint
|
|
102
|
+
|
|
103
|
+
print(f"Using override_endpoint={override_endpoint}")
|
|
104
|
+
|
|
105
|
+
# Prepare the kwargs for send_to_qa_async by copying vac_input and adding more values
|
|
106
|
+
qa_kwargs = vac_input.copy()
|
|
107
|
+
|
|
108
|
+
# Add additional arguments
|
|
109
|
+
qa_kwargs.update({
|
|
110
|
+
'vector_name': vac_name,
|
|
111
|
+
'chat_history': chat_history,
|
|
112
|
+
'image_url': vac_input.get('image_url') or vac_input.get('image_uri'),
|
|
113
|
+
'override_endpoint': override_endpoint,
|
|
114
|
+
'message_source': "sunholo.invoke_vac_qa.invoke",
|
|
115
|
+
'stream': False,
|
|
116
|
+
'configurable': {
|
|
117
|
+
"vector_name": vac_name,
|
|
118
|
+
},
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
log.info(f'Batch invoke_vac_qa {vac_name} with qa_kwargs={qa_kwargs}')
|
|
122
|
+
|
|
123
|
+
# Call send_to_qa_async directly
|
|
124
|
+
vac_response_generator = send_to_qa_async(**qa_kwargs)
|
|
125
|
+
|
|
126
|
+
# Since send_to_qa_async returns an async generator, we can get the response
|
|
127
|
+
vac_response = None
|
|
128
|
+
async for response in vac_response_generator:
|
|
129
|
+
vac_response = response # Since stream=False, we expect only one response
|
|
130
|
+
break
|
|
131
|
+
|
|
132
|
+
# Call parse_output synchronously (since it's non-blocking)
|
|
133
|
+
answer = parse_output(vac_response)
|
|
134
|
+
|
|
135
|
+
chat_history.append({"name": "Human", "content": vac_input})
|
|
136
|
+
chat_history.append({"name": "AI", "content": answer})
|
|
137
|
+
answer["chat_history"] = chat_history
|
|
138
|
+
|
|
139
|
+
return answer
|
|
140
|
+
|
|
69
141
|
def direct_vac_stream(vac_input: dict, vac_name: str, chat_history=[]):
|
|
70
142
|
|
|
71
143
|
if 'user_input' not in vac_input:
|
|
@@ -120,4 +192,88 @@ def direct_vac_stream(vac_input: dict, vac_name: str, chat_history=[]):
|
|
|
120
192
|
chat_history.append({"name": "Human", "content": vac_input})
|
|
121
193
|
chat_history.append({"name": "AI", "content": answer})
|
|
122
194
|
|
|
123
|
-
return chat_history
|
|
195
|
+
return chat_history
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async def async_direct_vac_stream(vac_input: dict, vac_name: str, chat_history=[]):
|
|
200
|
+
"""
|
|
201
|
+
Asynchronous version of direct_vac_stream.
|
|
202
|
+
Streams responses from VAC Q&A endpoints without blocking the event loop.
|
|
203
|
+
"""
|
|
204
|
+
if 'user_input' not in vac_input:
|
|
205
|
+
raise ValueError(f'vac_input must contain at least "user_input" key - got {vac_input}')
|
|
206
|
+
|
|
207
|
+
user_id = vac_input.get('user_id')
|
|
208
|
+
session_id = vac_input.get('session_id')
|
|
209
|
+
image_uri = vac_input.get('image_url') or vac_input.get('image_uri')
|
|
210
|
+
|
|
211
|
+
log.info(f"Streaming invoke_vac_qa with vac_input={vac_input}")
|
|
212
|
+
|
|
213
|
+
def sync_stream_response():
|
|
214
|
+
generate = generate_proxy_stream(
|
|
215
|
+
send_to_qa,
|
|
216
|
+
vac_input["user_input"],
|
|
217
|
+
vector_name=vac_name,
|
|
218
|
+
chat_history=chat_history,
|
|
219
|
+
generate_f_output=lambda x: x, # Replace with actual processing function
|
|
220
|
+
stream_wait_time=0.5,
|
|
221
|
+
stream_timeout=120,
|
|
222
|
+
message_author=user_id,
|
|
223
|
+
# TODO: populate these
|
|
224
|
+
image_url=image_uri,
|
|
225
|
+
source_filters=None,
|
|
226
|
+
search_kwargs=None,
|
|
227
|
+
private_docs=None,
|
|
228
|
+
whole_document=False,
|
|
229
|
+
source_filters_and_or=False,
|
|
230
|
+
# system kwargs
|
|
231
|
+
configurable={
|
|
232
|
+
"vector_name": vac_name,
|
|
233
|
+
},
|
|
234
|
+
user_id=user_id,
|
|
235
|
+
session_id=session_id,
|
|
236
|
+
message_source="sunholo.invoke_vac_qa.stream"
|
|
237
|
+
)
|
|
238
|
+
for part in generate():
|
|
239
|
+
yield part
|
|
240
|
+
|
|
241
|
+
async def async_stream_response():
|
|
242
|
+
loop = asyncio.get_event_loop()
|
|
243
|
+
queue = asyncio.Queue()
|
|
244
|
+
|
|
245
|
+
def run_sync_gen():
|
|
246
|
+
try:
|
|
247
|
+
for item in sync_stream_response():
|
|
248
|
+
loop.call_soon_threadsafe(queue.put_nowait, item)
|
|
249
|
+
finally:
|
|
250
|
+
loop.call_soon_threadsafe(queue.put_nowait, None) # Sentinel
|
|
251
|
+
|
|
252
|
+
thread = Thread(target=run_sync_gen)
|
|
253
|
+
thread.start()
|
|
254
|
+
|
|
255
|
+
while True:
|
|
256
|
+
item = await queue.get()
|
|
257
|
+
if item is None:
|
|
258
|
+
break
|
|
259
|
+
yield item
|
|
260
|
+
|
|
261
|
+
thread.join()
|
|
262
|
+
|
|
263
|
+
answer = ""
|
|
264
|
+
|
|
265
|
+
async for token in async_stream_response():
|
|
266
|
+
if isinstance(token, bytes):
|
|
267
|
+
token = token.decode('utf-8')
|
|
268
|
+
yield token
|
|
269
|
+
if isinstance(token, dict):
|
|
270
|
+
# Process dict token if necessary
|
|
271
|
+
pass
|
|
272
|
+
elif isinstance(token, str):
|
|
273
|
+
answer += token
|
|
274
|
+
|
|
275
|
+
if answer:
|
|
276
|
+
chat_history.append({"name": "Human", "content": vac_input})
|
|
277
|
+
chat_history.append({"name": "AI", "content": answer})
|
|
278
|
+
|
|
279
|
+
yield chat_history
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.96.
|
|
3
|
+
Version: 0.96.5
|
|
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.96.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.96.5.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -59,7 +59,7 @@ sunholo/components/retriever.py,sha256=bKIVT7_18Ut3OJd0E0jyiISPnD9qkHWVjcQPT4i1_
|
|
|
59
59
|
sunholo/components/vectorstore.py,sha256=xKk7micTRwZckaI7U6PxvFz_ZSjCH48xPTDYiDcv2tc,5913
|
|
60
60
|
sunholo/database/__init__.py,sha256=bpB5Nk21kwqYj-qdVnvNgXjLsbflnH4g-San7OHMqR4,283
|
|
61
61
|
sunholo/database/alloydb.py,sha256=YH8wNPS8gN-TDZEXQcVHxwd1NScHRfAxma3gK4R6KCk,11740
|
|
62
|
-
sunholo/database/alloydb_client.py,sha256=
|
|
62
|
+
sunholo/database/alloydb_client.py,sha256=bvQzvnLEYGrmOgTBx7QjgIn_-4N4aN8JNRUNOLNSRc8,18310
|
|
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
|
|
@@ -90,7 +90,7 @@ sunholo/genai/process_funcs_cls.py,sha256=M6vE_-Mi8v1Od8iny3h9-pRA5KbO5n4hiJKr1y
|
|
|
90
90
|
sunholo/genai/safety.py,sha256=mkFDO_BeEgiKjQd9o2I4UxB6XI7a9U-oOFjZ8LGRUC4,1238
|
|
91
91
|
sunholo/invoke/__init__.py,sha256=VOpsfhNf98az3at7bMaY1Fiw4UIZAS6zMmSqWd6_ksI,141
|
|
92
92
|
sunholo/invoke/async_class.py,sha256=uvCP8ekUCfTRWk7xwofTzRqFykMAwrRZ4Ce_YUR6PVs,2820
|
|
93
|
-
sunholo/invoke/direct_vac_func.py,sha256=
|
|
93
|
+
sunholo/invoke/direct_vac_func.py,sha256=GXSCMkC6vOWGUtQjxy-ZpTrMvJa3CgcW-y9mDpJwWC8,9533
|
|
94
94
|
sunholo/invoke/invoke_vac_utils.py,sha256=sJc1edHTHMzMGXjji1N67c3iUaP7BmAL5nj82Qof63M,2053
|
|
95
95
|
sunholo/langfuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
96
96
|
sunholo/langfuse/callback.py,sha256=jl0SZsFS53uMW9DGeM9SOL_EsRZsba0wwFGLqKzu9_U,1684
|
|
@@ -144,9 +144,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
|
|
|
144
144
|
sunholo/vertex/memory_tools.py,sha256=ZirFbS7EKxQaoRmOrb4BnG6jPJ83wt43N8M4zTVbutU,7717
|
|
145
145
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
|
146
146
|
sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
|
|
147
|
-
sunholo-0.96.
|
|
148
|
-
sunholo-0.96.
|
|
149
|
-
sunholo-0.96.
|
|
150
|
-
sunholo-0.96.
|
|
151
|
-
sunholo-0.96.
|
|
152
|
-
sunholo-0.96.
|
|
147
|
+
sunholo-0.96.5.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
148
|
+
sunholo-0.96.5.dist-info/METADATA,sha256=xSaGe0hLQU4vUWrnPs5v67kzLo3WMFwptSMOBXRSHvA,7889
|
|
149
|
+
sunholo-0.96.5.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
150
|
+
sunholo-0.96.5.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
151
|
+
sunholo-0.96.5.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
152
|
+
sunholo-0.96.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|