sunholo 0.64.6__py3-none-any.whl → 0.64.8__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.
@@ -4,3 +4,4 @@ from .pubsub import process_pubsub
4
4
  from .special_commands import handle_special_commands, app_to_store, handle_files
5
5
  from .flask import register_qna_routes, create_app
6
6
  from .fastapi import register_qna_fastapi_routes, create_fastapi_app
7
+ from .swagger import config_to_swagger
@@ -41,7 +41,32 @@ except ImportError:
41
41
 
42
42
 
43
43
  def register_qna_routes(app, stream_interpreter, vac_interpreter):
44
+ """
45
+ Register Q&A routes for a Flask application.
44
46
 
47
+ This function sets up multiple routes for handling Q&A operations,
48
+ including streaming responses and processing static responses.
49
+
50
+ Args:
51
+ app (Flask): The Flask application instance.
52
+ stream_interpreter (function): Function to handle streaming Q&A responses.
53
+ vac_interpreter (function): Function to handle static Q&A responses.
54
+
55
+ Returns:
56
+ None
57
+
58
+ Example:
59
+ from flask import Flask
60
+ app = Flask(__name__)
61
+
62
+ def dummy_stream_interpreter(...):
63
+ ...
64
+
65
+ def dummy_vac_interpreter(...):
66
+ ...
67
+
68
+ register_qna_routes(app, dummy_stream_interpreter, dummy_vac_interpreter)
69
+ """
45
70
  @app.route("/")
46
71
  def home():
47
72
  return jsonify("OK")
@@ -52,6 +77,21 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
52
77
 
53
78
  @app.route('/vac/streaming/<vector_name>', methods=['POST'])
54
79
  def stream_qa(vector_name):
80
+ """
81
+ Handle streaming Q&A responses.
82
+
83
+ This function sets up a route to handle streaming Q&A responses based on
84
+ the provided vector name.
85
+
86
+ Args:
87
+ vector_name (str): The name of the vector for the request.
88
+
89
+ Returns:
90
+ Response: A Flask response object streaming the Q&A response content.
91
+
92
+ Example:
93
+ response = stream_qa("example_vector")
94
+ """
55
95
  observed_stream_interpreter = observe()(stream_interpreter)
56
96
  prep = prep_vac(request, vector_name)
57
97
  log.debug(f"Processing prep: {prep}")
@@ -117,6 +157,21 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
117
157
 
118
158
  @app.route('/vac/<vector_name>', methods=['POST'])
119
159
  def process_qna(vector_name):
160
+ """
161
+ Handle static Q&A responses.
162
+
163
+ This function sets up a route to handle static Q&A responses based on
164
+ the provided vector name.
165
+
166
+ Args:
167
+ vector_name (str): The name of the vector for the request.
168
+
169
+ Returns:
170
+ Response: A Flask response object with the Q&A response content.
171
+
172
+ Example:
173
+ response = process_qna("example_vector")
174
+ """
120
175
  observed_vac_interpreter = observe()(vac_interpreter)
121
176
  prep = prep_vac(request, vector_name)
122
177
  log.debug(f"Processing prep: {prep}")
@@ -167,6 +222,21 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
167
222
  @app.route('/openai/v1/chat/completions', methods=['POST'])
168
223
  @app.route('/openai/v1/chat/completions/<vector_name>', methods=['POST'])
169
224
  def openai_compatible_endpoint(vector_name=None):
225
+ """
226
+ Handle OpenAI-compatible chat completions.
227
+
228
+ This function sets up routes to handle OpenAI-compatible chat completion requests,
229
+ both with and without a specified vector name.
230
+
231
+ Args:
232
+ vector_name (str, optional): The name of the vector for the request. Defaults to None.
233
+
234
+ Returns:
235
+ Response: A Flask response object with the chat completion content.
236
+
237
+ Example:
238
+ response = openai_compatible_endpoint("example_vector")
239
+ """
170
240
  data = request.get_json()
171
241
  log.info(f'openai_compatible_endpoint got data: {data} for vector: {vector_name}')
172
242
 
@@ -301,6 +371,22 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
301
371
 
302
372
 
303
373
  def create_langfuse_trace(request, vector_name):
