sunholo 0.62.2__tar.gz → 0.62.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.62.2 → sunholo-0.62.4}/PKG-INFO +2 -2
- {sunholo-0.62.2 → sunholo-0.62.4}/setup.py +1 -1
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/dispatch_to_qa.py +5 -1
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/route.py +2 -9
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/chat_vac.py +74 -36
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/components/__init__.py +0 -1
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/streaming/__init__.py +2 -1
- sunholo-0.62.4/sunholo/streaming/stream_lookup.py +12 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/config.py +22 -4
- sunholo-0.62.4/sunholo/utils/timedelta.py +14 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo.egg-info/PKG-INFO +2 -2
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo.egg-info/SOURCES.txt +2 -1
- sunholo-0.62.2/sunholo/components/prompt.py +0 -151
- {sunholo-0.62.2 → sunholo-0.62.4}/LICENSE.txt +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/MANIFEST.in +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/README.md +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/setup.cfg +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/flask/qna_routes.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/archive/archive.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/auth/run.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/bots/discord.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/data_to_embed_pubsub.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/images.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/cli.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/configs.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/embedder.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/components/llm.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/components/retriever.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/database.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/database/uuid.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/llamaindex/generate.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/logging.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/qna/retry.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/parsers.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/vertex/init.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/tests/test_chat_history.py +0 -0
- {sunholo-0.62.2 → sunholo-0.62.4}/tests/test_config.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.62.
|
|
3
|
+
Version: 0.62.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.62.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.62.4.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,10 @@ def prep_request_payload(user_input, chat_history, vector_name, stream, **kwargs
|
|
|
59
59
|
# {'stream': '', 'invoke': ''}
|
|
60
60
|
endpoints = route_endpoint(vector_name, override_endpoint=override_endpoint)
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
if stream:
|
|
63
|
+
qna_endpoint = endpoints["stream"]
|
|
64
|
+
else:
|
|
65
|
+
qna_endpoint = endpoints["invoke"]
|
|
63
66
|
|
|
64
67
|
if agent == "langserve" or agent_type == "langserve":
|
|
65
68
|
qna_data = prepare_request_data(user_input, endpoints["input_schema"], vector_name, **kwargs)
|
|
@@ -67,6 +70,7 @@ def prep_request_payload(user_input, chat_history, vector_name, stream, **kwargs
|
|
|
67
70
|
# Base qna_data dictionary
|
|
68
71
|
qna_data = {
|
|
69
72
|
'user_input': user_input,
|
|
73
|
+
'vector_name': vector_name,
|
|
70
74
|
}
|
|
71
75
|
# Update qna_data with optional values from kwargs
|
|
72
76
|
qna_data.update(kwargs)
|
|
@@ -42,15 +42,8 @@ def route_endpoint(vector_name, override_endpoint=None):
|
|
|
42
42
|
agent_type = load_config_key('agent', vector_name, kind="vacConfig")
|
|
43
43
|
|
|
44
44
|
stem = route_qna(vector_name) if not override_endpoint else override_endpoint
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
# Select the appropriate configuration based on agent_type
|
|
49
|
-
if agent_type in agent_config:
|
|
50
|
-
endpoints_config = agent_config[agent_type]
|
|
51
|
-
else:
|
|
52
|
-
log.warning('Using default endpoints configuration')
|
|
53
|
-
endpoints_config = agent_config['default']
|
|
45
|
+
|
|
46
|
+
endpoints_config = load_config_key(agent_type, vector_name, kind="agentConfig")
|
|
54
47
|
|
|
55
48
|
log.info(f"endpoints_config: {endpoints_config}")
|
|
56
49
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from ..agents import send_to_qa
|
|
2
|
-
from ..streaming import generate_proxy_stream
|
|
2
|
+
from ..streaming import generate_proxy_stream, can_agent_stream
|
|
3
3
|
from ..utils.user_ids import generate_user_id
|
|
4
4
|
from ..utils.config import load_config_key
|
|
5
|
+
from ..logging import log
|
|
5
6
|
|
|
6
7
|
from .run_proxy import clean_proxy_list, start_proxy, stop_proxy
|
|
7
8
|
|
|
@@ -33,12 +34,16 @@ def get_service_url(vac_name, project, region, no_config=False):
|
|
|
33
34
|
port = proxies[agent_name]['port']
|
|
34
35
|
url = f"http://127.0.0.1:{port}"
|
|
35
36
|
else:
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
if agent_name:
|
|
38
|
+
console.print(f"No proxy found running for service: [bold orange]'{agent_name}'[/bold orange] required for [bold orange]{vac_name}[/bold orange] - attempting to connect")
|
|
39
|
+
url = start_proxy(agent_name, region, project)
|
|
40
|
+
else:
|
|
41
|
+
console.print(f"No config for [bold orange]'{vac_name}'[/bold orange] - can't start proxy")
|
|
42
|
+
sys.exit(1)
|
|
38
43
|
|
|
39
44
|
return url
|
|
40
45
|
|
|
41
|
-
def stream_chat_session(service_url, service_name):
|
|
46
|
+
def stream_chat_session(service_url, service_name, stream=True):
|
|
42
47
|
|
|
43
48
|
user_id = generate_user_id()
|
|
44
49
|
chat_history = []
|
|
@@ -48,16 +53,11 @@ def stream_chat_session(service_url, service_name):
|
|
|
48
53
|
if user_input.lower() in ["exit", "quit"]:
|
|
49
54
|
console.print("[bold red]Exiting chat session.[/bold red]")
|
|
50
55
|
break
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
send_to_qa,
|
|
55
|
-
user_input,
|
|
56
|
+
|
|
57
|
+
if not stream:
|
|
58
|
+
vac_response = send_to_qa(user_input,
|
|
56
59
|
vector_name=service_name,
|
|
57
60
|
chat_history=chat_history,
|
|
58
|
-
generate_f_output=lambda x: x, # Replace with actual processing function
|
|
59
|
-
stream_wait_time=0.5,
|
|
60
|
-
stream_timeout=120,
|
|
61
61
|
message_author=user_id,
|
|
62
62
|
#TODO: populate these
|
|
63
63
|
image_url=None,
|
|
@@ -73,34 +73,65 @@ def stream_chat_session(service_url, service_name):
|
|
|
73
73
|
user_id=user_id,
|
|
74
74
|
session_id=session_id,
|
|
75
75
|
message_source="cli",
|
|
76
|
-
override_endpoint=service_url
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
response_started = False
|
|
82
|
-
vac_response = ""
|
|
76
|
+
override_endpoint=service_url)
|
|
77
|
+
|
|
78
|
+
console.print(f"[bold yellow]{service_name}:[/bold yellow] {vac_response}", end='\n')
|
|
79
|
+
else:
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
81
|
+
def stream_response():
|
|
82
|
+
generate = generate_proxy_stream(
|
|
83
|
+
send_to_qa,
|
|
84
|
+
user_input,
|
|
85
|
+
vector_name=service_name,
|
|
86
|
+
chat_history=chat_history,
|
|
87
|
+
generate_f_output=lambda x: x, # Replace with actual processing function
|
|
88
|
+
stream_wait_time=0.5,
|
|
89
|
+
stream_timeout=120,
|
|
90
|
+
message_author=user_id,
|
|
91
|
+
#TODO: populate these
|
|
92
|
+
image_url=None,
|
|
93
|
+
source_filters=None,
|
|
94
|
+
search_kwargs=None,
|
|
95
|
+
private_docs=None,
|
|
96
|
+
whole_document=False,
|
|
97
|
+
source_filters_and_or=False,
|
|
98
|
+
# system kwargs
|
|
99
|
+
configurable={
|
|
100
|
+
"vector_name": service_name,
|
|
101
|
+
},
|
|
102
|
+
user_id=user_id,
|
|
103
|
+
session_id=session_id,
|
|
104
|
+
message_source="cli",
|
|
105
|
+
override_endpoint=service_url
|
|
106
|
+
)
|
|
107
|
+
for part in generate():
|
|
108
|
+
yield part
|
|
109
|
+
|
|
110
|
+
response_started = False
|
|
111
|
+
vac_response = ""
|
|
112
|
+
|
|
113
|
+
# point or star?
|
|
114
|
+
with console.status("[bold orange]Thinking...[/bold orange]", spinner="star") as status:
|
|
115
|
+
for token in stream_response():
|
|
116
|
+
if not response_started:
|
|
117
|
+
status.stop()
|
|
118
|
+
console.print(f"[bold yellow]{service_name}:[/bold yellow] ", end='')
|
|
119
|
+
response_started = True
|
|
120
|
+
|
|
121
|
+
if isinstance(token, bytes):
|
|
122
|
+
token = token.decode('utf-8')
|
|
123
|
+
console.print(token, end='')
|
|
124
|
+
vac_response += token
|
|
125
|
+
|
|
126
|
+
response_started = False
|
|
96
127
|
|
|
97
128
|
chat_history.append({"name": "Human", "content": user_input})
|
|
98
129
|
chat_history.append({"name": "AI", "content": vac_response})
|
|
99
|
-
|
|
130
|
+
|
|
100
131
|
console.print()
|
|
101
132
|
console.rule()
|
|
102
133
|
|
|
103
|
-
def headless_mode(service_url, service_name, user_input, chat_history=None):
|
|
134
|
+
def headless_mode(service_url, service_name, user_input, chat_history=None, stream=True):
|
|
104
135
|
chat_history = chat_history or []
|
|
105
136
|
|
|
106
137
|
user_id = generate_user_id()
|
|
@@ -192,16 +223,23 @@ def vac_command(args):
|
|
|
192
223
|
service_url = resolve_service_url(args)
|
|
193
224
|
agent_name = load_config_key("agent", args.vac_name, kind="vacConfig")
|
|
194
225
|
|
|
226
|
+
streamer = can_agent_stream(agent_name)
|
|
227
|
+
log.warning(f"streamer: {streamer}")
|
|
228
|
+
if not streamer:
|
|
229
|
+
console.print(f"Non streaming agent: {args.vac_name}")
|
|
230
|
+
|
|
195
231
|
if args.headless:
|
|
196
|
-
headless_mode(service_url, args.vac_name, args.user_input, args.chat_history)
|
|
232
|
+
headless_mode(service_url, args.vac_name, args.user_input, args.chat_history, stream=streamer)
|
|
197
233
|
else:
|
|
198
234
|
display_name = load_config_key("display_name", vector_name=args.vac_name, kind="vacConfig")
|
|
199
235
|
description = load_config_key("description", vector_name=args.vac_name, kind="vacConfig")
|
|
236
|
+
endpoints_config = load_config_key(agent_name, "dummy_value", kind="agentConfig")
|
|
200
237
|
|
|
238
|
+
display_endpoints = ', '.join(f"{key}: {value}" for key, value in endpoints_config.items())
|
|
201
239
|
if agent_name == "langserve":
|
|
202
240
|
subtitle = f"{service_url}/{args.vac_name}/playground/"
|
|
203
241
|
else:
|
|
204
|
-
subtitle = f"{agent_name} - {
|
|
242
|
+
subtitle = f"{agent_name} - {display_endpoints}"
|
|
205
243
|
|
|
206
244
|
print(
|
|
207
245
|
Panel(description or "Starting VAC chat session",
|
|
@@ -209,7 +247,7 @@ def vac_command(args):
|
|
|
209
247
|
subtitle=subtitle)
|
|
210
248
|
)
|
|
211
249
|
|
|
212
|
-
stream_chat_session(service_url, args.vac_name)
|
|
250
|
+
stream_chat_session(service_url, args.vac_name, stream=streamer)
|
|
213
251
|
|
|
214
252
|
stop_proxy(agent_name, stop_local=False)
|
|
215
253
|
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
from .streaming import start_streaming_chat, generate_proxy_stream, generate_proxy_stream_async, start_streaming_chat_async
|
|
2
|
-
from .langserve import parse_langserve_token, parse_langserve_token_async
|
|
2
|
+
from .langserve import parse_langserve_token, parse_langserve_token_async
|
|
3
|
+
from .stream_lookup import can_agent_stream
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from ..utils import load_config_key
|
|
2
|
+
from ..logging import log
|
|
3
|
+
|
|
4
|
+
def can_agent_stream(agent_name: str):
|
|
5
|
+
|
|
6
|
+
log.warning(f"agent_type: {agent_name} checking streaming...")
|
|
7
|
+
endpoints_config = load_config_key(agent_name, "dummy_value", kind="agentConfig")
|
|
8
|
+
|
|
9
|
+
return 'stream' in endpoints_config
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
@@ -17,6 +17,7 @@ import json
|
|
|
17
17
|
import yaml
|
|
18
18
|
from datetime import datetime, timedelta
|
|
19
19
|
from collections import defaultdict
|
|
20
|
+
from .timedelta import format_timedelta
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def get_module_filepath(filepath: str):
|
|
@@ -56,6 +57,11 @@ def load_all_configs():
|
|
|
56
57
|
"""
|
|
57
58
|
from ..logging import log
|
|
58
59
|
|
|
60
|
+
if not os.getenv("_CONFIG_FOLDER", None):
|
|
61
|
+
log.debug("_CONFIG_FOLDER is not set, using os.getcwd() instead")
|
|
62
|
+
else:
|
|
63
|
+
log.debug(f"_CONFIG_FOLDER set to: {os.getenv('_CONFIG_FOLDER')}")
|
|
64
|
+
|
|
59
65
|
config_folder = os.getenv("_CONFIG_FOLDER", os.getcwd())
|
|
60
66
|
config_folder = os.path.join(config_folder, "config")
|
|
61
67
|
|
|
@@ -74,8 +80,9 @@ def load_all_configs():
|
|
|
74
80
|
# Check cache first
|
|
75
81
|
if filename in config_cache:
|
|
76
82
|
cached_config, cache_time = config_cache[filename]
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
time_to_recache = (current_time - cache_time)
|
|
84
|
+
if time_to_recache < timedelta(minutes=5):
|
|
85
|
+
log.debug(f"Returning cached config for {filename} - recache in {format_timedelta(timedelta(minutes=5) - time_to_recache)}")
|
|
79
86
|
config = cached_config
|
|
80
87
|
else:
|
|
81
88
|
config = reload_config_file(config_file, filename)
|
|
@@ -102,7 +109,7 @@ def reload_config_file(config_file, filename):
|
|
|
102
109
|
config = yaml.safe_load(file)
|
|
103
110
|
|
|
104
111
|
config_cache[filename] = (config, datetime.now())
|
|
105
|
-
log.debug(f"Loaded and cached {
|
|
112
|
+
log.debug(f"Loaded and cached {config_file}")
|
|
106
113
|
return config
|
|
107
114
|
|
|
108
115
|
|
|
@@ -187,7 +194,9 @@ def load_config_key(key: str, vector_name: str, kind: str):
|
|
|
187
194
|
"""
|
|
188
195
|
from ..logging import log
|
|
189
196
|
|
|
190
|
-
|
|
197
|
+
if kind != 'agentConfig':
|
|
198
|
+
assert isinstance(key, str), f"key must be a string got a {type(key)}"
|
|
199
|
+
|
|
191
200
|
assert isinstance(vector_name, str), f"vector_name must be a string, got a {type(vector_name)}"
|
|
192
201
|
|
|
193
202
|
configs_by_kind = load_all_configs()
|
|
@@ -236,3 +245,12 @@ def load_config_key(key: str, vector_name: str, kind: str):
|
|
|
236
245
|
key_value = prompt_for_vector_name.get(key)
|
|
237
246
|
|
|
238
247
|
return key_value
|
|
248
|
+
elif kind == 'agentConfig':
|
|
249
|
+
agents = config.get('agents')
|
|
250
|
+
|
|
251
|
+
if key in agents:
|
|
252
|
+
return agents[key]
|
|
253
|
+
else:
|
|
254
|
+
log.warning("Returning default agent endpoints")
|
|
255
|
+
return agents["default"]
|
|
256
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
def format_timedelta(td):
|
|
2
|
+
days = td.days
|
|
3
|
+
seconds = td.seconds
|
|
4
|
+
hours, remainder = divmod(seconds, 3600)
|
|
5
|
+
minutes, seconds = divmod(remainder, 60)
|
|
6
|
+
|
|
7
|
+
if days > 0:
|
|
8
|
+
return f"{days} day(s), {hours} hour(s), {minutes} minute(s), {seconds} second(s)"
|
|
9
|
+
elif hours > 0:
|
|
10
|
+
return f"{hours} hour(s), {minutes} minute(s), {seconds} second(s)"
|
|
11
|
+
elif minutes > 0:
|
|
12
|
+
return f"{minutes} minute(s), {seconds} second(s)"
|
|
13
|
+
else:
|
|
14
|
+
return f"{seconds} second(s)"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.62.
|
|
3
|
+
Version: 0.62.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.62.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.62.4.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -53,7 +53,6 @@ sunholo/cli/run_proxy.py
|
|
|
53
53
|
sunholo/cli/sun_rich.py
|
|
54
54
|
sunholo/components/__init__.py
|
|
55
55
|
sunholo/components/llm.py
|
|
56
|
-
sunholo/components/prompt.py
|
|
57
56
|
sunholo/components/retriever.py
|
|
58
57
|
sunholo/components/vectorstore.py
|
|
59
58
|
sunholo/database/__init__.py
|
|
@@ -96,6 +95,7 @@ sunholo/qna/retry.py
|
|
|
96
95
|
sunholo/streaming/__init__.py
|
|
97
96
|
sunholo/streaming/content_buffer.py
|
|
98
97
|
sunholo/streaming/langserve.py
|
|
98
|
+
sunholo/streaming/stream_lookup.py
|
|
99
99
|
sunholo/streaming/streaming.py
|
|
100
100
|
sunholo/summarise/__init__.py
|
|
101
101
|
sunholo/summarise/summarise.py
|
|
@@ -105,6 +105,7 @@ sunholo/utils/config.py
|
|
|
105
105
|
sunholo/utils/config_schema.py
|
|
106
106
|
sunholo/utils/gcp.py
|
|
107
107
|
sunholo/utils/parsers.py
|
|
108
|
+
sunholo/utils/timedelta.py
|
|
108
109
|
sunholo/utils/user_ids.py
|
|
109
110
|
sunholo/vertex/__init__.py
|
|
110
111
|
sunholo/vertex/init.py
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
# Copyright [2024] [Holosun ApS]
|
|
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
|
-
from ..logging import log
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
import datetime
|
|
18
|
-
|
|
19
|
-
from langchain.prompts.prompt import PromptTemplate
|
|
20
|
-
|
|
21
|
-
from ..utils import load_config_key
|
|
22
|
-
from .vectorstore import pick_vectorstore
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def pick_prompt(vector_name, chat_history=[]):
|
|
26
|
-
"""Pick a custom prompt"""
|
|
27
|
-
log.debug('Picking prompt')
|
|
28
|
-
|
|
29
|
-
prompt_str = load_config_key("prompt", vector_name, filename = "config/llm_config.yaml")
|
|
30
|
-
|
|
31
|
-
the_date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %Z')
|
|
32
|
-
prompt_str_default = f"""You are Edmonbrain the chat bot created by Mark Edmondson. It is now {the_date}.
|
|
33
|
-
Use your memory to answer the question at the end.
|
|
34
|
-
Indicate in your reply how sure you are about your answer, for example whether you are certain, taking your best guess, or its very speculative.
|
|
35
|
-
|
|
36
|
-
If you don't know, just say you don't know - don't make anything up. Avoid generic boilerplate answers.
|
|
37
|
-
Consider why the question was asked, and offer follow up questions linked to those reasons.
|
|
38
|
-
Any questions about how you work should direct users to issue the `!help` command.
|
|
39
|
-
"""
|
|
40
|
-
if prompt_str is not None:
|
|
41
|
-
if "{context}" in prompt_str:
|
|
42
|
-
raise ValueError("prompt must not contain a string '{context}'")
|
|
43
|
-
if "{question}" in prompt_str:
|
|
44
|
-
raise ValueError("prompt must not contain a string '{question}'")
|
|
45
|
-
prompt_str_default = prompt_str_default + "\n" + prompt_str
|
|
46
|
-
|
|
47
|
-
chat_summary = ""
|
|
48
|
-
original_question = ""
|
|
49
|
-
if len(chat_history) != 0:
|
|
50
|
-
original_question = chat_history[0][0]
|
|
51
|
-
chat_summary = get_chat_history(chat_history, vector_name)
|
|
52
|
-
|
|
53
|
-
follow_up = "\nIf you can't answer the human's question without more information, ask a follow up question"
|
|
54
|
-
|
|
55
|
-
agent_buddy, agent_description = pick_chat_buddy(vector_name)
|
|
56
|
-
if agent_buddy:
|
|
57
|
-
follow_up += f""" either to the human, or to your friend bot.
|
|
58
|
-
You bot friend will reply back to you within your chat history.
|
|
59
|
-
Ask {agent_buddy} for help with topics: {agent_description}
|
|
60
|
-
Ask clarification questions to the human and wait for response if your friend bot can't help.
|
|
61
|
-
Don't repeat the question if you can see the answer in the chat history (from any source)
|
|
62
|
-
This means there are three people in this conversation - you, the human and your assistant bot.
|
|
63
|
-
Asking questions to your friend bot are only allowed with this format:
|
|
64
|
-
€€Question€€
|
|
65
|
-
(your question here, including all required information needed to answer the question fully)
|
|
66
|
-
Can you help, {agent_buddy} , with the above question?
|
|
67
|
-
€€End Question€€
|
|
68
|
-
"""
|
|
69
|
-
else:
|
|
70
|
-
follow_up += ".\n"
|
|
71
|
-
|
|
72
|
-
memory_str = "\n## Your Memory (ignore if not relevant to question)\n{context}\n"
|
|
73
|
-
|
|
74
|
-
current_conversation = ""
|
|
75
|
-
if chat_summary != "":
|
|
76
|
-
current_conversation =f"## Current Conversation\n{chat_summary}\n"
|
|
77
|
-
current_conversation = current_conversation.replace("{","{{").replace("}","}}") #escape {} characters
|
|
78
|
-
|
|
79
|
-
buddy_question = ""
|
|
80
|
-
my_q = "## Current Question\n{question}\n"
|
|
81
|
-
if agent_buddy:
|
|
82
|
-
buddy_question = f"""(Including, if needed, your question to {agent_buddy})"""
|
|
83
|
-
my_q = f"## Original Question that started conversation\n{original_question}\n" + my_q
|
|
84
|
-
|
|
85
|
-
prompt_template = prompt_str_default + follow_up + memory_str + current_conversation + my_q + buddy_question + "\n## Your response:\n"
|
|
86
|
-
|
|
87
|
-
log.debug(f"--Prompt_template: {prompt_template}")
|
|
88
|
-
QA_PROMPT = PromptTemplate(
|
|
89
|
-
template=prompt_template, input_variables=["context", "question"]
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
return QA_PROMPT
|
|
93
|
-
|
|
94
|
-
def pick_chat_buddy(vector_name):
|
|
95
|
-
chat_buddy = load_config_key("chat_buddy", vector_name, filename = "config/llm_config.yaml")
|
|
96
|
-
if chat_buddy is not None:
|
|
97
|
-
log.info(f"Got chat buddy {chat_buddy} for {vector_name}")
|
|
98
|
-
buddy_description = load_config_key("chat_buddy_description", vector_name)
|
|
99
|
-
return chat_buddy, buddy_description
|
|
100
|
-
return None, None
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def pick_agent(vector_name):
|
|
104
|
-
agent_str = load_config_key("agent", vector_name, filename = "config/llm_config.yaml")
|
|
105
|
-
if agent_str == "yes":
|
|
106
|
-
return True
|
|
107
|
-
|
|
108
|
-
return False
|
|
109
|
-
|
|
110
|
-
def pick_shared_vectorstore(vector_name, embeddings):
|
|
111
|
-
shared_vectorstore = load_config_key("shared_vectorstore", vector_name, filename = "config/llm_config.yaml")
|
|
112
|
-
vectorstore = pick_vectorstore(shared_vectorstore, embeddings)
|
|
113
|
-
return vectorstore
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def get_chat_history(inputs, vector_name, last_chars=1000, summary_chars=1500) -> str:
|
|
117
|
-
from langchain.schema import Document
|
|
118
|
-
from ..summarise import summarise_docs
|
|
119
|
-
|
|
120
|
-
# Prepare the full chat history
|
|
121
|
-
res = []
|
|
122
|
-
for human, ai in inputs:
|
|
123
|
-
res.append(f"Human:{human}\nAI:{ai}")
|
|
124
|
-
full_history = "\n".join(res)
|
|
125
|
-
|
|
126
|
-
# Get the last `last_chars` characters of the full chat history
|
|
127
|
-
last_bits = []
|
|
128
|
-
for human, ai in reversed(inputs):
|
|
129
|
-
add_me = f"Human:{human}\nAI:{ai}"
|
|
130
|
-
last_bits.append(add_me)
|
|
131
|
-
|
|
132
|
-
recent_history = "\n".join(reversed(last_bits))
|
|
133
|
-
recent_history = recent_history[-last_chars:]
|
|
134
|
-
log.info(f"Recent chat history: {recent_history}")
|
|
135
|
-
|
|
136
|
-
# Summarize chat history too
|
|
137
|
-
remaining_history = full_history
|
|
138
|
-
log.info(f"Remaining chat history: {remaining_history}")
|
|
139
|
-
doc_history = Document(page_content=remaining_history)
|
|
140
|
-
chat_summary = summarise_docs([doc_history], vector_name=vector_name, skip_if_less=last_chars)
|
|
141
|
-
text_sum = ""
|
|
142
|
-
for summ in chat_summary:
|
|
143
|
-
text_sum += summ.page_content + "\n"
|
|
144
|
-
|
|
145
|
-
log.info(f"Conversation Summary: {text_sum}")
|
|
146
|
-
|
|
147
|
-
# Make sure the summary is not longer than `summary_chars` characters
|
|
148
|
-
summary = text_sum[:summary_chars]
|
|
149
|
-
|
|
150
|
-
# Concatenate the summary and the last `last_chars` characters of the chat history
|
|
151
|
-
return summary + "\n### Recent Chat History\n..." + recent_history
|
|
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
|
|
File without changes
|