sunholo 0.60.7__py3-none-any.whl → 0.60.9__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.
@@ -41,9 +41,14 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
41
41
  def home():
42
42
  return jsonify("OK")
43
43
 
44
+ @app.route("/health")
45
+ def health():
46
+ return jsonify({"status": "healthy"})
47
+
44
48
  @app.route('/vac/streaming/<vector_name>', methods=['POST'])
45
49
  @observe()
46
50
  def stream_qa(vector_name):
51
+ observed_stream_interpreter = observe()(stream_interpreter)
47
52
  prep = prep_vac(request, vector_name)
48
53
  log.debug(f"Processing prep: {prep}")
49
54
  trace = prep["trace"]
@@ -69,7 +74,7 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
69
74
 
70
75
  for chunk in start_streaming_chat(question=all_input["user_input"],
71
76
  vector_name=vector_name,
72
- qna_func=stream_interpreter,
77
+ qna_func=observed_stream_interpreter,
73
78
  chat_history=all_input["chat_history"],
74
79
  wait_time=all_input["stream_wait_time"],
75
80
  timeout=all_input["stream_timeout"],
sunholo/cli/chat_vac.py CHANGED
@@ -186,7 +186,7 @@ def vac_command(args):
186
186
 
187
187
  stream_chat_session(service_url, args.vac_name)
188
188
 
189
- stop_proxy(agent_name)
189
+ stop_proxy(agent_name, stop_local=False)
190
190
 
191
191
 
192
192
  def list_cloud_run_services(project, region):
@@ -296,6 +296,6 @@ def setup_vac_subparser(subparsers):
296
296
  chat_parser.add_argument('user_input', help='User input for the VAC service when in headless mode.', nargs='?', default=None)
297
297
  chat_parser.add_argument('--headless', action='store_true', help='Run in headless mode.')
298
298
  chat_parser.add_argument('--chat_history', help='Chat history for headless mode (as JSON string).', default=None)
299
- chat_parser.add_argument('--no_proxy', action='store_true', help='Do not use the proxy and connect directly to the VAC service.')
299
+ chat_parser.add_argument('--no-proxy', action='store_true', help='Do not use the proxy and connect directly to the VAC service.')
300
300
 
301
301
  vac_parser.set_defaults(func=vac_command)
sunholo/cli/cli.py CHANGED
@@ -11,10 +11,17 @@ from ..utils.config import load_config_key
11
11
 
12
12
  from ..logging import log
13
13
 
14
+ from .sun_rich import console
15
+ import sys
14
16
 
15
17
 
16
18
  def load_default_gcp_config():
17
- gcp_config = load_config_key('gcp_config', 'global', kind="vacConfig")
19
+ try:
20
+ gcp_config = load_config_key('gcp_config', 'global', kind="vacConfig")
21
+ except FileNotFoundError as e:
22
+ console.print(f"{e} - move config/ folder to working directory or set the _CONFIG_FOLDER environment variable to its location")
23
+ sys.exit(1)
24
+
18
25
  if gcp_config:
19
26
  return gcp_config.get('project_id', ''), gcp_config.get('location', 'europe-west1')
20
27
  else:
sunholo/cli/run_proxy.py CHANGED
@@ -1,5 +1,6 @@
1
1
  import subprocess
2
2
  import os
3
+ import sys
3
4
  import signal
4
5
  import json
5
6
 
@@ -96,7 +97,7 @@ def save_proxies(proxies):
96
97
 
97
98
 
98
99
 
99
- def start_proxy(service_name, region, project, port=None):
100
+ def start_proxy(service_name, region, project, port=None, local=False, app_type=None, app_folder=None, log_file=None):
100
101
  """
101
102
  Starts the gcloud proxy to the Cloud Run service and stores the PID.
102
103
 
@@ -114,34 +115,48 @@ def start_proxy(service_name, region, project, port=None):
114
115
 
115
116
  if not port:
116
117
  port = get_next_available_port(proxies, DEFAULT_PORT)
117
-
118
- command = [
119
- "gcloud", "run", "services", "proxy", service_name,
120
- "--region", region,
121
- "--project", project,
122
- "--port", str(port)
123
- ]
124
- with open(os.devnull, 'w') as devnull:
125
- process = subprocess.Popen(command, stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp)
126
-
127
- proxies[service_name] = {
128
- "pid": process.pid,
129
- "port": port
130
- }
131
- save_proxies(proxies)
132
118
 
133
- console.print(f"Proxy for [bold orange]'{service_name}'[/bold orange] setup complete on port {port}")
134
- list_proxies()
119
+
120
+
121
+ if local:
122
+ start_local(service_name, port, app_type, app_folder, log_file)
123
+ else:
124
+ command = [
125
+ "gcloud", "run", "services", "proxy", service_name,
126
+ "--region", region,
127
+ "--project", project,
128
+ "--port", str(port)
129
+ ]
130
+ if log_file:
131
+ log_file_path = os.path.join(app_folder, f"{service_name}_log.txt")
132
+ with open(log_file_path, 'a') as logf:
133
+ process = subprocess.Popen(command, stdout=logf, stderr=logf, preexec_fn=os.setpgrp)
134
+ else:
135
+ log_file_path = "No log file specified"
136
+ with open(os.devnull, 'w') as devnull:
137
+ process = subprocess.Popen(command, stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp)
138
+
139
+ proxies[service_name] = {
140
+ "pid": process.pid,
141
+ "port": port,
142
+ "local": "No",
143
+ "logs": log_file_path
144
+ }
145
+ save_proxies(proxies)
146
+
147
+ console.print(f"Proxy for [bold orange]'{service_name}'[/bold orange] setup complete on port {port}")
148
+ list_proxies()
135
149
 
136
150
  return f"http://127.0.0.1:{port}"
137
151
 
138
152
 
139
- def stop_proxy(service_name):
153
+ def stop_proxy(service_name, stop_local=True):
140
154
  """
141
155
  Stops the gcloud proxy to the Cloud Run service using the stored PID.
142
156
 
143
157
  Args:
144
158
  service_name (str): Name of the Cloud Run service.
159
+ stop_local (bool): Whether to stop locally running services or not. Defaults to True.
145
160
  """
146
161
  proxies = clean_proxy_list()
147
162
 
@@ -149,16 +164,21 @@ def stop_proxy(service_name):
149
164
  print(f"No proxy found for service: {service_name}")
150
165
  return
151
166
 
152
- pid = proxies[service_name]["pid"]
153
- try:
154
- os.kill(pid, signal.SIGTERM)
155
- del proxies[service_name]
156
- save_proxies(proxies)
157
- console.print(f"Proxy for [bold orange]'{service_name}'[bold orange] stopped.")
158
- except ProcessLookupError:
159
- console.print(f"No process found with PID: {pid}")
160
- except Exception as e:
161
- console.print(f"[bold red]Error stopping proxy for {service_name}: {e}[/bold red]")
167
+ if not stop_local:
168
+ local = proxies[service_name]["local"]
169
+ if local != "No":
170
+ console.print(f"Not stopping local VAC running on: {local}")
171
+ else:
172
+ pid = proxies[service_name]["pid"]
173
+ try:
174
+ os.kill(pid, signal.SIGTERM)
175
+ del proxies[service_name]
176
+ save_proxies(proxies)
177
+ console.print(f"Proxy for [bold orange]'{service_name}'[bold orange] stopped.")
178
+ except ProcessLookupError:
179
+ console.print(f"No process found with PID: {pid}")
180
+ except Exception as e:
181
+ console.print(f"[bold red]Error stopping proxy for {service_name}: {e}[/bold red]")
162
182
 
163
183
  list_proxies()
164
184
 
@@ -192,18 +212,71 @@ def list_proxies():
192
212
  if not proxies:
193
213
  print("No proxies currently running.")
194
214
  else:
195
- table = Table(title="VAC Proxies")
215
+ table = Table(title="VAC Proxies - `sunholo proxy list`")
196
216
  table.add_column("VAC")
197
217
  table.add_column("Port")
198
218
  table.add_column("PID")
199
219
  table.add_column("URL")
220
+ table.add_column("Local")
221
+ table.add_column("Logs")
200
222
 
201
223
  for service_name, info in proxies.items():
202
224
  url = f"http://127.0.0.1:{info['port']}"
203
- table.add_row(service_name, str(info['port']), str(info['pid']), url)
225
+ table.add_row(service_name,
226
+ str(info['port']),
227
+ str(info['pid']),
228
+ url,
229
+ str(info['local']),
230
+ str(info['logs']) )
204
231
 
205
232
  console.print(table)
206
233
 
234
+ def start_local(service_name, port, app_type, app_folder, log_file):
235
+ """
236
+ Starts a local Flask or FastAPI VAC app.
237
+
238
+ Args:
239
+ service_name (str): Name of the service.
240
+ port (int): Port to run the local app on.
241
+ app_type (str): Type of the app ('flask' or 'fastapi').
242
+ app_folder (str): Folder containing the app.
243
+ """
244
+ proxies = clean_proxy_list()
245
+
246
+ if service_name in proxies:
247
+ console.print(f"Local VAC app [bold orange]'{service_name}'[/bold orange] is already running on port {proxies[service_name]['port']}.")
248
+ return
249
+
250
+ if app_type == 'flask':
251
+ command = [sys.executable, 'app.py']
252
+ elif app_type == 'fastapi':
253
+ command = ["uvicorn", "app:app", f"--port={port}"]
254
+ else:
255
+ print(f"[bold red]Unknown app type: {app_type}[/bold red]")
256
+ return
257
+
258
+ if log_file:
259
+ log_file_path = os.path.join(app_folder, f"{service_name}_log.txt")
260
+ with open(log_file_path, 'w') as logf:
261
+ process = subprocess.Popen(command, cwd=app_folder, stdout=logf, stderr=logf, preexec_fn=os.setpgrp)
262
+ else:
263
+ log_file_path = "No log file specified"
264
+ with open(os.devnull, 'a') as devnull:
265
+ process = subprocess.Popen(command, cwd=app_folder, stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp)
266
+
267
+ proxies[service_name] = {
268
+ "pid": process.pid,
269
+ "port": port,
270
+ "local": f"{app_folder}/app.py - {app_type}",
271
+ "logs": log_file_path
272
+ }
273
+ save_proxies(proxies)
274
+
275
+ console.print(f"Local app [bold orange]'{service_name}'[/bold orange] started on port {port}")
276
+ list_proxies()
277
+
278
+ return f"http://127.0.0.1:{port}"
279
+
207
280
  def setup_proxy_subparser(subparsers):
208
281
  """
209
282
  Sets up an argparse subparser for the 'proxy' command.
@@ -218,8 +291,19 @@ def setup_proxy_subparser(subparsers):
218
291
  start_parser = proxy_subparsers.add_parser('start', help='Start the proxy to the VAC Cloud Run service')
219
292
  start_parser.add_argument('service_name', help='Name of the Cloud Run service.')
220
293
  start_parser.add_argument('--port', type=int, help='Port to run the proxy on. Auto-assigns if not provided.')
221
- start_parser.set_defaults(func=lambda args: start_proxy(args.service_name, args.region, args.project, args.port))
222
-
294
+ start_parser.add_argument('--local', action='store_true', help='Run the service locally instead of proxying to Cloud Run.')
295
+ start_parser.add_argument('--app-type', choices=['flask', 'fastapi'], help='If local, type of the local app (flask or fastapi).')
296
+ start_parser.add_argument('--app-folder', help='If local, folder containing the local app.py')
297
+ start_parser.add_argument('--log-file', action='store_true', help='Whether to create a file containing proxy logs.')
298
+ start_parser.set_defaults(func=lambda args: start_proxy(args.service_name,
299
+ args.region,
300
+ args.project,
301
+ args.port,
302
+ args.local,
303
+ args.app_type,
304
+ args.app_folder,
305
+ args.log_file))
306
+
223
307
  stop_parser = proxy_subparsers.add_parser('stop', help='Stop the proxy to the Cloud Run service.')
224
308
  stop_parser.add_argument('service_name', help='Name of the Cloud Run service.')
225
309
  stop_parser.set_defaults(func=lambda args: stop_proxy(args.service_name))
@@ -5,7 +5,7 @@ def create_lancedb_index(bucket, vector_name, num_partitions=256, num_sub_vector
5
5
  import lancedb
6
6
  #import tantivy
7
7
  except ImportError:
8
- raise ValueError("Could not import lancedb module, install via `pip intall sunholo[database]`")
8
+ raise ValueError("Could not import lancedb module, install via `pip install sunholo[database]`")
9
9
 
10
10
  try:
11
11
  db = lancedb.connect(bucket)
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.60.7
3
+ Version: 0.60.9
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.7.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.60.9.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -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=Pr2dxM7GKhXNKv6t7_J578BN6oMETAYFe6ydEm4D90g,8620
16
+ sunholo/agents/flask/qna_routes.py,sha256=9xQUIadDtQIgTRa-nXIYJbzwQokqtVjeLp-tcSxGy9Y,8788
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,13 +32,13 @@ 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=8iSda-K3w0zHLrMkjck919kVgM5vJNrLAbEj0zKVIKw,11361
36
- sunholo/cli/cli.py,sha256=LWA5OveHx3ocy9KD1XwAwosBFrTUwifArIbltYgpul4,2420
35
+ sunholo/cli/chat_vac.py,sha256=_NUjwATKvzwfnBJRedP2GqPFNeaCF5F8OvdygXRH1LY,11379
36
+ sunholo/cli/cli.py,sha256=cogY1F5rcIGFYpZVFtbDNlAIElpfyPSCvSLC1ZIpHXg,2666
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=53bRzm6IVf5SB07fiwqKpJrGQBTt3xAWi-669w6VYSU,7591
41
+ sunholo/cli/run_proxy.py,sha256=9ILCxSVHPzS-cSBvjdHhfZFlwsJ4Ttmu0vLtNoPCRgo,11469
42
42
  sunholo/cli/sun_rich.py,sha256=UpMqeJ0C8i0pkue1AHnnyyX0bFJ9zZeJ7HBR6yhuA8A,54
43
43
  sunholo/components/__init__.py,sha256=RJGNEihwvRIiDScKis04RHJv4yZGI1UpXlOmuCptNZI,208
44
44
  sunholo/components/llm.py,sha256=T4we3tGmqUj4tPwxQr9M6AXv_BALqZV_dRSvINan-oU,10374
@@ -48,7 +48,7 @@ sunholo/components/vectorstore.py,sha256=dzspqOBtuxSjCFxem5_50sqwUUjbZ4oBYERtCwx
48
48
  sunholo/database/__init__.py,sha256=Zz0Shcq-CtStf9rJGIYB_Ybzb8rY_Q9mfSj-nviM490,241
49
49
  sunholo/database/alloydb.py,sha256=0zRLyeC9nACzj3v36ET9NqLeuzdwBJ2bE09CzgVTTFM,17098
50
50
  sunholo/database/database.py,sha256=doY05kG8BZBLL-arh4hq5ef1ouWOtGHqdsDc6M2YHgk,7345
51
- sunholo/database/lancedb.py,sha256=WSrbY5mgyeXx6i7UBiz4YQ_i5UIYVYFo-vPGO72bQKY,707
51
+ sunholo/database/lancedb.py,sha256=2rAbJVusMrm5TPtVTsUtmwn0z1iZ_wvbKhc6eyT6ClE,708
52
52
  sunholo/database/static_dbs.py,sha256=aOyU3AJ-Dzz3qSNjbuN2293cfYw5PhkcQuQxdwPMJ4w,435
53
53
  sunholo/database/uuid.py,sha256=GtUL_uq80u2xkozPF9kwNpvhBf03hbZR3xUhO3NomBM,237
54
54
  sunholo/database/sql/sb/create_function.sql,sha256=HuDyp3fxS5Etop3gGDy28_AuFuhgEgVcq9-q3oeecPU,1033
@@ -96,9 +96,9 @@ sunholo/utils/parsers.py,sha256=OrHmASqIbI45atVOhiGodgLvnfrzkvVzyHnSvAXD89I,3841
96
96
  sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
97
97
  sunholo/vertex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
98
  sunholo/vertex/init_vertex.py,sha256=JDMUaBRdednzbKF-5p33qqLit2LMsvgvWW-NRz0AqO0,1801
99
- sunholo-0.60.7.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
100
- sunholo-0.60.7.dist-info/METADATA,sha256=UqURElBg2H6zB4MKBSBwTktG2AeeClFUcGVVr_BPSW4,8057
101
- sunholo-0.60.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
102
- sunholo-0.60.7.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
103
- sunholo-0.60.7.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
104
- sunholo-0.60.7.dist-info/RECORD,,
99
+ sunholo-0.60.9.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
100
+ sunholo-0.60.9.dist-info/METADATA,sha256=HRCIwV9y1sAi8Ft3p73fUff0wkaxHQ7V9CSN-1jwSzE,8057
101
+ sunholo-0.60.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
102
+ sunholo-0.60.9.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
103
+ sunholo-0.60.9.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
104
+ sunholo-0.60.9.dist-info/RECORD,,