374
+ """
375
+ Create a Langfuse trace for tracking requests.
376
+
377
+ This function initializes a Langfuse trace object based on the request headers
378
+ and vector name.
379
+
380
+ Args:
381
+ request (Request): The Flask request object.
382
+ vector_name (str): The name of the vector for the request.
383
+
384
+ Returns:
385
+ Langfuse.Trace: The Langfuse trace object.
386
+
387
+ Example:
388
+ trace = create_langfuse_trace(request, "example_vector")
389
+ """
304
390
  try:
305
391
  from langfuse import Langfuse
306
392
  langfuse = Langfuse()
@@ -327,6 +413,22 @@ def create_langfuse_trace(request, vector_name):
327
413
  )
328
414
 
329
415
  def prep_vac(request, vector_name):
416
+ """
417
+ Prepare the input data for a VAC request.
418
+
419
+ This function processes the incoming request data, extracts relevant
420
+ information, and prepares the data for VAC processing.
421
+
422
+ Args:
423
+ request (Request): The Flask request object.
424
+ vector_name (str): The name of the vector for the request.
425
+
426
+ Returns:
427
+ dict: A dictionary containing prepared input data and metadata.
428
+
429
+ Example:
430
+ prep_data = prep_vac(request, "example_vector")
431
+ """
330
432
  #trace = create_langfuse_trace(request, vector_name)
331
433
  trace = None
332
434
  span = None
@@ -396,6 +498,25 @@ def prep_vac(request, vector_name):
396
498
 
397
499
 
398
500
  def handle_file_upload(file, vector_name):
501
+ """
502
+ Handle file upload and store the file in Google Cloud Storage.
503
+
504
+ This function saves the uploaded file locally, uploads it to Google Cloud Storage,
505
+ and then removes the local copy.
506
+
507
+ Args:
508
+ file (FileStorage): The uploaded file.
509
+ vector_name (str): The name of the vector for the request.
510
+
511
+ Returns:
512
+ tuple: A tuple containing the URI of the uploaded file and its MIME type.
513
+
514
+ Raises:
515
+ Exception: If the file upload fails.
516
+
517
+ Example:
518
+ uri, mime_type = handle_file_upload(file, "example_vector")
519
+ """
399
520
  try:
400
521
  file.save(file.filename)
401
522
  image_uri = add_file_to_gcs(file.filename, vector_name)
sunholo/agents/route.py CHANGED
@@ -14,7 +14,7 @@
14
14
  from ..logging import log
15
15
  from ..utils import load_config_key, load_config
16
16
 
17
- def route_qna(vector_name):
17
+ def route_vac(vector_name):
18
18
 
19
19
  agent_url = load_config_key('agent_url', vector_name=vector_name, kind="vacConfig")
20
20
  if agent_url:
@@ -35,17 +35,22 @@ def route_qna(vector_name):
35
35
  log.info(f'agent_url: {agent_url}')
36
36
  return agent_url
37
37
 
38
- def route_endpoint(vector_name, override_endpoint=None):
38
+ def route_endpoint(vector_name, method = 'post', override_endpoint=None):
39
39
 
40
40
  agent_type = load_config_key('agent_type', vector_name, kind="vacConfig")
41
41
  if not agent_type:
42
42
  agent_type = load_config_key('agent', vector_name, kind="vacConfig")
43
43
 
44
- stem = route_qna(vector_name) if not override_endpoint else override_endpoint
44
+ stem = route_vac(vector_name) if not override_endpoint else override_endpoint
45
45
 
46
- endpoints_config = load_config_key(agent_type, vector_name, kind="agentConfig")
46
+ agents_config = load_config_key(agent_type, vector_name, kind="agentConfig")
47
47
 
48
- log.info(f"endpoints_config: {endpoints_config}")
48
+ log.info(f"endpoints_config: {agents_config}")
49
+ if method not in agents_config:
50
+ raise ValueError(f"Invalid method '{method}' for agent configuration.")
51
+
52
+ # 'post' or 'get'
53
+ endpoints_config = agents_config[method]
49
54
 
50
55
  # Replace placeholders in the config
51
56
  endpoints = {}
