sunholo 0.61.0__tar.gz → 0.61.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.
- {sunholo-0.61.0 → sunholo-0.61.5}/PKG-INFO +2 -2
- {sunholo-0.61.0 → sunholo-0.61.5}/setup.py +1 -1
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/chat_history.py +1 -1
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/chat_vac.py +59 -15
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/components/vectorstore.py +1 -1
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/config.py +6 -17
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo.egg-info/PKG-INFO +2 -2
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo.egg-info/SOURCES.txt +0 -1
- sunholo-0.61.5/tests/test_config.py +11 -0
- sunholo-0.61.0/test/test_dispatch_to_qa.py +0 -73
- sunholo-0.61.0/tests/test_config.py +0 -40
- {sunholo-0.61.0 → sunholo-0.61.5}/LICENSE.txt +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/MANIFEST.in +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/README.md +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/setup.cfg +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/route.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/archive/archive.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/auth/run.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/bots/discord.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/data_to_embed_pubsub.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/images.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/cli.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/configs.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/components/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/components/llm.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/components/prompt.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/components/retriever.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/database.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/database/uuid.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/llamaindex/generate.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/logging.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/qna/retry.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/parsers.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo/vertex/init_vertex.py +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.61.0 → sunholo-0.61.5}/tests/test_chat_history.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.61.
|
|
3
|
+
Version: 0.61.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.61.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.61.5.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -74,7 +74,7 @@ def embeds_to_json(message: dict):
|
|
|
74
74
|
# Output: '[{"type": "image", "url": "https://example.com/image.png"}]'
|
|
75
75
|
```
|
|
76
76
|
"""
|
|
77
|
-
if len(message['embeds'] > 0
|
|
77
|
+
if 'embeds' in message and len(message['embeds']) > 0:
|
|
78
78
|
return json.dumps(message.get("embeds"))
|
|
79
79
|
else:
|
|
80
80
|
return ""
|
|
@@ -9,6 +9,7 @@ import uuid
|
|
|
9
9
|
import sys
|
|
10
10
|
import subprocess
|
|
11
11
|
import json
|
|
12
|
+
import requests
|
|
12
13
|
|
|
13
14
|
from rich import print
|
|
14
15
|
from .sun_rich import console
|
|
@@ -143,27 +144,46 @@ def headless_mode(service_url, service_name, user_input, chat_history=None):
|
|
|
143
144
|
|
|
144
145
|
return chat_history
|
|
145
146
|
|
|
147
|
+
def resolve_service_url(args):
|
|
148
|
+
|
|
149
|
+
if args.url_override:
|
|
150
|
+
|
|
151
|
+
return args.url_override
|
|
152
|
+
|
|
153
|
+
if not args.no_proxy:
|
|
154
|
+
try:
|
|
155
|
+
service_url = get_service_url(args.vac_name, args.project, args.region)
|
|
156
|
+
except ValueError as e:
|
|
157
|
+
console.print(f"[bold red]ERROR: Could not start {args.vac_name} proxy URL: {str(e)}[/bold red]")
|
|
158
|
+
sys.exit(1)
|
|
159
|
+
else:
|
|
160
|
+
console.print(f"Not using a proxy, connecting directly to {service_url}")
|
|
161
|
+
|
|
162
|
+
agent_url = load_config_key("agent_url", args.vac_name, "vacConfig")
|
|
163
|
+
if agent_url:
|
|
164
|
+
console.print("Found agent_url within vacConfig: {agent_url}")
|
|
165
|
+
|
|
166
|
+
service_url = agent_url or get_cloud_run_service_url(args.project, args.region, args.vac_name)
|
|
167
|
+
|
|
168
|
+
return service_url
|
|
146
169
|
|
|
147
170
|
def vac_command(args):
|
|
171
|
+
|
|
172
|
+
service_url = resolve_service_url(args)
|
|
173
|
+
|
|
148
174
|
if args.action == 'list':
|
|
175
|
+
|
|
149
176
|
list_cloud_run_services(args.project, args.region)
|
|
177
|
+
|
|
150
178
|
return
|
|
179
|
+
|
|
151
180
|
elif args.action == 'get-url':
|
|
152
|
-
service_url = get_cloud_run_service_url(args.project, args.region, args.vac_name)
|
|
153
|
-
if service_url:
|
|
154
|
-
console.print(service_url)
|
|
155
|
-
return
|
|
156
|
-
elif args.action == 'chat':
|
|
157
181
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
sys.exit(1)
|
|
164
|
-
else:
|
|
165
|
-
service_url = get_cloud_run_service_url(args.project, args.region, args.vac_name)
|
|
166
|
-
console.print(f"Not using a proxy, connecting directly to {service_url}")
|
|
182
|
+
console.print(service_url)
|
|
183
|
+
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
elif args.action == 'chat':
|
|
167
187
|
|
|
168
188
|
agent_name = load_config_key("agent", args.vac_name, kind="vacConfig")
|
|
169
189
|
|
|
@@ -188,6 +208,24 @@ def vac_command(args):
|
|
|
188
208
|
|
|
189
209
|
stop_proxy(agent_name, stop_local=False)
|
|
190
210
|
|
|
211
|
+
elif args.action == 'invoke':
|
|
212
|
+
try:
|
|
213
|
+
json_data = json.loads(args.data)
|
|
214
|
+
except json.JSONDecodeError as err:
|
|
215
|
+
console.print(f"[bold red]ERROR: invalid JSON: {str(err)} [/bold red]")
|
|
216
|
+
sys.exit(1)
|
|
217
|
+
|
|
218
|
+
invoke_vac(service_url, json_data)
|
|
219
|
+
|
|
220
|
+
def invoke_vac(service_url, data):
|
|
221
|
+
try:
|
|
222
|
+
headers = {"Content-Type": "application/json"}
|
|
223
|
+
response = requests.post(service_url, headers=headers, data=json.dumps(data))
|
|
224
|
+
response.raise_for_status()
|
|
225
|
+
print(response.json())
|
|
226
|
+
except requests.exceptions.RequestException as e:
|
|
227
|
+
console.print(f"[bold red]ERROR: Failed to invoke VAC: {e}[/bold red]")
|
|
228
|
+
|
|
191
229
|
|
|
192
230
|
def list_cloud_run_services(project, region):
|
|
193
231
|
"""
|
|
@@ -281,6 +319,8 @@ def setup_vac_subparser(subparsers):
|
|
|
281
319
|
subparsers: The subparsers object from argparse.ArgumentParser().
|
|
282
320
|
"""
|
|
283
321
|
vac_parser = subparsers.add_parser('vac', help='Interact with deployed VAC services.')
|
|
322
|
+
vac_parser.add_argument('--url_override', help='Override the VAC service URL.')
|
|
323
|
+
vac_parser.add_argument('--no-proxy', action='store_true', help='Do not use the proxy and connect directly to the VAC service.')
|
|
284
324
|
vac_subparsers = vac_parser.add_subparsers(dest='action', help='VAC subcommands')
|
|
285
325
|
|
|
286
326
|
# Subcommand for listing VAC services
|
|
@@ -296,6 +336,10 @@ def setup_vac_subparser(subparsers):
|
|
|
296
336
|
chat_parser.add_argument('user_input', help='User input for the VAC service when in headless mode.', nargs='?', default=None)
|
|
297
337
|
chat_parser.add_argument('--headless', action='store_true', help='Run in headless mode.')
|
|
298
338
|
chat_parser.add_argument('--chat_history', help='Chat history for headless mode (as JSON string).', default=None)
|
|
299
|
-
|
|
339
|
+
|
|
340
|
+
# Subcommand for invoking a VAC service directly
|
|
341
|
+
invoke_parser = vac_subparsers.add_parser('invoke', help='Invoke a VAC service directly with custom data.')
|
|
342
|
+
invoke_parser.add_argument('vac_name', help='Name of the VAC service.')
|
|
343
|
+
invoke_parser.add_argument('data', help='Data to send to the VAC service (as JSON string).')
|
|
300
344
|
|
|
301
345
|
vac_parser.set_defaults(func=vac_command)
|
|
@@ -45,7 +45,7 @@ def pick_vectorstore(vs_str, vector_name, embeddings, read_only=None):
|
|
|
45
45
|
return vectorstore
|
|
46
46
|
|
|
47
47
|
elif vs_str == 'cloudsql' or vs_str == 'postgres':
|
|
48
|
-
from
|
|
48
|
+
from langchain_community.vectorstores import PGVector
|
|
49
49
|
|
|
50
50
|
log.debug("Inititaing CloudSQL/Postgres pgvector")
|
|
51
51
|
#setup_cloudsql(vector_name)
|
|
@@ -75,7 +75,7 @@ def load_all_configs():
|
|
|
75
75
|
if filename in config_cache:
|
|
76
76
|
cached_config, cache_time = config_cache[filename]
|
|
77
77
|
if (current_time - cache_time) < timedelta(minutes=5):
|
|
78
|
-
log.
|
|
78
|
+
log.debug(f"Returning cached config for {filename}")
|
|
79
79
|
config = cached_config
|
|
80
80
|
else:
|
|
81
81
|
config = reload_config_file(config_file, filename)
|
|
@@ -167,7 +167,7 @@ def load_config(filename: str=None) -> tuple[dict, str]:
|
|
|
167
167
|
|
|
168
168
|
return config, filename
|
|
169
169
|
|
|
170
|
-
def load_config_key(key: str, vector_name: str, kind: str
|
|
170
|
+
def load_config_key(key: str, vector_name: str, kind: str):
|
|
171
171
|
"""
|
|
172
172
|
Load a specific key from a configuration file.
|
|
173
173
|
|
|
@@ -192,27 +192,16 @@ def load_config_key(key: str, vector_name: str, kind: str=None):
|
|
|
192
192
|
|
|
193
193
|
configs_by_kind = load_all_configs()
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
log.debug(f"Got kind: {kind} - applying to configs")
|
|
195
|
+
log.debug(f"Got kind: {kind} - applying to configs")
|
|
197
196
|
|
|
198
197
|
if not configs_by_kind:
|
|
199
198
|
log.warning("Did not load configs via folder")
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
config = configs_by_kind[kind]
|
|
203
|
-
filename = kind
|
|
204
|
-
else:
|
|
205
|
-
config, filename = load_config(filename)
|
|
200
|
+
config = configs_by_kind[kind]
|
|
206
201
|
|
|
207
|
-
log.debug(f"Fetching '{key}' for '{vector_name}'")
|
|
208
202
|
apiVersion = config.get('apiVersion')
|
|
209
|
-
kind = config.get('kind')
|
|
210
|
-
vac = config.get('vac')
|
|
211
203
|
|
|
212
|
-
|
|
213
|
-
raise ValueError("Deprecated config file, move to config with `apiVersion` and `kind` set")
|
|
214
|
-
|
|
215
|
-
log.debug(f"Loaded config file {kind}/{apiVersion}")
|
|
204
|
+
log.debug(f"Fetching '{key}' for '{vector_name}' from '{kind}/{apiVersion}'")
|
|
216
205
|
|
|
217
206
|
if kind == 'vacConfig':
|
|
218
207
|
if vector_name == 'global':
|
|
@@ -226,7 +215,7 @@ def load_config_key(key: str, vector_name: str, kind: str=None):
|
|
|
226
215
|
raise ValueError("Deprecated config file, move to config with `vac:` at top level for `vector_name`")
|
|
227
216
|
vac_config = vac.get(vector_name)
|
|
228
217
|
if not vac_config:
|
|
229
|
-
raise ValueError(f"No config array was found for {vector_name} in {
|
|
218
|
+
raise ValueError(f"No config array was found for {vector_name} in {kind}")
|
|
230
219
|
|
|
231
220
|
log.debug(f'vac_config: {vac_config} for {vector_name} - fetching "{key}"')
|
|
232
221
|
key_value = vac_config.get(key)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.61.
|
|
3
|
+
Version: 0.61.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.61.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.61.5.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import patch, mock_open
|
|
3
|
+
from sunholo.utils import config
|
|
4
|
+
|
|
5
|
+
def test_load_config():
|
|
6
|
+
expected_config = {"key": "value"}
|
|
7
|
+
with pytest.raises(FileNotFoundError):
|
|
8
|
+
config.load_config("non_existent_file")
|
|
9
|
+
with patch("builtins.open", mock_open(read_data='{"key": "value"}'), create=True):
|
|
10
|
+
result, _ = config.load_config("mock_file.json")
|
|
11
|
+
assert result == expected_config
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
import requests_mock
|
|
3
|
-
from sunholo.agents import dispatch_to_qa
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def setup():
|
|
7
|
-
user_input = 'mock_user_input'
|
|
8
|
-
chat_history = 'mock_chat_history'
|
|
9
|
-
vector_name = 'mock_vector_name'
|
|
10
|
-
stream = 'mock_stream'
|
|
11
|
-
return user_input, chat_history, vector_name, stream
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def test_prep_request_payload():
|
|
15
|
-
user_input, chat_history, vector_name, stream = setup()
|
|
16
|
-
# Call 'prep_request_payload' with the mock data
|
|
17
|
-
qna_endpoint, qna_data = dispatch_to_qa.prep_request_payload(user_input, chat_history, vector_name, stream)
|
|
18
|
-
# Check the returned 'qna_endpoint' and 'qna_data'
|
|
19
|
-
assert qna_endpoint == 'expected_qna_endpoint'
|
|
20
|
-
assert qna_data == 'expected_qna_data'
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_send_to_qa():
|
|
24
|
-
user_input, chat_history, vector_name, stream = setup()
|
|
25
|
-
mock_qna_endpoint = 'http://mock.qna.endpoint'
|
|
26
|
-
mock_response = {'status': 'success'}
|
|
27
|
-
with requests_mock.Mocker() as m:
|
|
28
|
-
m.post(mock_qna_endpoint, json=mock_response)
|
|
29
|
-
response = dispatch_to_qa.send_to_qa(user_input, chat_history, vector_name, stream)
|
|
30
|
-
assert response == mock_response
|
|
31
|
-
|
|
32
|
-
# Scenario where 'stream' is True and the response is a generator that yields response content chunks
|
|
33
|
-
mock_response_chunk = 'mock_response_chunk'
|
|
34
|
-
m.post(mock_qna_endpoint, text=mock_response_chunk)
|
|
35
|
-
response = dispatch_to_qa.send_to_qa(user_input, chat_history, vector_name, True)
|
|
36
|
-
assert next(response) == mock_response_chunk
|
|
37
|
-
|
|
38
|
-
# Scenario where an HTTP error occurs
|
|
39
|
-
m.post(mock_qna_endpoint, status_code=500)
|
|
40
|
-
response = dispatch_to_qa.send_to_qa(user_input, chat_history, vector_name, stream)
|
|
41
|
-
assert 'Error' in response
|
|
42
|
-
|
|
43
|
-
# Scenario where any other error occurs
|
|
44
|
-
m.post(mock_qna_endpoint, exc=requests_mock.exceptions.ReadTimeout)
|
|
45
|
-
response = dispatch_to_qa.send_to_qa(user_input, chat_history, vector_name, stream)
|
|
46
|
-
assert 'Error' in response
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def test_send_to_qa_async():
|
|
50
|
-
user_input, chat_history, vector_name, stream = setup()
|
|
51
|
-
mock_qna_endpoint = 'http://mock.qna.endpoint'
|
|
52
|
-
mock_response = {'status': 'success'}
|
|
53
|
-
import aiohttp
|
|
54
|
-
|
|
55
|
-
@pytest.mark.asyncio
|
|
56
|
-
async def test_send_to_qa_async():
|
|
57
|
-
user_input, chat_history, vector_name, stream = setup()
|
|
58
|
-
mock_qna_endpoint = 'http://mock.qna.endpoint'
|
|
59
|
-
mock_response = {'status': 'success'}
|
|
60
|
-
async with aiohttp.ClientSession() as session:
|
|
61
|
-
async with session.post(mock_qna_endpoint, json=mock_response) as resp:
|
|
62
|
-
response = await dispatch_to_qa.send_to_qa_async(user_input, chat_history, vector_name, stream)
|
|
63
|
-
assert response == mock_response
|
|
64
|
-
|
|
65
|
-
# Scenario where an HTTP error occurs
|
|
66
|
-
async with session.post(mock_qna_endpoint, status=500) as resp:
|
|
67
|
-
response = await dispatch_to_qa.send_to_qa_async(user_input, chat_history, vector_name, stream)
|
|
68
|
-
assert 'Error' in response
|
|
69
|
-
|
|
70
|
-
# Scenario where any other error occurs
|
|
71
|
-
async with session.post(mock_qna_endpoint, raise_for_status=False) as resp:
|
|
72
|
-
response = await dispatch_to_qa.send_to_qa_async(user_input, chat_history, vector_name, stream)
|
|
73
|
-
assert 'Error' in response
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from sunholo.utils import config
|
|
3
|
-
|
|
4
|
-
# Test for the `load_config` function
|
|
5
|
-
def test_load_config():
|
|
6
|
-
# Assuming the function is supposed to load a configuration from a file
|
|
7
|
-
# and return a dictionary with the configuration data
|
|
8
|
-
expected_config = {"key": "value"}
|
|
9
|
-
with pytest.raises(FileNotFoundError):
|
|
10
|
-
config.load_config("non_existent_file")
|
|
11
|
-
with pytest.mock.patch("builtins.open", pytest.mock.mock_open(read_data="key: value"), create=True):
|
|
12
|
-
assert config.load_config("mock_file.yaml") == expected_config
|
|
13
|
-
|
|
14
|
-
# Test for the `load_config_key` function
|
|
15
|
-
def test_load_config_key():
|
|
16
|
-
# Assuming the function is supposed to load a specific key from the configuration
|
|
17
|
-
expected_value = "value"
|
|
18
|
-
with pytest.raises(KeyError):
|
|
19
|
-
config.load_config_key("non_existent_key", "mock_vector_name")
|
|
20
|
-
with pytest.mock.patch("sunholo.utils.config.load_all_configs", return_value={"mock_vector_name": {"key": "value"}}):
|
|
21
|
-
assert config.load_config_key("key", "mock_vector_name") == expected_value
|
|
22
|
-
|
|
23
|
-
# Test for the `get_module_filepath` function
|
|
24
|
-
def test_get_module_filepath():
|
|
25
|
-
# Assuming the function is supposed to return the absolute path of a module file
|
|
26
|
-
expected_path = "/absolute/path/to/module/file"
|
|
27
|
-
with pytest.mock.patch("os.path.dirname", return_value="/absolute/path/to"):
|
|
28
|
-
assert config.get_module_filepath("module/file") == expected_path
|
|
29
|
-
|
|
30
|
-
# Test for the `fetch_config` function
|
|
31
|
-
def test_fetch_config():
|
|
32
|
-
# Assuming the function is supposed to fetch configuration from a cloud storage bucket
|
|
33
|
-
expected_update_time = "2022-01-01T00:00:00Z"
|
|
34
|
-
with pytest.mock.patch("google.cloud.storage.Client") as mock_client:
|
|
35
|
-
mock_bucket = mock_client.return_value.get_bucket.return_value
|
|
36
|
-
mock_blob = mock_bucket.get_blob.return_value
|
|
37
|
-
mock_blob.updated = expected_update_time
|
|
38
|
-
assert config.fetch_config("bucket_name", "blob_name") == expected_update_time
|
|
39
|
-
mock_bucket.get_blob.return_value = None
|
|
40
|
-
assert config.fetch_config("bucket_name", "blob_name") is None
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|