sunholo 0.60.9__tar.gz → 0.61.4__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.60.9 → sunholo-0.61.4}/PKG-INFO +2 -2
- {sunholo-0.60.9 → sunholo-0.61.4}/setup.py +1 -1
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/chat_history.py +1 -1
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/components/vectorstore.py +1 -1
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/config.py +6 -17
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo.egg-info/PKG-INFO +2 -2
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo.egg-info/SOURCES.txt +2 -2
- sunholo-0.61.4/tests/test_chat_history.py +50 -0
- sunholo-0.61.4/tests/test_config.py +15 -0
- sunholo-0.60.9/sunholo/agents/test_chat_history.py +0 -119
- sunholo-0.60.9/test/test_dispatch_to_qa.py +0 -73
- {sunholo-0.60.9 → sunholo-0.61.4}/LICENSE.txt +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/MANIFEST.in +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/README.md +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/setup.cfg +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/route.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/archive/archive.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/auth/run.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/bots/discord.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/data_to_embed_pubsub.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/images.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/cli.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/configs.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/components/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/components/llm.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/components/prompt.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/components/retriever.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/database.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/database/uuid.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/llamaindex/generate.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/logging.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/qna/retry.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/parsers.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo/vertex/init_vertex.py +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.60.9 → sunholo-0.61.4}/sunholo.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.61.4
|
|
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.61.4.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 ""
|
|
@@ -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.
|
|
3
|
+
Version: 0.61.4
|
|
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.61.4.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -18,7 +18,6 @@ sunholo/agents/langserve.py
|
|
|
18
18
|
sunholo/agents/pubsub.py
|
|
19
19
|
sunholo/agents/route.py
|
|
20
20
|
sunholo/agents/special_commands.py
|
|
21
|
-
sunholo/agents/test_chat_history.py
|
|
22
21
|
sunholo/agents/fastapi/__init__.py
|
|
23
22
|
sunholo/agents/fastapi/base.py
|
|
24
23
|
sunholo/agents/fastapi/qna_routes.py
|
|
@@ -107,4 +106,5 @@ sunholo/utils/parsers.py
|
|
|
107
106
|
sunholo/utils/user_ids.py
|
|
108
107
|
sunholo/vertex/__init__.py
|
|
109
108
|
sunholo/vertex/init_vertex.py
|
|
110
|
-
|
|
109
|
+
tests/test_chat_history.py
|
|
110
|
+
tests/test_config.py
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from sunholo.agents.chat_history import extract_chat_history, embeds_to_json, create_message_element, is_human, is_bot, is_ai
|
|
3
|
+
|
|
4
|
+
# Test cases for extract_chat_history function
|
|
5
|
+
@pytest.mark.parametrize("chat_history,expected", [
|
|
6
|
+
([], []),
|
|
7
|
+
([{"name": "Human", "text": "Hello, AI!"}, {"name": "AI", "text": "Hello, Human! How can I help you today?"}], [("Hello, AI!", "Hello, Human! How can I help you today?")])
|
|
8
|
+
])
|
|
9
|
+
def test_extract_chat_history(chat_history, expected):
|
|
10
|
+
assert extract_chat_history(chat_history) == expected
|
|
11
|
+
|
|
12
|
+
# Test cases for embeds_to_json function
|
|
13
|
+
@pytest.mark.parametrize("message,expected", [
|
|
14
|
+
({"embeds": []}, ""),
|
|
15
|
+
({"embeds": [{"type": "image", "url": "https://example.com/image.png"}]}, '[{"type": "image", "url": "https://example.com/image.png"}]')
|
|
16
|
+
])
|
|
17
|
+
def test_embeds_to_json(message, expected):
|
|
18
|
+
assert embeds_to_json(message) == expected
|
|
19
|
+
|
|
20
|
+
# Test cases for create_message_element function
|
|
21
|
+
@pytest.mark.parametrize("message,expected", [
|
|
22
|
+
({"text": "Hello, AI!"}, "Hello, AI!"),
|
|
23
|
+
({"content": "Hello, AI!"}, "Hello, AI!")
|
|
24
|
+
])
|
|
25
|
+
def test_create_message_element(message, expected):
|
|
26
|
+
assert create_message_element(message) == expected
|
|
27
|
+
|
|
28
|
+
# Test cases for is_human function
|
|
29
|
+
@pytest.mark.parametrize("message,expected", [
|
|
30
|
+
({"name": "Human"}, True),
|
|
31
|
+
({"name": "AI"}, False)
|
|
32
|
+
])
|
|
33
|
+
def test_is_human(message, expected):
|
|
34
|
+
assert is_human(message) == expected
|
|
35
|
+
|
|
36
|
+
# Test cases for is_bot function
|
|
37
|
+
@pytest.mark.parametrize("message,expected", [
|
|
38
|
+
({"name": "AI"}, True),
|
|
39
|
+
({"name": "Human"}, False)
|
|
40
|
+
])
|
|
41
|
+
def test_is_bot(message, expected):
|
|
42
|
+
assert is_bot(message) == expected
|
|
43
|
+
|
|
44
|
+
# Test cases for is_ai function
|
|
45
|
+
@pytest.mark.parametrize("message,expected", [
|
|
46
|
+
({"name": "AI"}, True),
|
|
47
|
+
({"name": "Human"}, False)
|
|
48
|
+
])
|
|
49
|
+
def test_is_ai(message, expected):
|
|
50
|
+
assert is_ai(message) == expected
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
|
12
|
+
|
|
13
|
+
def test_load_config_key():
|
|
14
|
+
with pytest.raises(KeyError):
|
|
15
|
+
config.load_config_key("non_existent_key", "mock_vector_name")
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from .chat_history import *
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def test_extract_chat_history_null_input():
|
|
6
|
-
assert extract_chat_history(None) == [], 'Expected empty list for null input'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def test_extract_chat_history_no_chat():
|
|
10
|
-
assert extract_chat_history([]) == [], 'Expected empty list for no chat history'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_extract_chat_history_with_chat():
|
|
14
|
-
chat_history = [('User', 'Hello'), ('Bot', 'Hi'), ('User', 'How are you?'), ('Bot', 'I am fine.')]
|
|
15
|
-
expected_output = [('User', 'Hello'), ('Bot', 'Hi'), ('User', 'How are you?'), ('Bot', 'I am fine.')]
|
|
16
|
-
assert extract_chat_history(chat_history) == expected_output, 'Expected list of paired messages for chat history'
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# Test cases for embeds_to_json function
|
|
20
|
-
|
|
21
|
-
def test_embeds_to_json_no_embeds():
|
|
22
|
-
message = 'Hello, world!'
|
|
23
|
-
assert embeds_to_json(message) == '', 'Expected empty string for message with no embeds'
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def test_embeds_to_json_one_embed():
|
|
27
|
-
message = 'Hello, world! [embed]'
|
|
28
|
-
expected_output = '{"embeds": ["embed"]}'
|
|
29
|
-
assert embeds_to_json(message) == expected_output, 'Expected JSON string with one embed for message with one embed'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def test_embeds_to_json_multiple_embeds():
|
|
33
|
-
message = 'Hello, world! [embed1] [embed2]'
|
|
34
|
-
expected_output = '{"embeds": ["embed1", "embed2"]}'
|
|
35
|
-
assert embeds_to_json(message) == expected_output, 'Expected JSON string with multiple embeds for message with multiple embeds'
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# Test cases for create_message_element function
|
|
39
|
-
|
|
40
|
-
def test_create_message_element_text():
|
|
41
|
-
message = {'text': 'Hello, world!'}
|
|
42
|
-
assert create_message_element(message) == 'Hello, world!', 'Expected text element for message with text'
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def test_create_message_element_content():
|
|
46
|
-
message = {'content': 'Hello, world!'}
|
|
47
|
-
assert create_message_element(message) == 'Hello, world!', 'Expected content element for message with content'
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_create_message_element_no_text_or_content():
|
|
51
|
-
message = {}
|
|
52
|
-
with pytest.raises(KeyError):
|
|
53
|
-
create_message_element(message)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Test cases for is_human function
|
|
57
|
-
|
|
58
|
-
def test_is_human_name_human():
|
|
59
|
-
message = {'name': 'Human'}
|
|
60
|
-
assert is_human(message) == True, 'Expected True for message with name Human'
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def test_is_human_sender_type_human():
|
|
64
|
-
message = {'sender': {'type': 'HUMAN'}}
|
|
65
|
-
assert is_human(message) == True, 'Expected True for message with sender type HUMAN'
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_is_human_user_no_bot_id():
|
|
69
|
-
message = {'user': 'User1', 'bot_id': None}
|
|
70
|
-
assert is_human(message) == True, 'Expected True for message with user field and no bot_id field'
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def test_is_human_not_human():
|
|
74
|
-
message = {'name': 'Bot'}
|
|
75
|
-
assert is_human(message) == False, 'Expected False for message not from a human'
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
# Test cases for is_bot function
|
|
79
|
-
|
|
80
|
-
def test_is_bot_name_bot():
|
|
81
|
-
message = {'name': 'Bot'}
|
|
82
|
-
assert is_bot(message) == True, 'Expected True for message with name Bot'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def test_is_bot_sender_type_bot():
|
|
86
|
-
message = {'sender': {'type': 'BOT'}}
|
|
87
|
-
assert is_bot(message) == True, 'Expected True for message with sender type BOT'
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
def test_is_bot_with_bot_id():
|
|
91
|
-
message = {'bot_id': 'bot1'}
|
|
92
|
-
assert is_bot(message) == True, 'Expected True for message with bot_id field'
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def test_is_bot_not_bot():
|
|
96
|
-
message = {'name': 'Human'}
|
|
97
|
-
assert is_bot(message) == False, 'Expected False for message not from a bot'
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# Test cases for is_ai function
|
|
101
|
-
|
|
102
|
-
def test_is_ai_name_ai():
|
|
103
|
-
message = {'name': 'AI'}
|
|
104
|
-
assert is_ai(message) == True, 'Expected True for message with name AI'
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def test_is_ai_sender_type_bot():
|
|
108
|
-
message = {'sender': {'type': 'BOT'}}
|
|
109
|
-
assert is_ai(message) == True, 'Expected True for message with sender type BOT'
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def test_is_ai_with_bot_id():
|
|
113
|
-
message = {'bot_id': 'bot1'}
|
|
114
|
-
assert is_ai(message) == True, 'Expected True for message with bot_id field'
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def test_is_ai_not_ai():
|
|
118
|
-
message = {'name': 'Human'}
|
|
119
|
-
assert is_ai(message) == False, 'Expected False for message not from an AI'
|
|
@@ -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
|
|
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
|