@@ -0,0 +1,208 @@
1
+ import yaml
2
+ import copy
3
+
4
+ from ..utils.config import load_all_configs
5
+ from .route import route_vac
6
+ from ..logging import log
7
+
8
+ def config_to_swagger():
9
+ """
10
+ Load configuration files and generate a Swagger specification.
11
+
12
+ This function loads the 'vacConfig' and 'agentConfig' configuration files,
13
+ validates their presence, and then generates a Swagger specification
14
+ based on these configurations.
15
+
16
+ Returns:
17
+ str: The generated Swagger specification in YAML format.
18
+
19
+ Raises:
20
+ ValueError: If 'vacConfig' or 'agentConfig' is not loaded.
21
+
22
+ Example:
23
+ ```python
24
+ swagger_yaml = config_to_swagger()
25
+ print(swagger_yaml)
26
+ ```
27
+ """
28
+ configs = load_all_configs()
29
+
30
+ vac_config = configs.get('vacConfig')
31
+ agent_config = configs.get('agentConfig')
32
+
33
+ if not vac_config:
34
+ raise ValueError("Need valid 'vacConfig' loaded")
35
+
36
+ if not agent_config:
37
+ raise ValueError("Need valid 'agentConfig' loaded")
38
+
39
+ swag = generate_swagger(vac_config, agent_config)
40
+
41
+ return swag
42
+
43
+ def generate_swagger(vac_config, agent_config):
44
+ """
45
+ Generate a Swagger specification based on the provided configurations.
46
+
47
+ This function creates a Swagger specification using the provided 'vacConfig'
48
+ and 'agentConfig'. It dynamically builds paths and responses based on the
49
+ configurations.
50
+
51
+ Args:
52
+ vac_config (dict): The VAC configuration.
53
+ agent_config (dict): The agent configuration.
54
+
55
+ Returns:
56
+ str: The generated Swagger specification in YAML format.
57
+
58
+ Example:
59
+ ```python
60
+ vac_config = {
61
+ 'vac': {
62
+ 'service1': {
63
+ 'llm': 'vertex',
64
+ 'model': 'gemini-1.5-flash-001',
65
+ 'agent': 'langserve'
66
+ },
67
+ 'service2': {
68
+ 'llm': 'openai',
69
+ 'agent': 'crewai',
70
+ 'secrets': ['OPENAI_API_KEY']
71
+ }
72
+ }
73
+ }
74
+
75
+ agent_config = {
76
+ 'agents': {
77
+ 'default': {
78
+ 'stream': "{stem}/vac/streaming/{vector_name}",
79
+ 'invoke': "{stem}/vac/{vector_name}",
80
+ 'post': {
81
+ 'stream': "{stem}/vac/streaming/{vector_name}",
82
+ 'invoke': "{stem}/vac/{vector_name}",
83
+ 'openai': "{stem}/openai/v1/chat/completions",
84
+ 'openai-vac': "{stem}/openai/v1/chat/completions/{vector_name}"
85
+ },
86
+ 'get': {
87
+ 'home': "{stem}/",
88
+ 'health': "{stem}/health"
89
+ },
90
+ 'response': {
91
+ 'invoke': {
92
+ '200': {
93
+ 'description': 'Successful invocation response',
94
+ 'schema': {
95
+ 'type': 'object',
96
+ 'properties': {
97
+ 'answer': {'type': 'string'},
98
+ 'source_documents': {
99
+ 'type': 'array',
100
+ 'items': {
101
+ 'type': 'object',
102
+ 'properties': {
103
+ 'page_content': {'type': 'string'},
104
+ 'metadata': {'type': 'string'}
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ swagger_yaml = generate_swagger(vac_config, agent_config)
118
+ print(swagger_yaml)
119
+ ```
120
+ """
121
+ swagger_template = {
122
+ 'swagger': '2.0',
123
+ 'info': {
124
+ 'title': 'Multivac - Cloud Endpoints + Cloud Run',
125
+ 'description': 'Multivac - Cloud Endpoints with a Cloud Run backend',
126
+ 'version': '0.1.0'
127
+ },
128
+ 'host': '${_ENDPOINTS_HOST}',
129
+ 'schemes': ['https'],
130
+ 'produces': ['application/json'],
131
+ 'paths': {}
132
+ }
133
+
134
+ vac_services = vac_config['vac']
135
+
136
+ for vector_name, config in vac_services.items():
137
+ agent_type = config['agent']
138
+ agent_config_paths = agent_config['agents'].get(agent_type, {})
139
+ log.info(f'Configuring swagger for agent_type: {agent_type} for vector_name: {vector_name}')
140
+ try:
141
+ stem = route_vac(vector_name)
142
+ except ValueError:
143
+ stem = f"${{{agent_type.upper()}_BACKEND_URL}}"
144
+ log.warning(f"Failed to find URL stem for {vector_name}/{agent_type} - using {stem} instead")
145
+
146
+ for method, endpoints in agent_config_paths.items():
147
+ if method not in ['get', 'post']:
148
+ log.warning(f"Skipping {endpoints}")
149
+ continue
150
+ for endpoint_key, endpoint_template in endpoints.items():
151
+ endpoint_path = endpoint_template.replace("{stem}", f"/{agent_type}").replace("{vector_name}", vector_name)
152
+ if endpoint_path not in swagger_template['paths']:
153
+ swagger_template['paths'][endpoint_path] = {}
154
+ swagger_template['paths'][endpoint_path][method] = {
155
+ 'summary': f"{method.capitalize()} {vector_name}",
156
+ 'operationId': f"{method}_{agent_type}_{endpoint_key}",
157
+ 'x-google-backend': {
158
+ 'address': endpoint_template.replace("{stem}", stem).replace("{vector_name}", vector_name),
159
+ 'protocol': 'h2'
160
+ },
161
+ 'responses': copy.deepcopy(agent_config_paths.get('response', {}).get(endpoint_key, {
162
+ '200': {
163
+ 'description': 'Default - A successful response',
164
+ 'schema': {
165
+ 'type': 'string'
166
+ }
167
+ }
168
+ }))
169
+ }
170
+ # Handle default agent configuration for agent types without specific entries
171
+ default_agent_config = agent_config['agents'].get('default', {})
172
+
173
+ for vector_name, config in vac_services.items():
174
+ agent_type = config['agent']
175
+ if agent_type in agent_config['agents']:
176
+ continue
177
+ log.info(f'Applying default configuration for agent_type: {agent_type} for vector_name: {vector_name}')
178
+ try:
179
+ stem = route_vac(vector_name)
180
+ except ValueError:
181
+ stem = f"${{{agent_type.upper()}_BACKEND_URL}}"
182
+ log.warning(f"Failed to find URL stem for {vector_name}/{agent_type} - using {stem} instead")
183
+
184
+ for method, endpoints in default_agent_config.items():
185
+ if method not in ['get', 'post']:
186
+ continue
187
+ for endpoint_key, endpoint_template in endpoints.items():
188
+ endpoint_path = endpoint_template.replace("{stem}", f"/{agent_type}").replace("{vector_name}", vector_name)
189
+ if endpoint_path not in swagger_template['paths']:
190
+ swagger_template['paths'][endpoint_path] = {}
191
+ swagger_template['paths'][endpoint_path][method] = {
192
+ 'summary': f"{method.capitalize()} {agent_type}",
193
+ 'operationId': f"{method}_{agent_type}_{endpoint_key}",
194
+ 'x-google-backend': {
195
+ 'address': endpoint_template.replace("{stem}", stem).replace("{vector_name}", vector_name),
196
+ 'protocol': 'h2'
197
+ },
198
+ 'responses': copy.deepcopy(default_agent_config.get('response', {}).get(endpoint_key, {
199
+ '200': {
200
+ 'description': 'Default - A successful response',
201
+ 'schema': {
202
+ 'type': 'string'
203
+ }
204
+ }
205
+ }))
206
+ }
207
+
208
+ return yaml.dump(swagger_template, default_flow_style=False)
sunholo/auth/run.py CHANGED
@@ -5,14 +5,14 @@ from typing import Dict, Optional
5
5
  from ..utils.config import load_config_key, load_config
