sunholo 0.60.1__py3-none-any.whl → 0.60.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sunholo/__init__.py +3 -0
- sunholo/agents/dispatch_to_qa.py +1 -1
- sunholo/agents/flask/qna_routes.py +4 -0
- sunholo/cli/chat_vac.py +75 -44
- sunholo/cli/cli.py +35 -2
- sunholo/cli/run_proxy.py +119 -12
- sunholo/cli/sun_rich.py +3 -0
- sunholo/components/retriever.py +2 -1
- sunholo/components/vectorstore.py +27 -19
- sunholo/gcs/download_url.py +1 -1
- sunholo/logging.py +8 -6
- sunholo/utils/config.py +15 -11
- sunholo/utils/user_ids.py +2 -31
- {sunholo-0.60.1.dist-info → sunholo-0.60.3.dist-info}/METADATA +10 -6
- {sunholo-0.60.1.dist-info → sunholo-0.60.3.dist-info}/RECORD +19 -18
- {sunholo-0.60.1.dist-info → sunholo-0.60.3.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.60.1.dist-info → sunholo-0.60.3.dist-info}/WHEEL +0 -0
- {sunholo-0.60.1.dist-info → sunholo-0.60.3.dist-info}/entry_points.txt +0 -0
- {sunholo-0.60.1.dist-info → sunholo-0.60.3.dist-info}/top_level.txt +0 -0
sunholo/__init__.py
CHANGED
sunholo/agents/dispatch_to_qa.py
CHANGED
|
@@ -52,7 +52,7 @@ def prep_request_payload(user_input, chat_history, vector_name, stream, **kwargs
|
|
|
52
52
|
agent = load_config_key("agent", vector_name=vector_name, kind="vacConfig")
|
|
53
53
|
agent_type = load_config_key("agent_type", vector_name=vector_name, kind="vacConfig")
|
|
54
54
|
|
|
55
|
-
override_endpoint = kwargs.get("
|
|
55
|
+
override_endpoint = kwargs.get("override_endpoint")
|
|
56
56
|
if override_endpoint:
|
|
57
57
|
log.info(f"Overriding endpoint with {override_endpoint}")
|
|
58
58
|
|
|
@@ -37,6 +37,10 @@ except ImportError as err:
|
|
|
37
37
|
|
|
38
38
|
def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
39
39
|
|
|
40
|
+
@app.route("/")
|
|
41
|
+
def home():
|
|
42
|
+
return jsonify("OK")
|
|
43
|
+
|
|
40
44
|
@app.route('/vac/streaming/<vector_name>', methods=['POST'])
|
|
41
45
|
@observe()
|
|
42
46
|
def stream_qa(vector_name):
|
sunholo/cli/chat_vac.py
CHANGED
|
@@ -1,38 +1,46 @@
|
|
|
1
|
-
from ..agents import
|
|
2
|
-
from ..streaming import
|
|
3
|
-
from ..utils.user_ids import
|
|
1
|
+
from ..agents import send_to_qa
|
|
2
|
+
from ..streaming import generate_proxy_stream
|
|
3
|
+
from ..utils.user_ids import generate_user_id
|
|
4
|
+
from ..utils.config import load_config_key
|
|
4
5
|
|
|
5
|
-
from .run_proxy import
|
|
6
|
+
from .run_proxy import clean_proxy_list, start_proxy
|
|
6
7
|
|
|
7
8
|
import uuid
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
from rich import print
|
|
11
|
+
from .sun_rich import console
|
|
12
|
+
|
|
13
|
+
from rich.prompt import Prompt
|
|
14
|
+
from rich.panel import Panel
|
|
15
|
+
from rich.text import Text
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_service_url(service_name, project, region):
|
|
19
|
+
proxies = clean_proxy_list()
|
|
11
20
|
if service_name in proxies:
|
|
12
21
|
port = proxies[service_name]['port']
|
|
13
22
|
return f"http://127.0.0.1:{port}"
|
|
14
23
|
else:
|
|
15
24
|
print(f"No proxy found running for service: {service_name} - attempting to connect")
|
|
16
|
-
return start_proxy(service_name)
|
|
25
|
+
return start_proxy(service_name, region, project)
|
|
17
26
|
|
|
18
|
-
|
|
27
|
+
def stream_chat_session(service_name, project, region):
|
|
19
28
|
|
|
20
|
-
service_url = get_service_url(service_name)
|
|
21
|
-
user_id =
|
|
29
|
+
service_url = get_service_url(service_name, project, region)
|
|
30
|
+
user_id = generate_user_id()
|
|
31
|
+
chat_history = []
|
|
22
32
|
while True:
|
|
23
33
|
session_id = str(uuid.uuid4())
|
|
24
|
-
user_input =
|
|
34
|
+
user_input = Prompt.ask("[bold cyan]You[/bold cyan]")
|
|
25
35
|
if user_input.lower() in ["exit", "quit"]:
|
|
26
|
-
print("Exiting chat session.")
|
|
36
|
+
console.print("[bold red]Exiting chat session.[/bold red]")
|
|
27
37
|
break
|
|
28
38
|
|
|
29
|
-
chat_history.append({"role": "
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
chat_history.append({"role": "Human", "content": user_input})
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
generate =
|
|
35
|
-
|
|
41
|
+
def stream_response():
|
|
42
|
+
generate = generate_proxy_stream(
|
|
43
|
+
send_to_qa,
|
|
36
44
|
user_input,
|
|
37
45
|
vector_name=service_name,
|
|
38
46
|
chat_history=chat_history,
|
|
@@ -56,28 +64,40 @@ async def stream_chat_session(service_name, chat_history):
|
|
|
56
64
|
message_source="cli",
|
|
57
65
|
override_endpoint=service_url
|
|
58
66
|
)
|
|
59
|
-
|
|
67
|
+
for part in generate():
|
|
60
68
|
yield part
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if isinstance(token, bytes):
|
|
65
|
-
token = token.decode('utf-8')
|
|
66
|
-
print(token, end='', flush=True)
|
|
70
|
+
response_started = False
|
|
71
|
+
vac_response = ""
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
# point or star?
|
|
74
|
+
with console.status("[bold orange]Thinking...[/bold orange]", spinner="star") as status:
|
|
75
|
+
for token in stream_response():
|
|
76
|
+
if not response_started:
|
|
77
|
+
status.stop()
|
|
78
|
+
console.print(f"[bold yellow]{service_name}:[/bold yellow] ", end='')
|
|
79
|
+
response_started = True
|
|
70
80
|
|
|
71
|
-
|
|
81
|
+
if isinstance(token, bytes):
|
|
82
|
+
token = token.decode('utf-8')
|
|
83
|
+
console.print(token, end='')
|
|
84
|
+
vac_response += token
|
|
85
|
+
|
|
86
|
+
chat_history.append({"role": "AI", "content": vac_response})
|
|
87
|
+
response_started = False
|
|
88
|
+
console.print()
|
|
89
|
+
console.rule()
|
|
90
|
+
|
|
91
|
+
def headless_mode(service_name, user_input, project, region, chat_history=None):
|
|
72
92
|
chat_history = chat_history or []
|
|
73
|
-
chat_history.append({"role": "
|
|
74
|
-
service_url = get_service_url(
|
|
75
|
-
user_id =
|
|
93
|
+
chat_history.append({"role": "Human", "content": user_input})
|
|
94
|
+
service_url = get_service_url(project, region)
|
|
95
|
+
user_id = generate_user_id()
|
|
76
96
|
session_id = str(uuid.uuid4())
|
|
77
97
|
|
|
78
|
-
|
|
79
|
-
generate =
|
|
80
|
-
|
|
98
|
+
def stream_response():
|
|
99
|
+
generate = generate_proxy_stream(
|
|
100
|
+
send_to_qa,
|
|
81
101
|
user_input,
|
|
82
102
|
vector_name=service_name,
|
|
83
103
|
chat_history=chat_history,
|
|
@@ -101,30 +121,41 @@ async def headless_mode(service_name, user_input, chat_history=None):
|
|
|
101
121
|
message_source="cli",
|
|
102
122
|
override_endpoint=service_url
|
|
103
123
|
)
|
|
104
|
-
|
|
124
|
+
for part in generate():
|
|
105
125
|
yield part
|
|
106
126
|
|
|
107
|
-
print("
|
|
108
|
-
|
|
127
|
+
print(f"VAC {service_name}: ", end='', flush=True)
|
|
128
|
+
for token in stream_response():
|
|
109
129
|
if isinstance(token, bytes):
|
|
110
130
|
token = token.decode('utf-8')
|
|
111
131
|
print(token, end='', flush=True)
|
|
112
132
|
|
|
113
|
-
chat_history.append({"role": "
|
|
133
|
+
chat_history.append({"role": "AI", "content": token})
|
|
114
134
|
print() # For new line after streaming ends
|
|
115
135
|
|
|
136
|
+
return chat_history
|
|
137
|
+
|
|
116
138
|
|
|
117
139
|
def vac_command(args):
|
|
118
140
|
try:
|
|
119
|
-
service_url = get_service_url(args.service_name)
|
|
141
|
+
service_url = get_service_url(args.service_name, args.project, args.region)
|
|
120
142
|
except ValueError as e:
|
|
121
|
-
print(e)
|
|
143
|
+
console.print(f"[bold red]ERROR: Could not start {args.service_name} proxy URL: {str(e)}[/bold red]")
|
|
122
144
|
return
|
|
123
|
-
|
|
145
|
+
|
|
146
|
+
display_name = load_config_key("display_name", vector_name=args.service_name, kind="vacConfig")
|
|
147
|
+
description = load_config_key("description", vector_name=args.service_name, kind="vacConfig")
|
|
148
|
+
|
|
149
|
+
print(
|
|
150
|
+
Panel(description or "Starting VAC chat session",
|
|
151
|
+
title=display_name or args.service_name,
|
|
152
|
+
subtitle=service_url)
|
|
153
|
+
)
|
|
154
|
+
|
|
124
155
|
if args.headless:
|
|
125
|
-
headless_mode(
|
|
156
|
+
headless_mode(args.service_name, args.user_input, args.project, args.region, args.chat_history)
|
|
126
157
|
else:
|
|
127
|
-
stream_chat_session(
|
|
158
|
+
stream_chat_session(args.service_name, args.project, args.region)
|
|
128
159
|
|
|
129
160
|
def setup_vac_subparser(subparsers):
|
|
130
161
|
"""
|
|
@@ -133,9 +164,9 @@ def setup_vac_subparser(subparsers):
|
|
|
133
164
|
Args:
|
|
134
165
|
subparsers: The subparsers object from argparse.ArgumentParser().
|
|
135
166
|
"""
|
|
136
|
-
vac_parser = subparsers.add_parser('vac', help='Interact with
|
|
167
|
+
vac_parser = subparsers.add_parser('vac', help='Interact with deployed VAC services.')
|
|
137
168
|
vac_parser.add_argument('service_name', help='Name of the VAC service.')
|
|
138
|
-
vac_parser.add_argument('user_input', help='User input for the VAC service.', nargs='?', default=None)
|
|
169
|
+
vac_parser.add_argument('user_input', help='User input for the VAC service when in headless mode.', nargs='?', default=None)
|
|
139
170
|
vac_parser.add_argument('--headless', action='store_true', help='Run in headless mode.')
|
|
140
171
|
vac_parser.add_argument('--chat_history', help='Chat history for headless mode (as JSON string).', default=None)
|
|
141
172
|
vac_parser.set_defaults(func=vac_command)
|
sunholo/cli/cli.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import logging
|
|
2
3
|
|
|
3
4
|
from .configs import setup_list_configs_subparser
|
|
4
5
|
from .deploy import setup_deploy_subparser
|
|
@@ -6,19 +7,44 @@ from .cli_init import setup_init_subparser
|
|
|
6
7
|
from .merge_texts import setup_merge_text_subparser
|
|
7
8
|
from .run_proxy import setup_proxy_subparser
|
|
8
9
|
from .chat_vac import setup_vac_subparser
|
|
10
|
+
from ..utils.config import load_config_key
|
|
9
11
|
|
|
12
|
+
from ..logging import log
|
|
13
|
+
|
|
14
|
+
from rich import print
|
|
15
|
+
from rich.console import Console
|
|
16
|
+
from rich.prompt import Prompt
|
|
17
|
+
from rich.spinner import Spinner
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
from rich.text import Text
|
|
20
|
+
console = Console()
|
|
21
|
+
|
|
22
|
+
def load_default_gcp_config():
|
|
23
|
+
gcp_config = load_config_key('gcp_config', 'global', kind="vacConfig")
|
|
24
|
+
if gcp_config:
|
|
25
|
+
return gcp_config.get('project_id', ''), gcp_config.get('location', 'europe-west1')
|
|
26
|
+
else:
|
|
27
|
+
return '', 'europe-west1'
|
|
10
28
|
|
|
11
29
|
def main(args=None):
|
|
30
|
+
|
|
31
|
+
|
|
12
32
|
"""
|
|
13
33
|
Entry point for the sunholo console script. This function parses command line arguments
|
|
14
34
|
and invokes the appropriate functionality based on the user input.
|
|
15
35
|
|
|
16
|
-
|
|
36
|
+
Get started:
|
|
17
37
|
```bash
|
|
18
|
-
sunholo
|
|
38
|
+
sunholo --help
|
|
19
39
|
```
|
|
20
40
|
"""
|
|
41
|
+
default_project, default_region = load_default_gcp_config()
|
|
42
|
+
|
|
21
43
|
parser = argparse.ArgumentParser(description="sunholo CLI tool for deploying GenAI VACs")
|
|
44
|
+
parser.add_argument('--debug', action='store_true', help='Enable debug output')
|
|
45
|
+
parser.add_argument('--project', default=default_project, help='GCP project to list Cloud Run services from.')
|
|
46
|
+
parser.add_argument('--region', default=default_region, help='Region to list Cloud Run services from.')
|
|
47
|
+
|
|
22
48
|
subparsers = parser.add_subparsers(title='commands',
|
|
23
49
|
description='Valid commands',
|
|
24
50
|
help='Commands',
|
|
@@ -40,6 +66,13 @@ def main(args=None):
|
|
|
40
66
|
|
|
41
67
|
args = parser.parse_args(args)
|
|
42
68
|
|
|
69
|
+
if args.debug:
|
|
70
|
+
log.setLevel(logging.INFO)
|
|
71
|
+
logging.getLogger().setLevel(logging.INFO)
|
|
72
|
+
else:
|
|
73
|
+
log.setLevel(logging.WARNING)
|
|
74
|
+
logging.getLogger().setLevel(logging.WARNING)
|
|
75
|
+
|
|
43
76
|
if hasattr(args, 'func'):
|
|
44
77
|
args.func(args)
|
|
45
78
|
else:
|
sunholo/cli/run_proxy.py
CHANGED
|
@@ -3,6 +3,10 @@ import os
|
|
|
3
3
|
import signal
|
|
4
4
|
import json
|
|
5
5
|
|
|
6
|
+
from .sun_rich import console
|
|
7
|
+
from rich.table import Table
|
|
8
|
+
from rich import print
|
|
9
|
+
|
|
6
10
|
PROXY_TRACKER_FILE = '.vac_proxy_tracker.json'
|
|
7
11
|
DEFAULT_PORT = 8080
|
|
8
12
|
|
|
@@ -46,13 +50,13 @@ def check_gcloud():
|
|
|
46
50
|
"""
|
|
47
51
|
try:
|
|
48
52
|
# Check if gcloud is installed
|
|
49
|
-
result = subprocess.run(["gcloud", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
53
|
+
result = subprocess.run(["gcloud", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30)
|
|
50
54
|
if result.returncode != 0:
|
|
51
55
|
print("ERROR: gcloud is not installed or not found in PATH.")
|
|
52
56
|
return False
|
|
53
57
|
|
|
54
58
|
# Check if gcloud is authenticated
|
|
55
|
-
result = subprocess.run(["gcloud", "auth", "list"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
59
|
+
result = subprocess.run(["gcloud", "auth", "list"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30)
|
|
56
60
|
if result.returncode != 0 or "ACTIVE" not in result.stdout.decode():
|
|
57
61
|
print("ERROR: gcloud is not authenticated. Please run 'gcloud auth login'.")
|
|
58
62
|
return False
|
|
@@ -63,16 +67,35 @@ def check_gcloud():
|
|
|
63
67
|
print(f"ERROR: An unexpected error occurred: {e}")
|
|
64
68
|
return False
|
|
65
69
|
|
|
70
|
+
def is_process_running(pid):
|
|
71
|
+
try:
|
|
72
|
+
os.kill(pid, 0)
|
|
73
|
+
return True
|
|
74
|
+
except OSError:
|
|
75
|
+
print("WARNING: VAC Proxy lost connection")
|
|
76
|
+
return False
|
|
77
|
+
|
|
66
78
|
def load_proxies():
|
|
67
79
|
if os.path.exists(PROXY_TRACKER_FILE):
|
|
68
80
|
with open(PROXY_TRACKER_FILE, 'r') as file:
|
|
69
81
|
return json.load(file)
|
|
70
82
|
return {}
|
|
71
83
|
|
|
84
|
+
def clean_proxy_list():
|
|
85
|
+
proxies = load_proxies()
|
|
86
|
+
updated_proxies = {k: v for k, v in proxies.items() if is_process_running(v["pid"])}
|
|
87
|
+
if len(proxies) != len(updated_proxies):
|
|
88
|
+
save_proxies(updated_proxies)
|
|
89
|
+
|
|
90
|
+
return updated_proxies
|
|
91
|
+
|
|
72
92
|
def save_proxies(proxies):
|
|
73
93
|
with open(PROXY_TRACKER_FILE, 'w') as file:
|
|
74
94
|
json.dump(proxies, file, indent=4)
|
|
75
95
|
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
76
99
|
def start_proxy(service_name, region, project, port=None):
|
|
77
100
|
"""
|
|
78
101
|
Starts the gcloud proxy to the Cloud Run service and stores the PID.
|
|
@@ -83,7 +106,7 @@ def start_proxy(service_name, region, project, port=None):
|
|
|
83
106
|
project (str): GCP project of the Cloud Run service.
|
|
84
107
|
port (int, optional): Port to run the proxy on. If not provided, auto-assigns the next available port.
|
|
85
108
|
"""
|
|
86
|
-
proxies =
|
|
109
|
+
proxies = clean_proxy_list()
|
|
87
110
|
|
|
88
111
|
if service_name in proxies:
|
|
89
112
|
print(f"Proxy for service {service_name} is already running on port {proxies[service_name]['port']}.")
|
|
@@ -109,7 +132,7 @@ def start_proxy(service_name, region, project, port=None):
|
|
|
109
132
|
|
|
110
133
|
print(f"Proxy for {service_name} setup complete on port {port}")
|
|
111
134
|
list_proxies()
|
|
112
|
-
|
|
135
|
+
|
|
113
136
|
return f"http://127.0.0.1:{port}"
|
|
114
137
|
|
|
115
138
|
|
|
@@ -120,7 +143,7 @@ def stop_proxy(service_name):
|
|
|
120
143
|
Args:
|
|
121
144
|
service_name (str): Name of the Cloud Run service.
|
|
122
145
|
"""
|
|
123
|
-
proxies =
|
|
146
|
+
proxies = clean_proxy_list()
|
|
124
147
|
|
|
125
148
|
if service_name not in proxies:
|
|
126
149
|
print(f"No proxy found for service: {service_name}")
|
|
@@ -139,20 +162,99 @@ def stop_proxy(service_name):
|
|
|
139
162
|
|
|
140
163
|
list_proxies()
|
|
141
164
|
|
|
165
|
+
def stop_all_proxies():
|
|
166
|
+
"""
|
|
167
|
+
Stops all running gcloud proxies.
|
|
168
|
+
"""
|
|
169
|
+
proxies = clean_proxy_list()
|
|
170
|
+
|
|
171
|
+
for service_name, info in proxies.items():
|
|
172
|
+
pid = info["pid"]
|
|
173
|
+
try:
|
|
174
|
+
os.kill(pid, signal.SIGTERM)
|
|
175
|
+
print(f"Proxy for {service_name} stopped.")
|
|
176
|
+
except ProcessLookupError:
|
|
177
|
+
print(f"No process found with PID: {pid}")
|
|
178
|
+
except Exception as e:
|
|
179
|
+
print(f"Error stopping proxy for {service_name}: {e}")
|
|
180
|
+
|
|
181
|
+
save_proxies({})
|
|
182
|
+
|
|
183
|
+
list_proxies()
|
|
184
|
+
|
|
185
|
+
def list_cloud_run_services(project, region):
|
|
186
|
+
"""
|
|
187
|
+
Lists all Cloud Run services the user has access to in a specific project and region.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
project (str): The GCP project ID.
|
|
191
|
+
region (str): The region of the Cloud Run services.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
# point or star?
|
|
195
|
+
with console.status("[bold orange]Listing Cloud Run Services[/bold orange]", spinner="star") as status:
|
|
196
|
+
try:
|
|
197
|
+
result = subprocess.run(
|
|
198
|
+
["gcloud", "run", "services", "list", "--project", project, "--region", region, "--format=json"],
|
|
199
|
+
stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=30
|
|
200
|
+
)
|
|
201
|
+
if result.returncode != 0:
|
|
202
|
+
status.stop()
|
|
203
|
+
console.print(f"[bold red]ERROR: Unable to list Cloud Run services: {result.stderr.decode()}[/bold red]")
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
services = json.loads(result.stdout.decode())
|
|
207
|
+
if not services:
|
|
208
|
+
status.stop()
|
|
209
|
+
console.print("[bold red]No Cloud Run services found.[/bold red]")
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
proxies = clean_proxy_list()
|
|
213
|
+
status.stop()
|
|
214
|
+
|
|
215
|
+
table = Table(title="VAC Cloud Run Services")
|
|
216
|
+
table.add_column("Service Name")
|
|
217
|
+
table.add_column("Region")
|
|
218
|
+
table.add_column("URL")
|
|
219
|
+
table.add_column("Proxied")
|
|
220
|
+
table.add_column("Port")
|
|
221
|
+
|
|
222
|
+
for service in services:
|
|
223
|
+
service_name = service['metadata']['name']
|
|
224
|
+
service_url = service['status']['url']
|
|
225
|
+
if service_name in proxies:
|
|
226
|
+
proxied = "Yes"
|
|
227
|
+
proxy_port = proxies[service_name]['port']
|
|
228
|
+
else:
|
|
229
|
+
proxied = "No"
|
|
230
|
+
proxy_port = "-"
|
|
231
|
+
table.add_row(service_name, region, service_url, proxied, str(proxy_port))
|
|
232
|
+
|
|
233
|
+
console.print(table)
|
|
234
|
+
except Exception as e:
|
|
235
|
+
status.stop()
|
|
236
|
+
console.print(f"[bold red]ERROR: An unexpected error occurred: {e}[/bold red]")
|
|
237
|
+
|
|
142
238
|
def list_proxies():
|
|
143
239
|
"""
|
|
144
240
|
Lists all running proxies.
|
|
145
241
|
"""
|
|
146
|
-
|
|
242
|
+
print("Listing Proxies...")
|
|
243
|
+
proxies = clean_proxy_list()
|
|
147
244
|
if not proxies:
|
|
148
245
|
print("No proxies currently running.")
|
|
149
246
|
else:
|
|
150
|
-
|
|
247
|
+
table = Table(title="VAC Proxies")
|
|
248
|
+
table.add_column("VAC")
|
|
249
|
+
table.add_column("Port")
|
|
250
|
+
table.add_column("PID")
|
|
251
|
+
table.add_column("URL")
|
|
252
|
+
|
|
151
253
|
for service_name, info in proxies.items():
|
|
152
254
|
url = f"http://127.0.0.1:{info['port']}"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
255
|
+
table.add_row(service_name, str(info['port']), str(info['pid']), url)
|
|
256
|
+
|
|
257
|
+
console.print(table)
|
|
156
258
|
|
|
157
259
|
def setup_proxy_subparser(subparsers):
|
|
158
260
|
"""
|
|
@@ -161,13 +263,12 @@ def setup_proxy_subparser(subparsers):
|
|
|
161
263
|
Args:
|
|
162
264
|
subparsers: The subparsers object from argparse.ArgumentParser().
|
|
163
265
|
"""
|
|
266
|
+
|
|
164
267
|
proxy_parser = subparsers.add_parser('proxy', help='Set up or stop a proxy to the Cloud Run service.')
|
|
165
268
|
proxy_subparsers = proxy_parser.add_subparsers(dest='proxy_command', required=True)
|
|
166
269
|
|
|
167
270
|
start_parser = proxy_subparsers.add_parser('start', help='Start the proxy to the Cloud Run service.')
|
|
168
271
|
start_parser.add_argument('service_name', help='Name of the Cloud Run service.')
|
|
169
|
-
start_parser.add_argument('--region', default='europe-west1', help='Region of the Cloud Run service.')
|
|
170
|
-
start_parser.add_argument('--project', default='multivac-internal-dev', help='GCP project of the Cloud Run service.')
|
|
171
272
|
start_parser.add_argument('--port', type=int, help='Port to run the proxy on. Auto-assigns if not provided.')
|
|
172
273
|
start_parser.set_defaults(func=lambda args: start_proxy(args.service_name, args.region, args.project, args.port))
|
|
173
274
|
|
|
@@ -178,4 +279,10 @@ def setup_proxy_subparser(subparsers):
|
|
|
178
279
|
list_parser = proxy_subparsers.add_parser('list', help='List all running proxies.')
|
|
179
280
|
list_parser.set_defaults(func=lambda args: list_proxies())
|
|
180
281
|
|
|
282
|
+
stop_all_parser = proxy_subparsers.add_parser('stop-all', help='Stop all running proxies.')
|
|
283
|
+
stop_all_parser.set_defaults(func=lambda args: stop_all_proxies())
|
|
284
|
+
|
|
285
|
+
list_services_parser = proxy_subparsers.add_parser('list-vacs', help='List all Cloud Run VAC services.')
|
|
286
|
+
list_services_parser.set_defaults(func=lambda args: list_cloud_run_services(args.project, args.region))
|
|
287
|
+
|
|
181
288
|
|
sunholo/cli/sun_rich.py
ADDED
sunholo/components/retriever.py
CHANGED
|
@@ -48,7 +48,8 @@ def pick_retriever(vector_name, embeddings=None):
|
|
|
48
48
|
log.info(f"Found vectorstore {vectorstore}")
|
|
49
49
|
if embeddings is None:
|
|
50
50
|
embeddings = get_embeddings(vector_name)
|
|
51
|
-
|
|
51
|
+
read_only = value.get('readonly')
|
|
52
|
+
vectorstore = pick_vectorstore(vectorstore, vector_name=vector_name, embeddings=embeddings, read_only=read_only)
|
|
52
53
|
k_override = value.get('k', 3)
|
|
53
54
|
vs_retriever = vectorstore.as_retriever(search_kwargs=dict(k=k_override))
|
|
54
55
|
retriever_list.append(vs_retriever)
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import os
|
|
15
15
|
from ..logging import log
|
|
16
16
|
|
|
17
|
-
def pick_vectorstore(vs_str, vector_name, embeddings):
|
|
17
|
+
def pick_vectorstore(vs_str, vector_name, embeddings, read_only=None):
|
|
18
18
|
log.debug('Picking vectorstore')
|
|
19
19
|
|
|
20
20
|
if vs_str == 'supabase':
|
|
@@ -23,8 +23,9 @@ def pick_vectorstore(vs_str, vector_name, embeddings):
|
|
|
23
23
|
|
|
24
24
|
from ..database.database import setup_supabase
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
if not read_only:
|
|
27
|
+
log.debug(f"Initiating Supabase store: {vector_name}")
|
|
28
|
+
setup_supabase(vector_name)
|
|
28
29
|
|
|
29
30
|
# init embedding and vector store
|
|
30
31
|
supabase_url = os.getenv('SUPABASE_URL')
|
|
@@ -70,10 +71,14 @@ def pick_vectorstore(vs_str, vector_name, embeddings):
|
|
|
70
71
|
elif vs_str == 'alloydb':
|
|
71
72
|
from langchain_google_alloydb_pg import AlloyDBVectorStore
|
|
72
73
|
from ..database.alloydb import create_alloydb_table, create_alloydb_engine
|
|
74
|
+
from ..database.database import get_vector_size
|
|
73
75
|
|
|
76
|
+
vector_size = get_vector_size(vector_name)
|
|
74
77
|
engine = create_alloydb_engine(vector_name)
|
|
75
78
|
|
|
76
|
-
table_name =
|
|
79
|
+
table_name = f"{vector_name}_vectorstore_{vector_size}"
|
|
80
|
+
if not read_only:
|
|
81
|
+
table_name = create_alloydb_table(vector_name, engine)
|
|
77
82
|
|
|
78
83
|
log.info(f"Chose AlloyDB with table name {table_name}")
|
|
79
84
|
vectorstore = AlloyDBVectorStore.create_sync(
|
|
@@ -106,21 +111,24 @@ def pick_vectorstore(vs_str, vector_name, embeddings):
|
|
|
106
111
|
try:
|
|
107
112
|
table = db.open_table(vector_name)
|
|
108
113
|
except FileNotFoundError as err:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
114
|
+
if not read_only:
|
|
115
|
+
log.info(f"{err} - Could not open table for {vector_name} - creating new table")
|
|
116
|
+
init = f"Creating new table for {vector_name}"
|
|
117
|
+
table = db.create_table(
|
|
118
|
+
vector_name,
|
|
119
|
+
data=[
|
|
120
|
+
{
|
|
121
|
+
"vector": embeddings.embed_query(init),
|
|
122
|
+
"text": init,
|
|
123
|
+
"id": "1",
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
mode="overwrite",
|
|
127
|
+
)
|
|
128
|
+
else:
|
|
129
|
+
log.info(f"{err} - Could not create table for {vector_name} as read_only=True")
|
|
130
|
+
|
|
131
|
+
log.info(f"Initiating LanceDB object for {vector_name} using {LANCEDB_BUCKET}")
|
|
124
132
|
vectorstore = LanceDB(
|
|
125
133
|
connection=table,
|
|
126
134
|
embedding=embeddings,
|
sunholo/gcs/download_url.py
CHANGED
|
@@ -29,7 +29,7 @@ if is_running_on_gcp():
|
|
|
29
29
|
|
|
30
30
|
def refresh_credentials():
|
|
31
31
|
if not is_running_on_gcp():
|
|
32
|
-
log.
|
|
32
|
+
log.debug("Not running on Google Cloud so no credentials available for GCS.")
|
|
33
33
|
return False
|
|
34
34
|
if not gcs_credentials.token or gcs_credentials.expired or not gcs_credentials.valid:
|
|
35
35
|
try:
|
sunholo/logging.py
CHANGED
|
@@ -217,9 +217,6 @@ def setup_logging(logger_name=None, log_level=logging.INFO, project_id=None):
|
|
|
217
217
|
if logger_name is None:
|
|
218
218
|
logger_name = "sunholo"
|
|
219
219
|
|
|
220
|
-
if Client and os.environ.get('GOOGLE_CLOUD_LOGGING') != "1":
|
|
221
|
-
print("GOOGLE_CLOUD_LOGGING != 1 but authentication with Google Cloud Logging enabled - missing env var setting?")
|
|
222
|
-
|
|
223
220
|
if not Client and os.environ.get('GOOGLE_CLOUD_LOGGING') == "1":
|
|
224
221
|
print("Found GOOGLE_CLOUD_LOGGING=1 but no GCP Client available, install via `pip install sunholo[gcp]` and/or authenticate")
|
|
225
222
|
|
|
@@ -228,11 +225,16 @@ def setup_logging(logger_name=None, log_level=logging.INFO, project_id=None):
|
|
|
228
225
|
project_id = get_gcp_project()
|
|
229
226
|
# Instantiate the GoogleCloudLogging class
|
|
230
227
|
gc_logger = GoogleCloudLogging(project_id, log_level=log_level, logger_name=logger_name)
|
|
228
|
+
# Setup logging and return the logger instance
|
|
229
|
+
return gc_logger.setup_logging()
|
|
231
230
|
else:
|
|
232
|
-
|
|
231
|
+
if not logging.getLogger().hasHandlers():
|
|
232
|
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
233
|
+
log = logging.getLogger(logger_name)
|
|
234
|
+
|
|
235
|
+
return log
|
|
233
236
|
|
|
234
|
-
|
|
235
|
-
return gc_logger.setup_logging()
|
|
237
|
+
|
|
236
238
|
|
|
237
239
|
|
|
238
240
|
|
sunholo/utils/config.py
CHANGED
|
@@ -59,12 +59,12 @@ def load_all_configs():
|
|
|
59
59
|
config_folder = os.getenv("_CONFIG_FOLDER", os.getcwd())
|
|
60
60
|
config_folder = os.path.join(config_folder, "config")
|
|
61
61
|
|
|
62
|
-
log.
|
|
62
|
+
log.debug(f"Loading all configs from folder: {config_folder}")
|
|
63
63
|
current_time = datetime.now()
|
|
64
64
|
|
|
65
65
|
configs_by_kind = defaultdict(dict)
|
|
66
66
|
for filename in os.listdir(config_folder):
|
|
67
|
-
log.
|
|
67
|
+
log.debug(f"config file: {filename}")
|
|
68
68
|
if filename in ["cloudbuild.yaml", "cloud_run_urls.json"]:
|
|
69
69
|
# skip these
|
|
70
70
|
continue
|
|
@@ -191,10 +191,9 @@ def load_config_key(key: str, vector_name: str, kind: str=None):
|
|
|
191
191
|
assert isinstance(vector_name, str), f"vector_name must be a string, got a {type(vector_name)}"
|
|
192
192
|
|
|
193
193
|
configs_by_kind = load_all_configs()
|
|
194
|
-
log.info(f"configs by kind: {configs_by_kind}")
|
|
195
194
|
|
|
196
195
|
if kind:
|
|
197
|
-
log.
|
|
196
|
+
log.debug(f"Got kind: {kind} - applying to configs")
|
|
198
197
|
|
|
199
198
|
if not configs_by_kind:
|
|
200
199
|
log.warning("Did not load configs via folder")
|
|
@@ -205,18 +204,23 @@ def load_config_key(key: str, vector_name: str, kind: str=None):
|
|
|
205
204
|
else:
|
|
206
205
|
config, filename = load_config(filename)
|
|
207
206
|
|
|
208
|
-
log.
|
|
207
|
+
log.debug(f"Fetching '{key}' for '{vector_name}'")
|
|
209
208
|
apiVersion = config.get('apiVersion')
|
|
210
209
|
kind = config.get('kind')
|
|
211
210
|
vac = config.get('vac')
|
|
212
211
|
|
|
213
212
|
if not apiVersion or not kind:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
log.info(f"Loaded config file {kind}/{apiVersion}")
|
|
213
|
+
raise ValueError("Deprecated config file, move to config with `apiVersion` and `kind` set")
|
|
214
|
+
|
|
215
|
+
log.debug(f"Loaded config file {kind}/{apiVersion}")
|
|
218
216
|
|
|
219
217
|
if kind == 'vacConfig':
|
|
218
|
+
if vector_name == 'global':
|
|
219
|
+
key_value = config.get(key)
|
|
220
|
+
log.debug(f'vac_config global value for {key}: {key_value}')
|
|
221
|
+
|
|
222
|
+
return key_value
|
|
223
|
+
|
|
220
224
|
vac = config.get('vac')
|
|
221
225
|
if not vac:
|
|
222
226
|
raise ValueError("Deprecated config file, move to config with `vac:` at top level for `vector_name`")
|
|
@@ -224,7 +228,7 @@ def load_config_key(key: str, vector_name: str, kind: str=None):
|
|
|
224
228
|
if not vac_config:
|
|
225
229
|
raise ValueError(f"No config array was found for {vector_name} in {filename}")
|
|
226
230
|
|
|
227
|
-
log.
|
|
231
|
+
log.debug(f'vac_config: {vac_config} for {vector_name} - fetching "{key}"')
|
|
228
232
|
key_value = vac_config.get(key)
|
|
229
233
|
|
|
230
234
|
return key_value
|
|
@@ -237,7 +241,7 @@ def load_config_key(key: str, vector_name: str, kind: str=None):
|
|
|
237
241
|
if not prompt_for_vector_name:
|
|
238
242
|
raise ValueError(f"Could not find prompt for vector_name {vector_name}")
|
|
239
243
|
|
|
240
|
-
log.
|
|
244
|
+
log.debug(f'prompts: {prompt_for_vector_name} for {vector_name} - fetching "{key}"')
|
|
241
245
|
key_value = prompt_for_vector_name.get(key)
|
|
242
246
|
|
|
243
247
|
return key_value
|
sunholo/utils/user_ids.py
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import uuid
|
|
2
|
-
from google.auth import default
|
|
3
|
-
|
|
4
|
-
from ..logging import log
|
|
5
|
-
|
|
6
2
|
import hashlib
|
|
7
3
|
import platform
|
|
8
4
|
import socket
|
|
@@ -10,30 +6,5 @@ import socket
|
|
|
10
6
|
def generate_user_id():
|
|
11
7
|
data = f"{socket.gethostname()}-{platform.platform()}-{platform.processor()}"
|
|
12
8
|
hashed_id = hashlib.sha256(data.encode('utf-8')).hexdigest()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def generate_uuid_from_gcloud_user():
|
|
16
|
-
"""
|
|
17
|
-
Generates a UUID using the Google Cloud authorized user's email address, or if not available via os settings.
|
|
18
|
-
|
|
19
|
-
Returns:
|
|
20
|
-
str: The generated UUID as a string.
|
|
21
|
-
"""
|
|
22
|
-
_, credentials = default() # Get the default credentials
|
|
23
|
-
|
|
24
|
-
if credentials:
|
|
25
|
-
user_email = credentials.service_account_email # Get email for service accounts
|
|
26
|
-
if not user_email:
|
|
27
|
-
user_email = credentials.id_token['email'] # Get email for user accounts
|
|
28
|
-
|
|
29
|
-
if user_email:
|
|
30
|
-
# Create a UUID using the user's email as a source for randomness
|
|
31
|
-
user_uuid = uuid.uuid5(uuid.NAMESPACE_DNS, user_email)
|
|
32
|
-
return str(user_uuid)
|
|
33
|
-
else:
|
|
34
|
-
log.warning("Unable to get user email from Google Cloud credentials.")
|
|
35
|
-
|
|
36
|
-
else:
|
|
37
|
-
log.warning("No Google Cloud credentials found.")
|
|
38
|
-
|
|
39
|
-
return str(generate_user_id())
|
|
9
|
+
|
|
10
|
+
return str(uuid.uuid5(uuid.NAMESPACE_DNS, hashed_id))
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.60.
|
|
3
|
+
Version: 0.60.3
|
|
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.60.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.60.3.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -18,13 +18,13 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
|
-
Requires-Dist:
|
|
21
|
+
Requires-Dist: google-auth
|
|
22
22
|
Requires-Dist: langchain
|
|
23
23
|
Requires-Dist: langchain-experimental
|
|
24
24
|
Requires-Dist: langchain-community
|
|
25
|
-
Requires-Dist: google-auth
|
|
26
25
|
Provides-Extra: all
|
|
27
26
|
Requires-Dist: asyncpg ; extra == 'all'
|
|
27
|
+
Requires-Dist: fastapi ; extra == 'all'
|
|
28
28
|
Requires-Dist: flask ; extra == 'all'
|
|
29
29
|
Requires-Dist: google-auth ; extra == 'all'
|
|
30
30
|
Requires-Dist: google-auth-httplib2 ; extra == 'all'
|
|
@@ -42,6 +42,7 @@ Requires-Dist: google-generativeai ; extra == 'all'
|
|
|
42
42
|
Requires-Dist: gunicorn ; extra == 'all'
|
|
43
43
|
Requires-Dist: httpcore ; extra == 'all'
|
|
44
44
|
Requires-Dist: httpx ; extra == 'all'
|
|
45
|
+
Requires-Dist: jsonschema ; extra == 'all'
|
|
45
46
|
Requires-Dist: lancedb ; extra == 'all'
|
|
46
47
|
Requires-Dist: langchain ; extra == 'all'
|
|
47
48
|
Requires-Dist: langchain-experimental ; extra == 'all'
|
|
@@ -55,12 +56,15 @@ Requires-Dist: pg8000 ; extra == 'all'
|
|
|
55
56
|
Requires-Dist: pgvector ; extra == 'all'
|
|
56
57
|
Requires-Dist: psycopg2-binary ; extra == 'all'
|
|
57
58
|
Requires-Dist: pypdf ; extra == 'all'
|
|
58
|
-
Requires-Dist:
|
|
59
|
+
Requires-Dist: python-socketio ; extra == 'all'
|
|
60
|
+
Requires-Dist: rich ; extra == 'all'
|
|
59
61
|
Requires-Dist: supabase ; extra == 'all'
|
|
60
62
|
Requires-Dist: tiktoken ; extra == 'all'
|
|
61
|
-
Requires-Dist: python-socketio ; extra == 'all'
|
|
62
63
|
Provides-Extra: anthropic
|
|
63
64
|
Requires-Dist: langchain-anthropic ; extra == 'anthropic'
|
|
65
|
+
Provides-Extra: cli
|
|
66
|
+
Requires-Dist: jsonschema ; extra == 'cli'
|
|
67
|
+
Requires-Dist: rich ; extra == 'cli'
|
|
64
68
|
Provides-Extra: database
|
|
65
69
|
Requires-Dist: asyncpg ; extra == 'database'
|
|
66
70
|
Requires-Dist: supabase ; extra == 'database'
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
sunholo/__init__.py,sha256=
|
|
2
|
-
sunholo/logging.py,sha256=
|
|
1
|
+
sunholo/__init__.py,sha256=0CdpufyRKWyZe7J7UKigL6j_qOorM-p0OjHIAuf9M38,864
|
|
2
|
+
sunholo/logging.py,sha256=1jzfy4q9h5DNG4MjwtbTiM8keZxymlrZ0gDQEtGLMHY,11400
|
|
3
3
|
sunholo/agents/__init__.py,sha256=CnlbVohPt-Doth9PyROSlN3P8xMV9j9yS19YE-wCS90,341
|
|
4
4
|
sunholo/agents/chat_history.py,sha256=PbwYmw1TwzI8H-cwQIGgHZ6UIr2Qb-JWow0RG3ayLM8,5195
|
|
5
|
-
sunholo/agents/dispatch_to_qa.py,sha256=
|
|
5
|
+
sunholo/agents/dispatch_to_qa.py,sha256=h5qbcPqJ5JGa21T8Z5is7jbn4eG3P4xULLj_X25q3WM,8208
|
|
6
6
|
sunholo/agents/langserve.py,sha256=FdhQjorAY2bMn2rpuabNT6bU3uqSKWrl8DjpH3L_V7k,4375
|
|
7
7
|
sunholo/agents/pubsub.py,sha256=5hbbhbBGyVWRpt2sAGC5FEheYH1mCCwVUhZEB1S7vGg,1337
|
|
8
8
|
sunholo/agents/route.py,sha256=0klBifx-QtMGsjq8HB04s9Bytm0nFXPYaWKeyt-S9S4,2356
|
|
@@ -13,7 +13,7 @@ sunholo/agents/fastapi/base.py,sha256=clk76cHbUAvU0OYJrRfCWX_5f0ACbhDsIzYBhI3wyo
|
|
|
13
13
|
sunholo/agents/fastapi/qna_routes.py,sha256=DgK4Btu5XriOC1JaRQ4G_nWEjJfnQ0J5pyLanF6eF1g,3857
|
|
14
14
|
sunholo/agents/flask/__init__.py,sha256=uqfHNw2Ru3EJ4dJEcbp86h_lkquBQPMxZbjhV_xe3rs,72
|
|
15
15
|
sunholo/agents/flask/base.py,sha256=RUGWBYWeV60FatYF5sMRrxD-INU97Vodsi6JaB6i93s,763
|
|
16
|
-
sunholo/agents/flask/qna_routes.py,sha256=
|
|
16
|
+
sunholo/agents/flask/qna_routes.py,sha256=Pr2dxM7GKhXNKv6t7_J578BN6oMETAYFe6ydEm4D90g,8620
|
|
17
17
|
sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
|
|
18
18
|
sunholo/archive/archive.py,sha256=C-UhG5x-XtZ8VheQp92IYJqgD0V3NFQjniqlit94t18,1197
|
|
19
19
|
sunholo/auth/__init__.py,sha256=4owDjSaWYkbTlPK47UHTOC0gCWbZsqn4ZIEw5NWZTlg,28
|
|
@@ -32,18 +32,19 @@ sunholo/chunker/pdfs.py,sha256=daCZ1xjn1YvxlifIyxskWNpLJLe-Q9D_Jq12MWx3tZo,2473
|
|
|
32
32
|
sunholo/chunker/publish.py,sha256=PoT8q3XJeFCg10WrLkYhuaaXIrGVkvUD3-R9IfoWoH4,2703
|
|
33
33
|
sunholo/chunker/splitter.py,sha256=FLkDhkePkg_zGQpFBK13Cznw575D-Rf9pcaCpc1HUxY,6726
|
|
34
34
|
sunholo/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
sunholo/cli/chat_vac.py,sha256=
|
|
36
|
-
sunholo/cli/cli.py,sha256=
|
|
35
|
+
sunholo/cli/chat_vac.py,sha256=o17_ErIsR0FtCelSCTRSyleUeqZkbA7M463F7e61KBs,6360
|
|
36
|
+
sunholo/cli/cli.py,sha256=d52lyS0WnEWK8qSDX6-B6KgpNhQC6R9hiENE9s-qSqM,2613
|
|
37
37
|
sunholo/cli/cli_init.py,sha256=JMZ9AX2cPDZ-_mv3adiv2ToFVNyRPtjk9Biszl1kiR0,2358
|
|
38
38
|
sunholo/cli/configs.py,sha256=QUM9DvKOdZmEQRM5uI3Nh887T0YDiSMr7O240zTLqws,4546
|
|
39
39
|
sunholo/cli/deploy.py,sha256=zxdwUsRTRMC8U5vyRv0JiKBLFn84Ug_Tc88-_h9hJSs,1609
|
|
40
40
|
sunholo/cli/merge_texts.py,sha256=U9vdMwKmcPoc6iPOWX5MKSxn49dNGbNzVLw8ui5PhEU,1823
|
|
41
|
-
sunholo/cli/run_proxy.py,sha256=
|
|
41
|
+
sunholo/cli/run_proxy.py,sha256=2ZFjOPMUNeC2nK2iwLZfE2HQkq9ZDaDen2EabHuNAFs,9606
|
|
42
|
+
sunholo/cli/sun_rich.py,sha256=UpMqeJ0C8i0pkue1AHnnyyX0bFJ9zZeJ7HBR6yhuA8A,54
|
|
42
43
|
sunholo/components/__init__.py,sha256=RJGNEihwvRIiDScKis04RHJv4yZGI1UpXlOmuCptNZI,208
|
|
43
44
|
sunholo/components/llm.py,sha256=T4we3tGmqUj4tPwxQr9M6AXv_BALqZV_dRSvINan-oU,10374
|
|
44
45
|
sunholo/components/prompt.py,sha256=eZSghXkIlRzXiSrzgkG7e5ytUYq6R6LV-qjHU8jStig,6353
|
|
45
|
-
sunholo/components/retriever.py,sha256=
|
|
46
|
-
sunholo/components/vectorstore.py,sha256=
|
|
46
|
+
sunholo/components/retriever.py,sha256=_Lyt9RIgb2PD-rhV6oKAadiUs3ukT5uAYGW197tEskw,3755
|
|
47
|
+
sunholo/components/vectorstore.py,sha256=dzspqOBtuxSjCFxem5_50sqwUUjbZ4oBYERtCwxZR6E,5619
|
|
47
48
|
sunholo/database/__init__.py,sha256=Zz0Shcq-CtStf9rJGIYB_Ybzb8rY_Q9mfSj-nviM490,241
|
|
48
49
|
sunholo/database/alloydb.py,sha256=J4VzrW2ChIYyqtccUBCtoN-vClfn-iipEDJpxN7GJkY,14820
|
|
49
50
|
sunholo/database/database.py,sha256=doY05kG8BZBLL-arh4hq5ef1ouWOtGHqdsDc6M2YHgk,7345
|
|
@@ -60,7 +61,7 @@ sunholo/embedder/__init__.py,sha256=sI4N_CqgEVcrMDxXgxKp1FsfsB4FpjoXgPGkl4N_u4I,
|
|
|
60
61
|
sunholo/embedder/embed_chunk.py,sha256=XV1kdDUWw2QO-am5_Yl7GrYP9V_4i1XRNNFPhqUSnZQ,5851
|
|
61
62
|
sunholo/gcs/__init__.py,sha256=DtVw_AZwQn-IguR5BJuIi2XJeF_FQXizhJikzRNrXiE,50
|
|
62
63
|
sunholo/gcs/add_file.py,sha256=JmJIuz5Z1h7-eJ6s2eE3wc8Y4IAv3Jridq1xfQbD9_E,4711
|
|
63
|
-
sunholo/gcs/download_url.py,sha256=
|
|
64
|
+
sunholo/gcs/download_url.py,sha256=8XSEf8byfubqs5CMQeF_tn9wxqwUTq3n9mo5mLNIUTA,4801
|
|
64
65
|
sunholo/gcs/metadata.py,sha256=C9sMPsHsq1ETetdQCqB3EBs3Kws8b8QHS9L7ei_v5aw,891
|
|
65
66
|
sunholo/langfuse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
66
67
|
sunholo/langfuse/callback.py,sha256=G9xcZHpLvyzolU57ycItLaooMCtRuM37QJSWjiwQEd0,1776
|
|
@@ -88,16 +89,16 @@ sunholo/summarise/__init__.py,sha256=MZk3dblUMODcPb1crq4v-Z508NrFIpkSWNf9FIO8BcU
|
|
|
88
89
|
sunholo/summarise/summarise.py,sha256=C3HhjepTjUhUC8FLk4jMQIBvq1BcORniwuTFHjPVhVo,3784
|
|
89
90
|
sunholo/utils/__init__.py,sha256=G11nN_6ATjxpuMfG_BvcUr9UU8onPIgkpTK6CjOcbr8,48
|
|
90
91
|
sunholo/utils/big_context.py,sha256=gJIP7_ZL-YSLhOMq8jmFTMqH1wq8eB1NK7oKPeZAq2s,5578
|
|
91
|
-
sunholo/utils/config.py,sha256=
|
|
92
|
+
sunholo/utils/config.py,sha256=3GSDFGbHugB3qlkHadKi3Z1CEr6EZhCOQ3TiNt03nNU,8594
|
|
92
93
|
sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
|
|
93
94
|
sunholo/utils/gcp.py,sha256=B2G1YKjeD7X9dqO86Jrp2vPuFwZ223Xl5Tg09Ndw-oc,5760
|
|
94
95
|
sunholo/utils/parsers.py,sha256=OrHmASqIbI45atVOhiGodgLvnfrzkvVzyHnSvAXD89I,3841
|
|
95
|
-
sunholo/utils/user_ids.py,sha256=
|
|
96
|
+
sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
|
|
96
97
|
sunholo/vertex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
97
98
|
sunholo/vertex/init_vertex.py,sha256=JDMUaBRdednzbKF-5p33qqLit2LMsvgvWW-NRz0AqO0,1801
|
|
98
|
-
sunholo-0.60.
|
|
99
|
-
sunholo-0.60.
|
|
100
|
-
sunholo-0.60.
|
|
101
|
-
sunholo-0.60.
|
|
102
|
-
sunholo-0.60.
|
|
103
|
-
sunholo-0.60.
|
|
99
|
+
sunholo-0.60.3.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
100
|
+
sunholo-0.60.3.dist-info/METADATA,sha256=Zk0NZ77eeA0GocxUY1fVWY7RA7rtma6t531MCjaBiVU,8057
|
|
101
|
+
sunholo-0.60.3.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
102
|
+
sunholo-0.60.3.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
103
|
+
sunholo-0.60.3.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
104
|
+
sunholo-0.60.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|