sunholo 0.55.14__tar.gz → 0.56.1__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.55.14 → sunholo-0.56.1}/PKG-INFO +5 -3
- {sunholo-0.55.14 → sunholo-0.56.1}/setup.py +9 -2
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/flask/qna_routes.py +10 -22
- sunholo-0.56.1/sunholo/cli/cli.py +12 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/components/llm.py +14 -14
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/logging.py +7 -2
- sunholo-0.56.1/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/utils/config.py +63 -3
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo.egg-info/PKG-INFO +5 -3
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo.egg-info/SOURCES.txt +3 -0
- sunholo-0.56.1/sunholo.egg-info/entry_points.txt +2 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo.egg-info/requires.txt +3 -1
- {sunholo-0.55.14 → sunholo-0.56.1}/LICENSE.txt +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/MANIFEST.in +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/README.md +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/setup.cfg +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/route.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/agents/test_chat_history.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/archive/archive.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/auth/run.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/bots/discord.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/data_to_embed_pubsub.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/images.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.55.14/sunholo/langfuse → sunholo-0.56.1/sunholo/cli}/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/components/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/components/prompt.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/components/retriever.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/database.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/database/uuid.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.55.14/sunholo/llamaindex → sunholo-0.56.1/sunholo/langfuse}/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.55.14/sunholo/lookup → sunholo-0.56.1/sunholo/llamaindex}/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/llamaindex/generate.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.55.14/sunholo/patches → sunholo-0.56.1/sunholo/lookup}/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.55.14/sunholo/patches/langchain → sunholo-0.56.1/sunholo/patches}/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/qna/retry.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo/utils/parsers.py +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.55.14 → sunholo-0.56.1}/test/test_dispatch_to_qa.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.56.1
|
|
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.56.1.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -30,6 +30,7 @@ Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
|
|
|
30
30
|
Requires-Dist: google-cloud-logging; extra == "all"
|
|
31
31
|
Requires-Dist: google-cloud-storage; extra == "all"
|
|
32
32
|
Requires-Dist: google-cloud-pubsub; extra == "all"
|
|
33
|
+
Requires-Dist: gunicorn; extra == "all"
|
|
33
34
|
Requires-Dist: httpcore; extra == "all"
|
|
34
35
|
Requires-Dist: httpx; extra == "all"
|
|
35
36
|
Requires-Dist: lancedb; extra == "all"
|
|
@@ -63,11 +64,12 @@ Requires-Dist: langchain-openai; extra == "openai"
|
|
|
63
64
|
Provides-Extra: anthropic
|
|
64
65
|
Requires-Dist: langchain-anthropic; extra == "anthropic"
|
|
65
66
|
Provides-Extra: http
|
|
66
|
-
Requires-Dist: langfuse; extra == "http"
|
|
67
67
|
Requires-Dist: fastapi; extra == "http"
|
|
68
68
|
Requires-Dist: flask; extra == "http"
|
|
69
|
+
Requires-Dist: gunicorn; extra == "http"
|
|
69
70
|
Requires-Dist: httpcore; extra == "http"
|
|
70
71
|
Requires-Dist: httpx; extra == "http"
|
|
72
|
+
Requires-Dist: langfuse; extra == "http"
|
|
71
73
|
Requires-Dist: python-socketio; extra == "http"
|
|
72
74
|
|
|
73
75
|
## Introduction
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from setuptools import setup, find_packages
|
|
2
2
|
|
|
3
3
|
# Define your base version
|
|
4
|
-
version = '0.
|
|
4
|
+
version = '0.56.1'
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='sunholo',
|
|
@@ -16,6 +16,11 @@ setup(
|
|
|
16
16
|
url = 'https://github.com/sunholo-data/sunholo-py',
|
|
17
17
|
download_url=f'https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v{version}.tar.gz',
|
|
18
18
|
keywords=['llms', 'devops','google_cloud_platform'],
|
|
19
|
+
entry_points={
|
|
20
|
+
'console_scripts': [
|
|
21
|
+
'sunholo=sunholo.cli.cli:main',
|
|
22
|
+
],
|
|
23
|
+
},
|
|
19
24
|
package_data={
|
|
20
25
|
'sunholo.database': ['sql/sb/*.sql'],
|
|
21
26
|
'sunholo.lookup': ['*.yaml']
|
|
@@ -38,6 +43,7 @@ setup(
|
|
|
38
43
|
"google-cloud-logging",
|
|
39
44
|
"google-cloud-storage",
|
|
40
45
|
"google-cloud-pubsub",
|
|
46
|
+
"gunicorn",
|
|
41
47
|
"httpcore",
|
|
42
48
|
"httpx",
|
|
43
49
|
"lancedb",
|
|
@@ -76,11 +82,12 @@ setup(
|
|
|
76
82
|
"langchain-anthropic",
|
|
77
83
|
],
|
|
78
84
|
'http': [
|
|
79
|
-
"langfuse",
|
|
80
85
|
"fastapi",
|
|
81
86
|
"flask",
|
|
87
|
+
"gunicorn",
|
|
82
88
|
"httpcore",
|
|
83
89
|
"httpx",
|
|
90
|
+
"langfuse",
|
|
84
91
|
"python-socketio",
|
|
85
92
|
]
|
|
86
93
|
},
|
|
@@ -23,13 +23,6 @@ from ...streaming import start_streaming_chat
|
|
|
23
23
|
from ...archive import archive_qa
|
|
24
24
|
from ...logging import log
|
|
25
25
|
from ...utils.config import load_config
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
from langfuse import Langfuse
|
|
29
|
-
langfuse = Langfuse()
|
|
30
|
-
except ImportError as err:
|
|
31
|
-
print(f"No langfuse installed for agents.flask.register_qna_routes, install via `pip install sunholo[http]` - {str(err)}")
|
|
32
|
-
langfuse = None
|
|
33
26
|
|
|
34
27
|
try:
|
|
35
28
|
from flask import request, jsonify, Response
|
|
@@ -71,7 +64,7 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
71
64
|
wait_time=all_input["stream_wait_time"],
|
|
72
65
|
timeout=all_input["stream_timeout"],
|
|
73
66
|
#kwargs
|
|
74
|
-
|
|
67
|
+
**all_input["kwargs"]
|
|
75
68
|
):
|
|
76
69
|
if isinstance(chunk, dict) and 'answer' in chunk:
|
|
77
70
|
# When we encounter the dictionary, we yield it as a JSON string
|
|
@@ -98,13 +91,11 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
98
91
|
response = Response(generate_response_content(), content_type='text/plain; charset=utf-8')
|
|
99
92
|
response.headers['Transfer-Encoding'] = 'chunked'
|
|
100
93
|
|
|
94
|
+
log.debug(f"streaming response: {response}")
|
|
101
95
|
if trace:
|
|
102
96
|
generation.end(output=response)
|
|
103
97
|
span.end(output=response)
|
|
104
98
|
trace.update(output=response)
|
|
105
|
-
|
|
106
|
-
if langfuse:
|
|
107
|
-
langfuse.flush()
|
|
108
99
|
|
|
109
100
|
return response
|
|
110
101
|
|
|
@@ -133,7 +124,7 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
133
124
|
question=all_input["user_input"],
|
|
134
125
|
vector_name=vector_name,
|
|
135
126
|
chat_history=all_input["chat_history"],
|
|
136
|
-
|
|
127
|
+
**all_input["kwargs"]
|
|
137
128
|
)
|
|
138
129
|
if generation:
|
|
139
130
|
generation.end(output=bot_output)
|
|
@@ -152,9 +143,6 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
152
143
|
if trace:
|
|
153
144
|
span.end(output=jsonify(bot_output))
|
|
154
145
|
trace.update(output=jsonify(bot_output))
|
|
155
|
-
|
|
156
|
-
if langfuse:
|
|
157
|
-
langfuse.flush()
|
|
158
146
|
|
|
159
147
|
return jsonify(bot_output)
|
|
160
148
|
|
|
@@ -200,18 +188,18 @@ def prep_vac(request, vector_name):
|
|
|
200
188
|
if trace:
|
|
201
189
|
trace.update(input=data, metadata=vac_config)
|
|
202
190
|
|
|
203
|
-
user_input = data
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
191
|
+
user_input = data.pop('user_input').strip()
|
|
192
|
+
stream_wait_time = data.pop('stream_wait_time', 7)
|
|
193
|
+
stream_timeout = data.pop('stream_timeout', 120)
|
|
194
|
+
chat_history = data.pop('chat_history', None)
|
|
195
|
+
paired_messages = extract_chat_history(chat_history)
|
|
207
196
|
|
|
208
|
-
paired_messages = extract_chat_history(data.get('chat_history', None))
|
|
209
197
|
all_input = {'user_input': user_input,
|
|
210
198
|
'vector_name': vector_name,
|
|
211
199
|
'chat_history': paired_messages,
|
|
212
|
-
'message_author': message_author,
|
|
213
200
|
'stream_wait_time': stream_wait_time,
|
|
214
|
-
'stream_timeout':stream_timeout
|
|
201
|
+
'stream_timeout':stream_timeout,
|
|
202
|
+
'kwargs': data}
|
|
215
203
|
|
|
216
204
|
if trace:
|
|
217
205
|
span = trace.span(
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# sunholo/cli/cli.py
|
|
2
|
+
import argparse
|
|
3
|
+
|
|
4
|
+
def main():
|
|
5
|
+
parser = argparse.ArgumentParser(description="sunholo CLI tool.")
|
|
6
|
+
parser.add_argument('--echo', help='Echo the string you use here')
|
|
7
|
+
args = parser.parse_args()
|
|
8
|
+
if args.echo:
|
|
9
|
+
print(args.echo)
|
|
10
|
+
|
|
11
|
+
if __name__ == "__main__":
|
|
12
|
+
main()
|
|
@@ -19,7 +19,7 @@ import os
|
|
|
19
19
|
def pick_llm(vector_name):
|
|
20
20
|
log.debug('Picking llm')
|
|
21
21
|
|
|
22
|
-
llm_str = load_config_key("llm", vector_name,
|
|
22
|
+
llm_str = load_config_key("llm", vector_name, kind="vacConfig")
|
|
23
23
|
|
|
24
24
|
if llm_str == 'openai':
|
|
25
25
|
llm_chat = get_llm_chat(vector_name)
|
|
@@ -49,7 +49,7 @@ def pick_llm(vector_name):
|
|
|
49
49
|
|
|
50
50
|
def pick_streaming(vector_name):
|
|
51
51
|
|
|
52
|
-
llm_str = load_config_key("llm", vector_name,
|
|
52
|
+
llm_str = load_config_key("llm", vector_name, kind="vacConfig")
|
|
53
53
|
|
|
54
54
|
if llm_str == 'openai' or llm_str == 'gemini' or llm_str == 'vertex':
|
|
55
55
|
return True
|
|
@@ -57,7 +57,7 @@ def pick_streaming(vector_name):
|
|
|
57
57
|
return False
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def llm_str_to_llm(llm_str, model=None, vector_name=None
|
|
60
|
+
def llm_str_to_llm(llm_str, model=None, vector_name=None):
|
|
61
61
|
if llm_str == 'openai':
|
|
62
62
|
# Setup for OpenAI LLM
|
|
63
63
|
from langchain_openai import ChatOpenAI
|
|
@@ -79,7 +79,7 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None, config_file="config/ll
|
|
|
79
79
|
|
|
80
80
|
elif llm_str == 'model_garden':
|
|
81
81
|
from ..patches.langchain.vertexai import VertexAIModelGarden
|
|
82
|
-
model_garden_config = load_config_key("gcp_config", vector_name,
|
|
82
|
+
model_garden_config = load_config_key("gcp_config", vector_name, kind="vacConfig")
|
|
83
83
|
if model_garden_config is None:
|
|
84
84
|
raise ValueError("llm='model_garden' requires a gcp_config entry in config yaml file")
|
|
85
85
|
|
|
@@ -97,21 +97,21 @@ def llm_str_to_llm(llm_str, model=None, vector_name=None, config_file="config/ll
|
|
|
97
97
|
if llm_str is None:
|
|
98
98
|
raise NotImplementedError(f'No llm implemented for {llm_str}')
|
|
99
99
|
|
|
100
|
-
def get_llm(vector_name, model=None
|
|
101
|
-
llm_str = load_config_key("llm", vector_name,
|
|
100
|
+
def get_llm(vector_name, model=None):
|
|
101
|
+
llm_str = load_config_key("llm", vector_name, kind="vacConfig")
|
|
102
102
|
#model_lookup_filepath = get_module_filepath("lookup/model_lookup.yaml")
|
|
103
103
|
#model_lookup, _ = load_config(model_lookup_filepath)
|
|
104
104
|
|
|
105
105
|
if not model:
|
|
106
|
-
model = load_config_key("model", vector_name,
|
|
106
|
+
model = load_config_key("model", vector_name, kind="vacConfig")
|
|
107
107
|
|
|
108
108
|
log.debug(f"Chose LLM: {llm_str}")
|
|
109
|
-
return llm_str_to_llm(llm_str, model=model, vector_name=vector_name,
|
|
109
|
+
return llm_str_to_llm(llm_str, model=model, vector_name=vector_name, kind="vacConfig")
|
|
110
110
|
|
|
111
111
|
def get_llm_chat(vector_name, model=None, config_file="config/llm_config.yaml"):
|
|
112
|
-
llm_str = load_config_key("llm", vector_name,
|
|
112
|
+
llm_str = load_config_key("llm", vector_name, kind="vacConfig")
|
|
113
113
|
if not model:
|
|
114
|
-
model = load_config_key("model", vector_name,
|
|
114
|
+
model = load_config_key("model", vector_name, kind="vacConfig")
|
|
115
115
|
|
|
116
116
|
log.debug(f"Chose LLM: {llm_str}")
|
|
117
117
|
# Configure LLMs based on llm_str
|
|
@@ -150,7 +150,7 @@ def get_llm_chat(vector_name, model=None, config_file="config/llm_config.yaml"):
|
|
|
150
150
|
return ChatAnthropic(model_name = model, temperature=0)
|
|
151
151
|
elif llm_str == 'azure':
|
|
152
152
|
from langchain_openai import AzureChatOpenAI
|
|
153
|
-
azure_config = load_config_key("azure", vector_name,
|
|
153
|
+
azure_config = load_config_key("azure", vector_name, kind="vacConfig")
|
|
154
154
|
if not azure_config:
|
|
155
155
|
raise ValueError("Need to configure azure.config if llm='azure'")
|
|
156
156
|
|
|
@@ -195,13 +195,13 @@ def get_llm_chat(vector_name, model=None, config_file="config/llm_config.yaml"):
|
|
|
195
195
|
def get_embeddings(vector_name):
|
|
196
196
|
|
|
197
197
|
llm_str = None
|
|
198
|
-
embed_dict = load_config_key("embedder", vector_name,
|
|
198
|
+
embed_dict = load_config_key("embedder", vector_name, kind="vacConfig")
|
|
199
199
|
|
|
200
200
|
if embed_dict:
|
|
201
201
|
llm_str = embed_dict.get('llm')
|
|
202
202
|
|
|
203
203
|
if llm_str is None:
|
|
204
|
-
llm_str = load_config_key("llm", vector_name,
|
|
204
|
+
llm_str = load_config_key("llm", vector_name, kind="vacConfig")
|
|
205
205
|
|
|
206
206
|
return pick_embedding(llm_str, vector_name=vector_name)
|
|
207
207
|
|
|
@@ -227,7 +227,7 @@ def pick_embedding(llm_str: str, vector_name: str=None):
|
|
|
227
227
|
elif llm_str == 'azure':
|
|
228
228
|
from langchain_openai import AzureOpenAIEmbeddings
|
|
229
229
|
|
|
230
|
-
azure_config = load_config_key("azure", vector_name,
|
|
230
|
+
azure_config = load_config_key("azure", vector_name, kind="vacConfig")
|
|
231
231
|
if not azure_config:
|
|
232
232
|
raise ValueError("Need to configure azure.config if llm='azure'")
|
|
233
233
|
|
|
@@ -220,11 +220,16 @@ def setup_logging(logger_name=None, log_level=logging.INFO, project_id=None):
|
|
|
220
220
|
if logger_name is None:
|
|
221
221
|
logger_name = "sunholo"
|
|
222
222
|
|
|
223
|
-
if Client:
|
|
223
|
+
if Client and os.environ.get('GOOGLE_CLOUD_LOGGING') != "1":
|
|
224
|
+
print("GOOGLE_CLOUD_LOGGING != 1 but authentication with Google Cloud Logging enabled - missing env var setting?")
|
|
225
|
+
|
|
226
|
+
if not Client and os.environ.get('GOOGLE_CLOUD_LOGGING') == "1":
|
|
227
|
+
print("Found GOOGLE_CLOUD_LOGGING=1 but no GCP Client available, install via `pip install sunholo[gcp]` and/or authenticate")
|
|
228
|
+
|
|
229
|
+
if Client and os.environ.get('GOOGLE_CLOUD_LOGGING') == "1":
|
|
224
230
|
# Instantiate the GoogleCloudLogging class
|
|
225
231
|
gc_logger = GoogleCloudLogging(project_id, log_level=log_level, logger_name=logger_name)
|
|
226
232
|
else:
|
|
227
|
-
print("Could not find GoogleCloudLogging Client, install via `pip install sunholo[gcp]`")
|
|
228
233
|
return logger
|
|
229
234
|
|
|
230
235
|
# Setup logging and return the logger instance
|
|
File without changes
|
|
@@ -16,6 +16,7 @@ import os
|
|
|
16
16
|
import json
|
|
17
17
|
import yaml
|
|
18
18
|
from datetime import datetime, timedelta
|
|
19
|
+
from collections import defaultdict
|
|
19
20
|
|
|
20
21
|
try:
|
|
21
22
|
from google.cloud import storage
|
|
@@ -95,6 +96,58 @@ def get_module_filepath(filepath: str):
|
|
|
95
96
|
|
|
96
97
|
# Global cache
|
|
97
98
|
config_cache = {}
|
|
99
|
+
def load_all_configs():
|
|
100
|
+
"""
|
|
101
|
+
Load all configuration files from the specified directory into a dictionary.
|
|
102
|
+
Files are expected to be either YAML or JSON and must contain a 'kind' key at the root.
|
|
103
|
+
Caching is used to avoid reloading files within a 5-minute window.
|
|
104
|
+
"""
|
|
105
|
+
from ..logging import log
|
|
106
|
+
|
|
107
|
+
config_folder = os.getenv("_CONFIG_FOLDER", os.getcwd())
|
|
108
|
+
log.debug(f"Loading all configs from folder: {config_folder}")
|
|
109
|
+
current_time = datetime.now()
|
|
110
|
+
|
|
111
|
+
configs_by_kind = defaultdict(dict)
|
|
112
|
+
for filename in os.listdir(config_folder):
|
|
113
|
+
if filename.endswith(('.yaml', '.yml', '.json')):
|
|
114
|
+
config_file = os.path.join(config_folder, filename)
|
|
115
|
+
|
|
116
|
+
# Check cache first
|
|
117
|
+
if filename in config_cache:
|
|
118
|
+
cached_config, cache_time = config_cache[filename]
|
|
119
|
+
if (current_time - cache_time) < timedelta(minutes=5):
|
|
120
|
+
log.debug(f"Returning cached config for {filename}")
|
|
121
|
+
config = cached_config
|
|
122
|
+
else:
|
|
123
|
+
config = reload_config_file(config_file, filename)
|
|
124
|
+
else:
|
|
125
|
+
config = reload_config_file(config_file, filename)
|
|
126
|
+
|
|
127
|
+
kind = config.get('kind')
|
|
128
|
+
if kind:
|
|
129
|
+
configs_by_kind[kind] = config
|
|
130
|
+
else:
|
|
131
|
+
log.warning(f"No 'kind' found in {filename}")
|
|
132
|
+
|
|
133
|
+
return configs_by_kind
|
|
134
|
+
|
|
135
|
+
def reload_config_file(config_file, filename):
|
|
136
|
+
"""
|
|
137
|
+
Helper function to load a config file and update the cache.
|
|
138
|
+
"""
|
|
139
|
+
from ..logging import log
|
|
140
|
+
with open(config_file, 'r') as file:
|
|
141
|
+
if filename.endswith('.json'):
|
|
142
|
+
config = json.load(file)
|
|
143
|
+
else:
|
|
144
|
+
config = yaml.safe_load(file)
|
|
145
|
+
|
|
146
|
+
config_cache[filename] = (config, datetime.now())
|
|
147
|
+
log.debug(f"Loaded and cached {filename}")
|
|
148
|
+
return config
|
|
149
|
+
|
|
150
|
+
|
|
98
151
|
|
|
99
152
|
def load_config(filename: str=None) -> tuple[dict, str]:
|
|
100
153
|
"""
|
|
@@ -156,14 +209,15 @@ def load_config(filename: str=None) -> tuple[dict, str]:
|
|
|
156
209
|
|
|
157
210
|
return config, filename
|
|
158
211
|
|
|
159
|
-
def load_config_key(key: str, vector_name: str, filename: str=None):
|
|
212
|
+
def load_config_key(key: str, vector_name: str, filename: str=None, kind: str=None):
|
|
160
213
|
"""
|
|
161
214
|
Load a specific key from a configuration file.
|
|
162
215
|
|
|
163
216
|
Args:
|
|
164
217
|
key (str): The key to fetch from the configuration.
|
|
165
218
|
vector_name (str): The name of the vector in the configuration file.
|
|
166
|
-
filename (str, optional): The configuration file name. Defaults to the `_CONFIG_FILE` environment variable.
|
|
219
|
+
filename (str, optional): The configuration file name. Defaults to the `_CONFIG_FILE` environment variable. Deprecated - use 'kind' instead
|
|
220
|
+
kind: (str, optional): Specify the type of configuration to retrieve e.g. 'vacConfig' which will pick from files within `_CONFIG_FOLDER`
|
|
167
221
|
|
|
168
222
|
Returns:
|
|
169
223
|
str: The value associated with the specified key.
|
|
@@ -179,7 +233,13 @@ def load_config_key(key: str, vector_name: str, filename: str=None):
|
|
|
179
233
|
assert isinstance(key, str), f"key must be a string got a {type(key)}"
|
|
180
234
|
assert isinstance(vector_name, str), f"vector_name must be a string, got a {type(vector_name)}"
|
|
181
235
|
|
|
182
|
-
|
|
236
|
+
configs_by_kind = load_all_configs()
|
|
237
|
+
if kind and configs_by_kind.get(kind):
|
|
238
|
+
config = configs_by_kind[kind]
|
|
239
|
+
filename = kind
|
|
240
|
+
else:
|
|
241
|
+
config, filename = load_config(filename)
|
|
242
|
+
|
|
183
243
|
log.info(f"Fetching {key} for {vector_name}")
|
|
184
244
|
apiVersion = config.get('apiVersion')
|
|
185
245
|
kind = config.get('kind')
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.56.1
|
|
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.56.1.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -30,6 +30,7 @@ Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
|
|
|
30
30
|
Requires-Dist: google-cloud-logging; extra == "all"
|
|
31
31
|
Requires-Dist: google-cloud-storage; extra == "all"
|
|
32
32
|
Requires-Dist: google-cloud-pubsub; extra == "all"
|
|
33
|
+
Requires-Dist: gunicorn; extra == "all"
|
|
33
34
|
Requires-Dist: httpcore; extra == "all"
|
|
34
35
|
Requires-Dist: httpx; extra == "all"
|
|
35
36
|
Requires-Dist: lancedb; extra == "all"
|
|
@@ -63,11 +64,12 @@ Requires-Dist: langchain-openai; extra == "openai"
|
|
|
63
64
|
Provides-Extra: anthropic
|
|
64
65
|
Requires-Dist: langchain-anthropic; extra == "anthropic"
|
|
65
66
|
Provides-Extra: http
|
|
66
|
-
Requires-Dist: langfuse; extra == "http"
|
|
67
67
|
Requires-Dist: fastapi; extra == "http"
|
|
68
68
|
Requires-Dist: flask; extra == "http"
|
|
69
|
+
Requires-Dist: gunicorn; extra == "http"
|
|
69
70
|
Requires-Dist: httpcore; extra == "http"
|
|
70
71
|
Requires-Dist: httpx; extra == "http"
|
|
72
|
+
Requires-Dist: langfuse; extra == "http"
|
|
71
73
|
Requires-Dist: python-socketio; extra == "http"
|
|
72
74
|
|
|
73
75
|
## Introduction
|
|
@@ -8,6 +8,7 @@ sunholo/logging.py
|
|
|
8
8
|
sunholo.egg-info/PKG-INFO
|
|
9
9
|
sunholo.egg-info/SOURCES.txt
|
|
10
10
|
sunholo.egg-info/dependency_links.txt
|
|
11
|
+
sunholo.egg-info/entry_points.txt
|
|
11
12
|
sunholo.egg-info/requires.txt
|
|
12
13
|
sunholo.egg-info/top_level.txt
|
|
13
14
|
sunholo/agents/__init__.py
|
|
@@ -40,6 +41,8 @@ sunholo/chunker/message_data.py
|
|
|
40
41
|
sunholo/chunker/pdfs.py
|
|
41
42
|
sunholo/chunker/publish.py
|
|
42
43
|
sunholo/chunker/splitter.py
|
|
44
|
+
sunholo/cli/__init__.py
|
|
45
|
+
sunholo/cli/cli.py
|
|
43
46
|
sunholo/components/__init__.py
|
|
44
47
|
sunholo/components/llm.py
|
|
45
48
|
sunholo/components/prompt.py
|
|
@@ -11,6 +11,7 @@ google-cloud-alloydb-connector[pg8000]
|
|
|
11
11
|
google-cloud-logging
|
|
12
12
|
google-cloud-storage
|
|
13
13
|
google-cloud-pubsub
|
|
14
|
+
gunicorn
|
|
14
15
|
httpcore
|
|
15
16
|
httpx
|
|
16
17
|
lancedb
|
|
@@ -46,11 +47,12 @@ google-api-python-client
|
|
|
46
47
|
google-cloud-alloydb-connector[pg8000]
|
|
47
48
|
|
|
48
49
|
[http]
|
|
49
|
-
langfuse
|
|
50
50
|
fastapi
|
|
51
51
|
flask
|
|
52
|
+
gunicorn
|
|
52
53
|
httpcore
|
|
53
54
|
httpx
|
|
55
|
+
langfuse
|
|
54
56
|
python-socketio
|
|
55
57
|
|
|
56
58
|
[openai]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|