6
6
  from ..utils.gcp import is_running_on_cloudrun
7
7
  from ..logging import log
8
- from ..agents.route import route_qna
8
+ from ..agents.route import route_vac
9
9
 
10
10
  def get_run_url(vector_name=None):
11
11
 
12
12
  if not vector_name:
13
13
  raise ValueError('Vector name was not specified')
14
14
 
15
- cloud_urls = route_qna(vector_name)
15
+ cloud_urls = route_vac(vector_name)
16
16
 
17
17
  cloud_urls, _ = load_config('config/cloud_run_urls.json')
18
18
  agent = load_config_key("agent", vector_name=vector_name, kind="vacConfig")
sunholo/cli/chat_vac.py CHANGED
@@ -272,8 +272,9 @@ def vac_command(args):
272
272
  display_name = load_config_key("display_name", vector_name=args.vac_name, kind="vacConfig")
273
273
  description = load_config_key("description", vector_name=args.vac_name, kind="vacConfig")
274
274
  endpoints_config = load_config_key(agent_name, "dummy_value", kind="agentConfig")
275
+ post_endpoints = endpoints_config['post']
275
276
 
276
- display_endpoints = ' '.join(f"{key}: {value}" for key, value in endpoints_config.items())
277
+ display_endpoints = ' '.join(f"{key}: {value}" for key, value in post_endpoints.items())
277
278
  display_endpoints = display_endpoints.replace("{stem}", service_url).replace("{vector_name}", args.vac_name)
278
279
 
279
280
  if agent_name == "langserve":
sunholo/cli/cli.py CHANGED
@@ -8,6 +8,7 @@ from .merge_texts import setup_merge_text_subparser
8
8
  from .run_proxy import setup_proxy_subparser
9
9
  from .chat_vac import setup_vac_subparser
10
10
  from .embedder import setup_embedder_subparser
11
+ from .swagger import setup_swagger_subparser
11
12
 
12
13
  from ..utils.config import load_config_key
13
14
 
@@ -17,7 +18,6 @@ from .sun_rich import console
17
18
  import sys
18
19
  from rich.panel import Panel
19
20
 
20
-
21
21
  def load_default_gcp_config():
22
22
  try:
23
23
  gcp_config = load_config_key('gcp_config', 'global', kind="vacConfig")
@@ -82,6 +82,8 @@ def main(args=None):
82
82
  setup_vac_subparser(subparsers)
83
83
  # embed command
84
84
  setup_embedder_subparser(subparsers)
85
+ # swagger generation
86
+ setup_swagger_subparser(subparsers)
85
87
 
86
88
  #TODO: add database setup commands: alloydb and supabase
87
89
 
sunholo/cli/swagger.py ADDED
@@ -0,0 +1,38 @@
1
+ from ..agents.swagger import generate_swagger
2
+ from ..utils.config import load_all_configs
3
+ from .sun_rich import console
4
+
5
+ def cli_swagger(args):
6
+
7
+ configs = load_all_configs()
8
+
9
+ vac_config = args.vac_config_path or configs.get('vacConfig')
10
+ agent_config = args.agent_config_path or configs.get('agentConfig')
11
+ if not agent_config:
12
+ raise ValueError('Need an agentConfig path')
13
+
14
+ if not vac_config:
15
+ raise ValueError('Need a vacConfig path')
16
+
17
+ swag = generate_swagger(vac_config, agent_config)
18
+
19
+ console.print(swag)
20
+
21
+ return swag
22
+
23
+ def setup_swagger_subparser(subparsers):
24
+ """
25
+ Sets up an argparse subparser for the 'swagger' command.
26
+
27
+ By default will use the 'vacConfig' configuration within the folder specified by '_CONFIG_FOLDER'
28
+
29
+ Example command:
30
+ ```bash
31
+ sunholo swagger --config .
32
+ ```
33
+ """
34
+ deploy_parser = subparsers.add_parser('swagger', help='Create a swagger specification based off a "vacConfig" configuration')
35
+ deploy_parser.add_argument('--vac_config_path', help='Path to the vacConfig file. Set _CONFIG_FOLDER env var and place file in there to change default config location.')
36
+ deploy_parser.add_argument('--agent_config_path', help='Path to agentConfig file. Set _CONFIG_FOLDER env var and place file in there to change default config location.')
37
+ deploy_parser.set_defaults(func=cli_swagger)
38
+
@@ -234,6 +234,10 @@ def create_alloydb_table(vector_name, engine, type = "vectorstore", alloydb_conf
234
234
  log.info(f"AlloyDB Table '{table_name}' exists in cache, skipping creation.")
235
235
 
236
236
  return table_name
237
+
238
+ alloydb_table_cache[table_name] = True
239
+ return table_name
240
+
237
241
  log.info(f"# Creating AlloyDB table {table_name}")
238
242
  try:
239
243
  engine.init_vectorstore_table(
@@ -5,8 +5,9 @@ def can_agent_stream(agent_name: str):
5
5
 
6
6
  log.debug(f"agent_type: {agent_name} checking streaming...")
7
7
  endpoints_config = load_config_key(agent_name, "dummy_value", kind="agentConfig")
8
+ post_endpoints = endpoints_config['post']
8
9
 
9
- return 'stream' in endpoints_config
10
+ return 'stream' in post_endpoints
10
11
 
11
12
 
12
13
 
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sunholo
3
- Version: 0.64.6
3
+ Version: 0.64.8
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.64.6.tar.gz
6
+ Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.64.8.tar.gz
7
7
  Author: Holosun ApS
8
8
  Author-email: multivac@sunholo.com
9
9
  License: Apache License, Version 2.0
@@ -1,22 +1,23 @@
1
1
  sunholo/__init__.py,sha256=0CdpufyRKWyZe7J7UKigL6j_qOorM-p0OjHIAuf9M38,864
2
2
  sunholo/logging.py,sha256=hPmB5VgHV9fN2Ze55jNkRx5QNfxRtezYQkhu_RaE8mc,11667
3
- sunholo/agents/__init__.py,sha256=CnlbVohPt-Doth9PyROSlN3P8xMV9j9yS19YE-wCS90,341
3
+ sunholo/agents/__init__.py,sha256=Hb4NXy2rN-83Z0-UDRwX-LXv2R29lcbSFPf8G6q4fZg,380
4
4
  sunholo/agents/chat_history.py,sha256=bkII7PNEbGCaobu2Rnr2rM9dim3BCK0kM-tiWhoI1tw,5219
5
5
  sunholo/agents/dispatch_to_qa.py,sha256=7Dl82DL3Wt-MxpLyCi_Udf8OPvxU6-UXbgP-pojoPuY,8339
6
6
  sunholo/agents/langserve.py,sha256=FdhQjorAY2bMn2rpuabNT6bU3uqSKWrl8DjpH3L_V7k,4375
7
7
  sunholo/agents/pubsub.py,sha256=5hbbhbBGyVWRpt2sAGC5FEheYH1mCCwVUhZEB1S7vGg,1337
8
- sunholo/agents/route.py,sha256=R_j-o2-K0RiDkj8Gt1yZivBohcI9SCl-8j79h03H1mQ,2109
8
+ sunholo/agents/route.py,sha256=-O6kljLSPdBOsysKyn6hZvXZlNlqNDHGwWl2WwR6Tss,2304
9
9
  sunholo/agents/special_commands.py,sha256=ecD5jrBVXo170sdgPILi0m_m_4nRFEv6qKn5zYEvEK8,6494
10
+ sunholo/agents/swagger.py,sha256=WaF7uecKPAqhBBB2mwPvJ87YkFmYLhGCYGWpVsBN53Q,8428
10
11
  sunholo/agents/fastapi/__init__.py,sha256=S_pj4_bTUmDGoq_exaREHlOKThi0zTuGT0VZY0YfODQ,88
11
12
  sunholo/agents/fastapi/base.py,sha256=clk76cHbUAvU0OYJrRfCWX_5f0ACbhDsIzYBhI3wyoE,2514
12
13
  sunholo/agents/fastapi/qna_routes.py,sha256=DgK4Btu5XriOC1JaRQ4G_nWEjJfnQ0J5pyLanF6eF1g,3857
13
14
  sunholo/agents/flask/__init__.py,sha256=uqfHNw2Ru3EJ4dJEcbp86h_lkquBQPMxZbjhV_xe3rs,72
14
15
  sunholo/agents/flask/base.py,sha256=FgSaCODyoTtlstJtsqlLPScdgRUtv9_plxftdzHdVFo,809
15
- sunholo/agents/flask/qna_routes.py,sha256=DWKpOl515MfewIvvVAwT-EbWLnjhg_bcBVFJVDeVW_8,15418
16
+ sunholo/agents/flask/qna_routes.py,sha256=9wJC_SDbn7A6EzqsbkQicApztAzvvtKvs6cztXhh9Dw,19027
16
17
  sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
17
18
  sunholo/archive/archive.py,sha256=C-UhG5x-XtZ8VheQp92IYJqgD0V3NFQjniqlit94t18,1197
18
19
  sunholo/auth/__init__.py,sha256=4owDjSaWYkbTlPK47UHTOC0gCWbZsqn4ZIEw5NWZTlg,28
19
- sunholo/auth/run.py,sha256=SoXkyRSSO3ln4Uq71Zj2J2P9_TRp0Pg_wU1D9kI24Io,2690
20
+ sunholo/auth/run.py,sha256=1ATGHM1ji-08oDINltfTOabYqG3_nQqL4cNpw-3l4L8,2690
20
21
  sunholo/bots/__init__.py,sha256=EMFd7e2z68l6pzYOnkzHbLd2xJRvxTKFRNCTuhZ8hIw,130
21
22
  sunholo/bots/discord.py,sha256=cCFae5K1BCa6JVkWGLh_iZ9qFO1JpXb6K4eJrlDfEro,2442
22
23
  sunholo/bots/github_webhook.py,sha256=5pQPRLM_wxxcILVaIzUDV8Kt7Arcm2dL1r1kMMHA524,9629
@@ -31,8 +32,8 @@ sunholo/chunker/pdfs.py,sha256=daCZ1xjn1YvxlifIyxskWNpLJLe-Q9D_Jq12MWx3tZo,2473
31
32
  sunholo/chunker/publish.py,sha256=GNXV6IPdKM2GZUcjGXIERu49D0ITYtizsLIktKVtMjM,2768
32
33
  sunholo/chunker/splitter.py,sha256=FLkDhkePkg_zGQpFBK13Cznw575D-Rf9pcaCpc1HUxY,6726
33
34
  sunholo/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- sunholo/cli/chat_vac.py,sha256=RbhKICZtWZEPwL9wFmTNzhCWKHHRmNSqQHIfA-wi04U,17820
35
- sunholo/cli/cli.py,sha256=1-grjOE5sB5k0wrccsqCWSXB1vfrYNgdHBFH5F94pa0,3632
35
+ sunholo/cli/chat_vac.py,sha256=uksCsOrkEvGXIpG_TTy8rUE3qLdxfUQaxR9MpyZQWFs,17872
36
+ sunholo/cli/cli.py,sha256=8e00HBN6eYIUJ8cnvKteBJNn7aZPRMk4b82jwcGg9D4,3741
36
37
  sunholo/cli/cli_init.py,sha256=JMZ9AX2cPDZ-_mv3adiv2ToFVNyRPtjk9Biszl1kiR0,2358
37
38
  sunholo/cli/configs.py,sha256=QUM9DvKOdZmEQRM5uI3Nh887T0YDiSMr7O240zTLqws,4546
38
39
  sunholo/cli/deploy.py,sha256=zxdwUsRTRMC8U5vyRv0JiKBLFn84Ug_Tc88-_h9hJSs,1609
@@ -40,12 +41,13 @@ sunholo/cli/embedder.py,sha256=w7LT1CANSoQbOz8xAP3Zt4C_hP4lzGJOf8XD2jY5jBQ,7291
40
41
  sunholo/cli/merge_texts.py,sha256=U9vdMwKmcPoc6iPOWX5MKSxn49dNGbNzVLw8ui5PhEU,1823
41
42
  sunholo/cli/run_proxy.py,sha256=8mrZj0GPYO1q5e6cxej-PHdns5pGguWoDrX7RFg0FWo,11581
42
43
  sunholo/cli/sun_rich.py,sha256=UpMqeJ0C8i0pkue1AHnnyyX0bFJ9zZeJ7HBR6yhuA8A,54
44
+ sunholo/cli/swagger.py,sha256=Sa4FuWifyoPow_3DrqvfVIbmaZwGnPmLY1XQjOs7M1g,1397
43
45
  sunholo/components/__init__.py,sha256=IDoylb74zFKo6NIS3RQqUl0PDFBGVxM1dfUmO7OJ44U,176
44
46
  sunholo/components/llm.py,sha256=T4we3tGmqUj4tPwxQr9M6AXv_BALqZV_dRSvINan-oU,10374
45
47
  sunholo/components/retriever.py,sha256=jAgcmEM_D2Qfb3hYqHVZMZMLUEUqUbqmhD6G5czmEas,3820
46
48
  sunholo/components/vectorstore.py,sha256=lB8vx_N6eBA44orNeVo1WRn0Q8GCIjvPPT9AfiPWBWE,5620
47
49
  sunholo/database/__init__.py,sha256=Zz0Shcq-CtStf9rJGIYB_Ybzb8rY_Q9mfSj-nviM490,241
48
- sunholo/database/alloydb.py,sha256=zvT50Df7r-jJPo5lEEWbjlXzVr0KuqN6WINgRtiSyxo,17014
50
+ sunholo/database/alloydb.py,sha256=Myk1l97c7cMgZIk3eiJiJzjQW0GLNTlGqbJJwxFIDdQ,17122
49
51
  sunholo/database/database.py,sha256=UDHkceiEvJmS3esQX2LYEjEMrHcogN_JHuJXoVWCH3M,7354
50
52
  sunholo/database/lancedb.py,sha256=2rAbJVusMrm5TPtVTsUtmwn0z1iZ_wvbKhc6eyT6ClE,708
51
53
  sunholo/database/static_dbs.py,sha256=aOyU3AJ-Dzz3qSNjbuN2293cfYw5PhkcQuQxdwPMJ4w,435
@@ -84,7 +86,7 @@ sunholo/qna/retry.py,sha256=gFgOf9AxrZMIO9OwOYu1EW7rhNhyfnw_o4XAsNLBOVQ,2021
84
86
  sunholo/streaming/__init__.py,sha256=MpbydI2UYo_adttPQFkxNM33b-QRyNEbrKJx0C2AGPc,241
85
87
  sunholo/streaming/content_buffer.py,sha256=fWcg0oTf470M3U40VAChfmHmWRFgRD8VaT90jNfBCH0,6455
86
88
  sunholo/streaming/langserve.py,sha256=4AeNt4FPv461s20_5q17Nx83cHjK7Dl3gVOcWAxMgOk,6350
87
- sunholo/streaming/stream_lookup.py,sha256=vUeQS7-QFXMIqN2hIIA9syjxVVIjkxQvuBkxsH33dYM,309
89
+ sunholo/streaming/stream_lookup.py,sha256=uTTUjf96mV7OCc-Sc8N09Fpu5g0T_mD_HbSzivtHMFQ,353
88
90
  sunholo/streaming/streaming.py,sha256=9z6pXINEopuL_Z1RnmgXAoZJum9dzyuOxqYtEYnjf8w,16405
89
91
  sunholo/summarise/__init__.py,sha256=MZk3dblUMODcPb1crq4v-Z508NrFIpkSWNf9FIO8BcU,38
90
92
  sunholo/summarise/summarise.py,sha256=C3HhjepTjUhUC8FLk4jMQIBvq1BcORniwuTFHjPVhVo,3784
@@ -102,9 +104,9 @@ sunholo/vertex/__init__.py,sha256=JvHcGFuv6R_nAhY2AdoqqhMpJ5ugeWPZ_svGhWrObBk,13
102
104
  sunholo/vertex/init.py,sha256=JDMUaBRdednzbKF-5p33qqLit2LMsvgvWW-NRz0AqO0,1801
103
105
  sunholo/vertex/memory_tools.py,sha256=8F1iTWnqEK9mX4W5RzCVKIjydIcNp6OFxjn_dtQ3GXo,5379
104
106
  sunholo/vertex/safety.py,sha256=3meAX0HyGZYrH7rXPUAHxtI_3w_zoy_RX7Shtkoa660,1275
105
- sunholo-0.64.6.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
106
- sunholo-0.64.6.dist-info/METADATA,sha256=ShQPolb2mmJyt1EJIc6GccsHjb_aPwbHInoS6H08Nl8,5971
107
- sunholo-0.64.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
108
- sunholo-0.64.6.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
109
- sunholo-0.64.6.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
110
- sunholo-0.64.6.dist-info/RECORD,,
107
+ sunholo-0.64.8.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
108
+ sunholo-0.64.8.dist-info/METADATA,sha256=6m6jy17jtXnhV0pL6yb9jx0_6kc6Y1fs7fRX66Ce8W8,5971
109
+ sunholo-0.64.8.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
110
+ sunholo-0.64.8.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
111
+ sunholo-0.64.8.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
112
+ sunholo-0.64.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5