sunholo 0.140.11__py3-none-any.whl → 0.140.12__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.
@@ -6,7 +6,38 @@ from collections import defaultdict
6
6
  from .timedelta import format_timedelta
7
7
 
8
8
  class ConfigManager:
9
- def __init__(self, vector_name: str, validate:bool=True):
9
+ # Class-level cache for instances
10
+ _instances = {}
11
+ _instance_cache_time = {}
12
+ _instance_cache_duration = timedelta(minutes=30) # Cache instances for 30 minutes
13
+
14
+ def __new__(cls, vector_name: str, validate: bool = True):
15
+ """
16
+ Override __new__ to implement instance caching.
17
+ Returns existing instance if available and not expired.
18
+ """
19
+ current_time = datetime.now()
20
+ cache_key = (vector_name, validate)
21
+
22
+ # Check if we have a cached instance
23
+ if cache_key in cls._instances:
24
+ cached_time = cls._instance_cache_time.get(cache_key)
25
+ if cached_time and (current_time - cached_time) < cls._instance_cache_duration:
26
+ # Return cached instance
27
+ return cls._instances[cache_key]
28
+ else:
29
+ # Cache expired, remove from cache
30
+ del cls._instances[cache_key]
31
+ if cache_key in cls._instance_cache_time:
32
+ del cls._instance_cache_time[cache_key]
33
+
34
+ # Create new instance
35
+ instance = super().__new__(cls)
36
+ cls._instances[cache_key] = instance
37
+ cls._instance_cache_time[cache_key] = current_time
38
+ return instance
39
+
40
+ def __init__(self, vector_name: str, validate: bool = True):
10
41
  """
11
42
  Initialize the ConfigManager with a vector name.
12
43
  Requires a local config/ folder holding your configuration files or the env var VAC_CONFIG_FOLDER to be set.
@@ -24,6 +55,10 @@ class ConfigManager:
24
55
  agent = config.vacConfig("agent")
25
56
  ```
26
57
  """
58
+ # Prevent re-initialization of cached instances
59
+ if hasattr(self, '_initialized'):
60
+ return
61
+
27
62
  if os.getenv("VAC_CONFIG_FOLDER") is None:
28
63
  print("WARNING: No VAC_CONFIG_FOLDER environment variable was specified")
29
64
  local_config_folder = os.path.join(os.getcwd(), "config")
@@ -39,11 +74,68 @@ class ConfigManager:
39
74
  self.local_config_folder = local_config_folder
40
75
  self.configs_by_kind = self.load_all_configs()
41
76
  self.validate = validate
77
+ self._initialized = True
42
78
 
43
79
  test_agent = self.vacConfig("agent")
44
80
  if not test_agent and self.vector_name != "global" and self.validate:
45
81
  print(f"WARNING: No vacConfig.agent found for {self.vector_name} - are you in right folder? {local_config_folder=} {self.config_folder=}")
46
82
 
83
+ @classmethod
84
+ def get_instance(cls, vector_name: str, validate: bool = True):
85
+ """
86
+ Alternative class method to get an instance. This is more explicit than using __new__.
87
+
88
+ Args:
89
+ vector_name (str): The name of the vector in the configuration files.
90
+ validate (bool): Whether to validate the configurations
91
+
92
+ Returns:
93
+ ConfigManager: The ConfigManager instance (cached or new)
94
+ """
95
+ return cls(vector_name, validate)
96
+
97
+ @classmethod
98
+ def clear_instance_cache(cls, vector_name: str = None, validate: bool = None):
99
+ """
100
+ Clear the instance cache. Useful for forcing fresh instances.
101
+
102
+ Args:
103
+ vector_name (str, optional): If provided, only clear cache for this vector_name
104
+ validate (bool, optional): If provided along with vector_name, clear specific cache entry
105
+ """
106
+ if vector_name is not None:
107
+ if validate is not None:
108
+ # Clear specific cache entry
109
+ cache_key = (vector_name, validate)
110
+ if cache_key in cls._instances:
111
+ del cls._instances[cache_key]
112
+ if cache_key in cls._instance_cache_time:
113
+ del cls._instance_cache_time[cache_key]
114
+ else:
115
+ # Clear all entries for this vector_name
116
+ keys_to_remove = [key for key in cls._instances.keys() if key[0] == vector_name]
117
+ for key in keys_to_remove:
118
+ del cls._instances[key]
119
+ if key in cls._instance_cache_time:
120
+ del cls._instance_cache_time[key]
121
+ else:
122
+ # Clear all cache
123
+ cls._instances.clear()
124
+ cls._instance_cache_time.clear()
125
+
126
+ @classmethod
127
+ def get_cached_instances(cls):
128
+ """
129
+ Get information about currently cached instances.
130
+
131
+ Returns:
132
+ dict: Dictionary with cache keys and their creation times
133
+ """
134
+ return {
135
+ key: cls._instance_cache_time.get(key)
136
+ for key in cls._instances.keys()
137
+ }
138
+
47
139
  def load_all_configs(self):
48
140
  """
49
141
  Load all configuration files from the specified directories into a dictionary.
@@ -251,4 +343,4 @@ class ConfigManager:
251
343
  if key in agents:
252
344
  return agents[key]
253
345
  else:
254
- return None
346
+ return None
@@ -0,0 +1,522 @@
1
+ Metadata-Version: 2.4
2
+ Name: sunholo
3
+ Version: 0.140.12
4
+ Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
+ Author-email: Holosun ApS <multivac@sunholo.com>
6
+ License: Apache License, Version 2.0
7
+ Project-URL: Homepage, https://github.com/sunholo-data/sunholo-py
8
+ Project-URL: Download, https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.118.0.tar.gz
9
+ Keywords: llms,devops,google_cloud_platform
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Build Tools
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE.txt
21
+ Requires-Dist: aiohttp
22
+ Requires-Dist: google-auth
23
+ Requires-Dist: ollama>=0.4.7
24
+ Requires-Dist: pillow>=11.0.0
25
+ Requires-Dist: pydantic
26
+ Requires-Dist: requests
27
+ Requires-Dist: ruamel.yaml
28
+ Requires-Dist: tenacity
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest; extra == "test"
31
+ Requires-Dist: pytest-cov; extra == "test"
32
+ Provides-Extra: all
33
+ Requires-Dist: aiofiles; extra == "all"
34
+ Requires-Dist: aiohttp; extra == "all"
35
+ Requires-Dist: anthropic[vertex]; extra == "all"
36
+ Requires-Dist: asyncpg; extra == "all"
37
+ Requires-Dist: azure-identity; extra == "all"
38
+ Requires-Dist: azure-storage-blob; extra == "all"
39
+ Requires-Dist: fastapi; extra == "all"
40
+ Requires-Dist: flask; extra == "all"
41
+ Requires-Dist: google-auth; extra == "all"
42
+ Requires-Dist: google-auth-httplib2; extra == "all"
43
+ Requires-Dist: google-auth-oauthlib; extra == "all"
44
+ Requires-Dist: google-cloud-aiplatform>=1.58.0; extra == "all"
45
+ Requires-Dist: google-api-python-client; extra == "all"
46
+ Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
47
+ Requires-Dist: google-cloud-bigquery; extra == "all"
48
+ Requires-Dist: google-cloud-build; extra == "all"
49
+ Requires-Dist: google-cloud-service-control; extra == "all"
50
+ Requires-Dist: google-cloud-logging; extra == "all"
51
+ Requires-Dist: google-cloud-storage; extra == "all"
52
+ Requires-Dist: google-cloud-pubsub; extra == "all"
53
+ Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "all"
54
+ Requires-Dist: google-cloud-texttospeech; extra == "all"
55
+ Requires-Dist: google-generativeai>=0.7.1; extra == "all"
56
+ Requires-Dist: google-genai>=0.2.2; extra == "all"
57
+ Requires-Dist: gunicorn; extra == "all"
58
+ Requires-Dist: httpcore; extra == "all"
59
+ Requires-Dist: httpx; extra == "all"
60
+ Requires-Dist: jsonschema; extra == "all"
61
+ Requires-Dist: lancedb; extra == "all"
62
+ Requires-Dist: langchain>=0.2.16; extra == "all"
63
+ Requires-Dist: langchain-experimental>=0.0.61; extra == "all"
64
+ Requires-Dist: langchain-community>=0.2.11; extra == "all"
65
+ Requires-Dist: langchain-openai>=0.3.2; extra == "all"
66
+ Requires-Dist: langchain-google-genai>=2.0.9; extra == "all"
67
+ Requires-Dist: langchain_google_alloydb_pg; extra == "all"
68
+ Requires-Dist: langchain-anthropic>=0.1.23; extra == "all"
69
+ Requires-Dist: langchain-google-vertexai; extra == "all"
70
+ Requires-Dist: langchain-unstructured; extra == "all"
71
+ Requires-Dist: langfuse; extra == "all"
72
+ Requires-Dist: mcp; extra == "all"
73
+ Requires-Dist: numpy; extra == "all"
74
+ Requires-Dist: opencv-python; extra == "all"
75
+ Requires-Dist: pg8000; extra == "all"
76
+ Requires-Dist: pgvector; extra == "all"
77
+ Requires-Dist: pillow; extra == "all"
78
+ Requires-Dist: playwright; extra == "all"
79
+ Requires-Dist: psutil; extra == "all"
80
+ Requires-Dist: psycopg2-binary; extra == "all"
81
+ Requires-Dist: pydantic; extra == "all"
82
+ Requires-Dist: pypdf; extra == "all"
83
+ Requires-Dist: python-hcl2; extra == "all"
84
+ Requires-Dist: python-socketio; extra == "all"
85
+ Requires-Dist: pytesseract; extra == "all"
86
+ Requires-Dist: requests; extra == "all"
87
+ Requires-Dist: rich; extra == "all"
88
+ Requires-Dist: sounddevice; extra == "all"
89
+ Requires-Dist: supabase; extra == "all"
90
+ Requires-Dist: tabulate; extra == "all"
91
+ Requires-Dist: tantivy; extra == "all"
92
+ Requires-Dist: tenacity; extra == "all"
93
+ Requires-Dist: tiktoken; extra == "all"
94
+ Requires-Dist: unstructured[all-docs,local-inference]; extra == "all"
95
+ Requires-Dist: xlwings; extra == "all"
96
+ Provides-Extra: langchain
97
+ Requires-Dist: langchain; extra == "langchain"
98
+ Requires-Dist: langchain_experimental; extra == "langchain"
99
+ Requires-Dist: langchain-community; extra == "langchain"
100
+ Requires-Dist: langsmith; extra == "langchain"
101
+ Requires-Dist: langchain-unstructured; extra == "langchain"
102
+ Provides-Extra: azure
103
+ Requires-Dist: azure-identity; extra == "azure"
104
+ Requires-Dist: azure-storage-blob; extra == "azure"
105
+ Provides-Extra: cli
106
+ Requires-Dist: jsonschema>=4.21.1; extra == "cli"
107
+ Requires-Dist: rich; extra == "cli"
108
+ Provides-Extra: database
109
+ Requires-Dist: asyncpg; extra == "database"
110
+ Requires-Dist: supabase; extra == "database"
111
+ Requires-Dist: sqlalchemy; extra == "database"
112
+ Requires-Dist: pg8000; extra == "database"
113
+ Requires-Dist: pgvector; extra == "database"
114
+ Requires-Dist: psycopg2-binary; extra == "database"
115
+ Requires-Dist: lancedb; extra == "database"
116
+ Requires-Dist: tantivy; extra == "database"
117
+ Provides-Extra: pipeline
118
+ Requires-Dist: GitPython; extra == "pipeline"
119
+ Requires-Dist: lark; extra == "pipeline"
120
+ Requires-Dist: langchain>=0.2.16; extra == "pipeline"
121
+ Requires-Dist: langchain-unstructured; extra == "pipeline"
122
+ Requires-Dist: psutil; extra == "pipeline"
123
+ Requires-Dist: pypdf; extra == "pipeline"
124
+ Requires-Dist: pytesseract; extra == "pipeline"
125
+ Requires-Dist: tabulate; extra == "pipeline"
126
+ Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
127
+ Provides-Extra: gcp
128
+ Requires-Dist: aiofiles; extra == "gcp"
129
+ Requires-Dist: anthropic[vertex]; extra == "gcp"
130
+ Requires-Dist: google-api-python-client; extra == "gcp"
131
+ Requires-Dist: google-auth-httplib2; extra == "gcp"
132
+ Requires-Dist: google-auth-oauthlib; extra == "gcp"
133
+ Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "gcp"
134
+ Requires-Dist: google-cloud-aiplatform>=1.58.0; extra == "gcp"
135
+ Requires-Dist: google-cloud-bigquery; extra == "gcp"
136
+ Requires-Dist: google-cloud-build; extra == "gcp"
137
+ Requires-Dist: google-cloud-service-control; extra == "gcp"
138
+ Requires-Dist: google-cloud-storage; extra == "gcp"
139
+ Requires-Dist: google-cloud-logging; extra == "gcp"
140
+ Requires-Dist: google-cloud-pubsub; extra == "gcp"
141
+ Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "gcp"
142
+ Requires-Dist: google-cloud-texttospeech; extra == "gcp"
143
+ Requires-Dist: google-genai>=0.2.2; extra == "gcp"
144
+ Requires-Dist: google-generativeai>=0.8.3; extra == "gcp"
145
+ Requires-Dist: langchain; extra == "gcp"
146
+ Requires-Dist: langchain-google-genai>=2.0.0; extra == "gcp"
147
+ Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
148
+ Requires-Dist: langchain-google-vertexai; extra == "gcp"
149
+ Requires-Dist: pillow; extra == "gcp"
150
+ Provides-Extra: ollama
151
+ Requires-Dist: pillow; extra == "ollama"
152
+ Requires-Dist: ollama>=0.4.7; extra == "ollama"
153
+ Provides-Extra: openai
154
+ Requires-Dist: langchain-openai>=0.3.2; extra == "openai"
155
+ Requires-Dist: tiktoken; extra == "openai"
156
+ Provides-Extra: anthropic
157
+ Requires-Dist: langchain-anthropic>=0.1.23; extra == "anthropic"
158
+ Requires-Dist: mcp; extra == "anthropic"
159
+ Provides-Extra: tools
160
+ Requires-Dist: openapi-spec-validator; extra == "tools"
161
+ Requires-Dist: playwright; extra == "tools"
162
+ Provides-Extra: http
163
+ Requires-Dist: fastapi; extra == "http"
164
+ Requires-Dist: flask; extra == "http"
165
+ Requires-Dist: gunicorn; extra == "http"
166
+ Requires-Dist: httpcore; extra == "http"
167
+ Requires-Dist: httpx; extra == "http"
168
+ Requires-Dist: langchain; extra == "http"
169
+ Requires-Dist: langfuse; extra == "http"
170
+ Requires-Dist: python-socketio; extra == "http"
171
+ Requires-Dist: requests; extra == "http"
172
+ Requires-Dist: tenacity; extra == "http"
173
+ Provides-Extra: excel
174
+ Requires-Dist: xlwings; extra == "excel"
175
+ Requires-Dist: requests; extra == "excel"
176
+ Requires-Dist: rich; extra == "excel"
177
+ Provides-Extra: iac
178
+ Requires-Dist: python-hcl2; extra == "iac"
179
+ Provides-Extra: tts
180
+ Requires-Dist: google-cloud-texttospeech; extra == "tts"
181
+ Requires-Dist: numpy; extra == "tts"
182
+ Requires-Dist: sounddevice; extra == "tts"
183
+ Provides-Extra: video
184
+ Requires-Dist: opencv-python; extra == "video"
185
+ Dynamic: license-file
186
+
187
+ # Sunholo Python Library
188
+
189
+ [![PyPi Version](https://img.shields.io/pypi/v/sunholo.svg)](https://pypi.python.org/pypi/sunholo/)
190
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
191
+ [![Python Version](https://img.shields.io/pypi/pyversions/sunholo.svg)](https://pypi.python.org/pypi/sunholo/)
192
+
193
+ 🚀 **AI DevOps framework for building GenAI applications on Google Cloud Platform**
194
+
195
+ Sunholo is a comprehensive Python framework that streamlines the development, deployment, and management of Generative AI applications (VACs - Virtual Agent Computers). It provides a configuration-driven approach with deep integration into Google Cloud services while supporting multiple AI providers.
196
+
197
+ ## 🎯 What is Sunholo?
198
+
199
+ Sunholo helps you:
200
+ - 🤖 Build conversational AI agents with any LLM provider (Vertex AI, OpenAI, Anthropic, Ollama)
201
+ - ☁️ Deploy to Google Cloud Run with automatic scaling
202
+ - 🗄️ Use AlloyDB and Discovery Engine for vector storage and search
203
+ - 🔄 Handle streaming responses and async processing
204
+ - 📄 Process documents with chunking and embedding pipelines
205
+ - 🔧 Manage complex configurations with YAML files
206
+ - 🎨 Create APIs, web apps, and chat bots
207
+
208
+ ## 🚀 Quick Start
209
+
210
+ ### Prerequisites
211
+
212
+ Install [uv](https://docs.astral.sh/uv/) - a fast, modern Python package manager:
213
+
214
+ ```bash
215
+ # macOS/Linux
216
+ curl -LsSf https://astral.sh/uv/install.sh | sh
217
+
218
+ # Windows
219
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
220
+ ```
221
+
222
+ ### Installation
223
+
224
+ ```bash
225
+ # Install with CLI tools (recommended)
226
+ uv tool install --from "sunholo[cli]" sunholo
227
+
228
+ # Install with all features including GCP
229
+ uv tool install --from "sunholo[cli]" sunholo --with "sunholo[all]"
230
+ ```
231
+
232
+ ### Your First VAC
233
+
234
+ 1. **Initialize a new project:**
235
+ ```bash
236
+ sunholo init my-ai-agent
237
+ cd my-ai-agent
238
+ ```
239
+
240
+ 2. **Configure your AI agent:**
241
+ Edit `config/vac_config.yaml`:
242
+ ```yaml
243
+ kind: vacConfig
244
+ apiVersion: v1
245
+ vac:
246
+ my-agent:
247
+ llm: vertex
248
+ model: gemini-1.5-pro
249
+ agent: simple
250
+ description: "My AI agent powered by Google Cloud"
251
+ ```
252
+
253
+ 3. **Chat with your agent locally:**
254
+ ```bash
255
+ sunholo vac chat my-agent
256
+ ```
257
+
258
+ 4. **Deploy to Google Cloud Run:**
259
+ ```bash
260
+ sunholo deploy my-agent
261
+ ```
262
+
263
+ ## 📋 Features
264
+
265
+ ### Core Capabilities
266
+
267
+ - **Multi-Model Support**: Integrate Vertex AI, OpenAI, Anthropic, Ollama in one app
268
+ - **Document Processing**: Chunk, embed, and index documents with Discovery Engine
269
+ - **Vector Databases**: Native support for AlloyDB, LanceDB, Supabase
270
+ - **Streaming**: Real-time response streaming for chat applications
271
+ - **Async Processing**: Pub/Sub integration for background tasks
272
+ - **Authentication**: Built-in Google Cloud IAM and custom auth
273
+
274
+ ### Google Cloud Integration
275
+
276
+ - **Vertex AI**: Access Gemini, PaLM, and custom models
277
+ - **AlloyDB**: PostgreSQL-compatible vector database
278
+ - **Discovery Engine**: Enterprise search and RAG
279
+ - **Cloud Run**: Serverless deployment
280
+ - **Cloud Storage**: Document and file management
281
+ - **Pub/Sub**: Asynchronous message processing
282
+ - **Cloud Logging**: Centralized logging
283
+
284
+ ### Framework Support
285
+
286
+ - **Web Frameworks**: Flask and FastAPI templates
287
+ - **AI Frameworks**: LangChain and LlamaIndex integration
288
+ - **Observability**: Langfuse for tracing and monitoring
289
+ - **API Standards**: OpenAI-compatible endpoints
290
+
291
+ ## 🛠 Installation Options
292
+
293
+ ### Using uv
294
+
295
+ ```bash
296
+ # Core CLI features
297
+ uv tool install --from "sunholo[cli]" sunholo
298
+
299
+ # With Google Cloud Platform integration
300
+ uv tool install --from "sunholo[cli]" sunholo --with "sunholo[gcp]"
301
+
302
+ # With specific LLM providers
303
+ uv tool install --from "sunholo[cli]" sunholo --with "sunholo[openai]"
304
+ uv tool install --from "sunholo[cli]" sunholo --with "sunholo[anthropic]"
305
+
306
+ # With database support
307
+ uv tool install --from "sunholo[cli]" sunholo --with "sunholo[database]"
308
+
309
+ # Everything
310
+ uv tool install --from "sunholo[cli]" sunholo --with "sunholo[all]"
311
+ ```
312
+
313
+ ### Managing Installations
314
+
315
+ ```bash
316
+ # Upgrade
317
+ uv tool upgrade sunholo
318
+
319
+ # List installed
320
+ uv tool list
321
+
322
+ # Uninstall
323
+ uv tool uninstall sunholo
324
+ ```
325
+
326
+ ### Development Setup
327
+
328
+ ```bash
329
+ # Clone repository
330
+ git clone https://github.com/sunholo-data/sunholo-py.git
331
+ cd sunholo-py
332
+
333
+ # Install in development mode
334
+ uv venv
335
+ uv pip install -e ".[all]"
336
+
337
+ # Run tests
338
+ pytest tests/
339
+ ```
340
+
341
+ ## ⚙️ Configuration
342
+
343
+ Sunholo uses YAML configuration files:
344
+
345
+ ```yaml
346
+ # config/vac_config.yaml
347
+ kind: vacConfig
348
+ apiVersion: v1
349
+ gcp_config:
350
+ project_id: my-gcp-project
351
+ location: us-central1
352
+ vac:
353
+ my-agent:
354
+ llm: vertex
355
+ model: gemini-1.5-pro
356
+ agent: langchain
357
+ memory:
358
+ - alloydb:
359
+ project_id: my-gcp-project
360
+ region: us-central1
361
+ cluster: my-cluster
362
+ instance: my-instance
363
+ tools:
364
+ - search
365
+ - calculator
366
+ ```
367
+
368
+ ## 🔧 CLI Commands
369
+
370
+ ```bash
371
+ # Project Management
372
+ sunholo init <project-name> # Create new project
373
+ sunholo list-configs # List all configurations
374
+ sunholo list-configs --validate # Validate configs
375
+
376
+ # Development
377
+ sunholo vac chat <vac-name> # Chat with a VAC locally
378
+ sunholo vac list # List available VACs
379
+ sunholo proxy start <service> # Start local proxy to cloud service
380
+
381
+ # Deployment
382
+ sunholo deploy <vac-name> # Deploy to Cloud Run
383
+ sunholo deploy <vac-name> --dev # Deploy to dev environment
384
+
385
+ # Document Processing
386
+ sunholo embed <vac-name> # Embed documents
387
+ sunholo merge-text <folder> <output> # Merge files for context
388
+
389
+ # Cloud Services
390
+ sunholo discovery-engine create <name> # Create Discovery Engine
391
+ sunholo proxy list # List running proxies
392
+ ```
393
+
394
+ ## 📝 Examples
395
+
396
+ ### Vertex AI Chat with Memory
397
+
398
+ ```python
399
+ from sunholo.utils import ConfigManager
400
+ from sunholo.components import pick_llm
401
+ from sunholo.agents import memory_client
402
+
403
+ config = ConfigManager('my-agent')
404
+ llm = pick_llm(config=config)
405
+ memory = memory_client(config=config)
406
+
407
+ # Chat with context
408
+ response = llm.invoke("What is Google Cloud?")
409
+ memory.add_message("user", "What is Google Cloud?")
410
+ memory.add_message("assistant", response)
411
+ ```
412
+
413
+ ### Document Processing with Discovery Engine
414
+
415
+ ```python
416
+ from sunholo.discovery_engine import DiscoveryEngineClient
417
+ from sunholo.chunker import chunk_doc
418
+
419
+ # Initialize client
420
+ client = DiscoveryEngineClient(
421
+ project_id='my-project',
422
+ data_store_id='my-datastore'
423
+ )
424
+
425
+ # Process and index document
426
+ chunks = chunk_doc.chunk_file("document.pdf", chunk_size=1000)
427
+ client.import_documents(chunks)
428
+
429
+ # Search
430
+ results = client.search("What is the main topic?")
431
+ ```
432
+
433
+ ### Streaming Flask API
434
+
435
+ ```python
436
+ from sunholo.agents import dispatch_to_qa
437
+
438
+ @app.route('/vac/streaming/<vac_name>', methods=['POST'])
439
+ def streaming_endpoint(vac_name):
440
+ question = request.json.get('user_input')
441
+
442
+ def generate():
443
+ for chunk in dispatch_to_qa(
444
+ question,
445
+ vac_name=vac_name,
446
+ stream=True
447
+ ):
448
+ yield f"data: {chunk}\n\n"
449
+
450
+ return Response(generate(), content_type='text/event-stream')
451
+ ```
452
+
453
+ ### Deploy from Template
454
+
455
+ ```bash
456
+ # Create from template
457
+ sunholo init my-api --template agent
458
+
459
+ # Customize configuration
460
+ cd my-api
461
+ vi config/vac_config.yaml
462
+
463
+ # Test locally
464
+ sunholo vac chat my-agent --local
465
+
466
+ # Deploy to production
467
+ sunholo deploy my-agent
468
+ ```
469
+
470
+ ## 🧪 Testing
471
+
472
+ ```bash
473
+ # Run all tests
474
+ pytest tests/
475
+
476
+ # Run specific test file
477
+ pytest tests/test_config.py
478
+
479
+ # Run with coverage
480
+ pytest --cov=src/sunholo tests/
481
+
482
+ # Run async tests
483
+ pytest tests/test_async_genai2.py
484
+ ```
485
+
486
+ ## 📚 Documentation
487
+
488
+ - 📖 **Full Documentation**: https://dev.sunholo.com/
489
+ - 🎓 **Tutorials**: https://dev.sunholo.com/docs/howto/
490
+ - 🤖 **VAC Examples**: https://github.com/sunholo-data/vacs-public
491
+ - 🎧 **Audio Overview**: [Listen to the NotebookLM podcast](https://drive.google.com/file/d/1GvwRmiYDjPjN2hXQ8plhnVDByu6TmgCQ/view?usp=drive_link)
492
+
493
+ ## 🤝 Contributing
494
+
495
+ We welcome contributions! See our [Contributing Guidelines](CONTRIBUTING.md).
496
+
497
+ 1. Fork the repository
498
+ 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
499
+ 3. Commit your changes (`git commit -m 'Add AmazingFeature'`)
500
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
501
+ 5. Open a Pull Request
502
+
503
+ ## 📜 License
504
+
505
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE.txt) file for details.
506
+
507
+ ```
508
+ Copyright [2024] [Holosun ApS]
509
+
510
+ Licensed under the Apache License, Version 2.0 (the "License");
511
+ you may not use this file except in compliance with the License.
512
+ You may obtain a copy of the License at
513
+
514
+ http://www.apache.org/licenses/LICENSE-2.0
515
+ ```
516
+
517
+ ## 🙏 Support
518
+
519
+ - 📧 Email: multivac@sunholo.com
520
+ - 🐛 Issues: [GitHub Issues](https://github.com/sunholo-data/sunholo-py/issues)
521
+ - 💬 Discussions: [GitHub Discussions](https://github.com/sunholo-data/sunholo-py/discussions)
522
+ - 📖 Documentation: https://dev.sunholo.com/
@@ -151,7 +151,7 @@ sunholo/utils/__init__.py,sha256=Hv02T5L2zYWvCso5hzzwm8FQogwBq0OgtUbN_7Quzqc,89
151
151
  sunholo/utils/api_key.py,sha256=Ct4bIAQZxzPEw14hP586LpVxBAVi_W9Serpy0BK-7KI,244
152
152
  sunholo/utils/big_context.py,sha256=HuP9_r_Nx1jvZHxjMEihgoZAXmnCh80zzsj1fq3mIOg,6021
153
153
  sunholo/utils/config.py,sha256=OeYr4UvhRv94e1OVFab4kuQa5TdbbljQjvhnGlkDewM,9160
154
- sunholo/utils/config_class.py,sha256=uSRiJLj8t5UgWNxaq8W4KPnzxb4SkUJ1avXecDHuP-E,9768
154
+ sunholo/utils/config_class.py,sha256=U0xwyCz68KCJgzyhXd0AmbFnstMBFvZMedb-lLKKa5Q,13363
155
155
  sunholo/utils/config_schema.py,sha256=Wv-ncitzljOhgbDaq9qnFqH5LCuxNv59dTGDWgd1qdk,4189
156
156
  sunholo/utils/gcp.py,sha256=lus1HH8YhFInw6QRKwfvKZq-Lz-2KQg4ips9v1I_3zE,4783
157
157
  sunholo/utils/gcp_project.py,sha256=Fa0IhCX12bZ1ctF_PKN8PNYd7hihEUfb90kilBfUDjg,1411
@@ -168,9 +168,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
168
168
  sunholo/vertex/memory_tools.py,sha256=tBZxqVZ4InTmdBvLlOYwoSEWu4-kGquc-gxDwZCC4FA,7667
169
169
  sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
170
170
  sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
171
- sunholo-0.140.11.dist-info/licenses/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
172
- sunholo-0.140.11.dist-info/METADATA,sha256=5dpzFz8d_yiaY_tXGWGUsAxCHy2TPeQcHcooeZzbIcE,10068
173
- sunholo-0.140.11.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
174
- sunholo-0.140.11.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
175
- sunholo-0.140.11.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
176
- sunholo-0.140.11.dist-info/RECORD,,
171
+ sunholo-0.140.12.dist-info/licenses/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
172
+ sunholo-0.140.12.dist-info/METADATA,sha256=UBt83NkXY5EpTwdtDF5LCOe2IsBXlR1TCVx9EoAuAOA,17116
173
+ sunholo-0.140.12.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
174
+ sunholo-0.140.12.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
175
+ sunholo-0.140.12.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
176
+ sunholo-0.140.12.dist-info/RECORD,,
@@ -1,249 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sunholo
3
- Version: 0.140.11
4
- Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
- Author-email: Holosun ApS <multivac@sunholo.com>
6
- License: Apache License, Version 2.0
7
- Project-URL: Homepage, https://github.com/sunholo-data/sunholo-py
8
- Project-URL: Download, https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.118.0.tar.gz
9
- Keywords: llms,devops,google_cloud_platform
10
- Classifier: Development Status :: 3 - Alpha
11
- Classifier: Intended Audience :: Developers
12
- Classifier: Topic :: Software Development :: Build Tools
13
- Classifier: License :: OSI Approved :: Apache Software License
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.10
16
- Classifier: Programming Language :: Python :: 3.11
17
- Classifier: Programming Language :: Python :: 3.12
18
- Requires-Python: >=3.10
19
- Description-Content-Type: text/markdown
20
- License-File: LICENSE.txt
21
- Requires-Dist: aiohttp
22
- Requires-Dist: google-auth
23
- Requires-Dist: ollama>=0.4.7
24
- Requires-Dist: pillow>=11.0.0
25
- Requires-Dist: pydantic
26
- Requires-Dist: requests
27
- Requires-Dist: ruamel.yaml
28
- Requires-Dist: tenacity
29
- Provides-Extra: test
30
- Requires-Dist: pytest; extra == "test"
31
- Requires-Dist: pytest-cov; extra == "test"
32
- Provides-Extra: all
33
- Requires-Dist: aiofiles; extra == "all"
34
- Requires-Dist: aiohttp; extra == "all"
35
- Requires-Dist: anthropic[vertex]; extra == "all"
36
- Requires-Dist: asyncpg; extra == "all"
37
- Requires-Dist: azure-identity; extra == "all"
38
- Requires-Dist: azure-storage-blob; extra == "all"
39
- Requires-Dist: fastapi; extra == "all"
40
- Requires-Dist: flask; extra == "all"
41
- Requires-Dist: google-auth; extra == "all"
42
- Requires-Dist: google-auth-httplib2; extra == "all"
43
- Requires-Dist: google-auth-oauthlib; extra == "all"
44
- Requires-Dist: google-cloud-aiplatform>=1.58.0; extra == "all"
45
- Requires-Dist: google-api-python-client; extra == "all"
46
- Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
47
- Requires-Dist: google-cloud-bigquery; extra == "all"
48
- Requires-Dist: google-cloud-build; extra == "all"
49
- Requires-Dist: google-cloud-service-control; extra == "all"
50
- Requires-Dist: google-cloud-logging; extra == "all"
51
- Requires-Dist: google-cloud-storage; extra == "all"
52
- Requires-Dist: google-cloud-pubsub; extra == "all"
53
- Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "all"
54
- Requires-Dist: google-cloud-texttospeech; extra == "all"
55
- Requires-Dist: google-generativeai>=0.7.1; extra == "all"
56
- Requires-Dist: google-genai>=0.2.2; extra == "all"
57
- Requires-Dist: gunicorn; extra == "all"
58
- Requires-Dist: httpcore; extra == "all"
59
- Requires-Dist: httpx; extra == "all"
60
- Requires-Dist: jsonschema; extra == "all"
61
- Requires-Dist: lancedb; extra == "all"
62
- Requires-Dist: langchain>=0.2.16; extra == "all"
63
- Requires-Dist: langchain-experimental>=0.0.61; extra == "all"
64
- Requires-Dist: langchain-community>=0.2.11; extra == "all"
65
- Requires-Dist: langchain-openai>=0.3.2; extra == "all"
66
- Requires-Dist: langchain-google-genai>=2.0.9; extra == "all"
67
- Requires-Dist: langchain_google_alloydb_pg; extra == "all"
68
- Requires-Dist: langchain-anthropic>=0.1.23; extra == "all"
69
- Requires-Dist: langchain-google-vertexai; extra == "all"
70
- Requires-Dist: langchain-unstructured; extra == "all"
71
- Requires-Dist: langfuse; extra == "all"
72
- Requires-Dist: mcp; extra == "all"
73
- Requires-Dist: numpy; extra == "all"
74
- Requires-Dist: opencv-python; extra == "all"
75
- Requires-Dist: pg8000; extra == "all"
76
- Requires-Dist: pgvector; extra == "all"
77
- Requires-Dist: pillow; extra == "all"
78
- Requires-Dist: playwright; extra == "all"
79
- Requires-Dist: psutil; extra == "all"
80
- Requires-Dist: psycopg2-binary; extra == "all"
81
- Requires-Dist: pydantic; extra == "all"
82
- Requires-Dist: pypdf; extra == "all"
83
- Requires-Dist: python-hcl2; extra == "all"
84
- Requires-Dist: python-socketio; extra == "all"
85
- Requires-Dist: pytesseract; extra == "all"
86
- Requires-Dist: requests; extra == "all"
87
- Requires-Dist: rich; extra == "all"
88
- Requires-Dist: sounddevice; extra == "all"
89
- Requires-Dist: supabase; extra == "all"
90
- Requires-Dist: tabulate; extra == "all"
91
- Requires-Dist: tantivy; extra == "all"
92
- Requires-Dist: tenacity; extra == "all"
93
- Requires-Dist: tiktoken; extra == "all"
94
- Requires-Dist: unstructured[all-docs,local-inference]; extra == "all"
95
- Requires-Dist: xlwings; extra == "all"
96
- Provides-Extra: langchain
97
- Requires-Dist: langchain; extra == "langchain"
98
- Requires-Dist: langchain_experimental; extra == "langchain"
99
- Requires-Dist: langchain-community; extra == "langchain"
100
- Requires-Dist: langsmith; extra == "langchain"
101
- Requires-Dist: langchain-unstructured; extra == "langchain"
102
- Provides-Extra: azure
103
- Requires-Dist: azure-identity; extra == "azure"
104
- Requires-Dist: azure-storage-blob; extra == "azure"
105
- Provides-Extra: cli
106
- Requires-Dist: jsonschema>=4.21.1; extra == "cli"
107
- Requires-Dist: rich; extra == "cli"
108
- Provides-Extra: database
109
- Requires-Dist: asyncpg; extra == "database"
110
- Requires-Dist: supabase; extra == "database"
111
- Requires-Dist: sqlalchemy; extra == "database"
112
- Requires-Dist: pg8000; extra == "database"
113
- Requires-Dist: pgvector; extra == "database"
114
- Requires-Dist: psycopg2-binary; extra == "database"
115
- Requires-Dist: lancedb; extra == "database"
116
- Requires-Dist: tantivy; extra == "database"
117
- Provides-Extra: pipeline
118
- Requires-Dist: GitPython; extra == "pipeline"
119
- Requires-Dist: lark; extra == "pipeline"
120
- Requires-Dist: langchain>=0.2.16; extra == "pipeline"
121
- Requires-Dist: langchain-unstructured; extra == "pipeline"
122
- Requires-Dist: psutil; extra == "pipeline"
123
- Requires-Dist: pypdf; extra == "pipeline"
124
- Requires-Dist: pytesseract; extra == "pipeline"
125
- Requires-Dist: tabulate; extra == "pipeline"
126
- Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
127
- Provides-Extra: gcp
128
- Requires-Dist: aiofiles; extra == "gcp"
129
- Requires-Dist: anthropic[vertex]; extra == "gcp"
130
- Requires-Dist: google-api-python-client; extra == "gcp"
131
- Requires-Dist: google-auth-httplib2; extra == "gcp"
132
- Requires-Dist: google-auth-oauthlib; extra == "gcp"
133
- Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "gcp"
134
- Requires-Dist: google-cloud-aiplatform>=1.58.0; extra == "gcp"
135
- Requires-Dist: google-cloud-bigquery; extra == "gcp"
136
- Requires-Dist: google-cloud-build; extra == "gcp"
137
- Requires-Dist: google-cloud-service-control; extra == "gcp"
138
- Requires-Dist: google-cloud-storage; extra == "gcp"
139
- Requires-Dist: google-cloud-logging; extra == "gcp"
140
- Requires-Dist: google-cloud-pubsub; extra == "gcp"
141
- Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "gcp"
142
- Requires-Dist: google-cloud-texttospeech; extra == "gcp"
143
- Requires-Dist: google-genai>=0.2.2; extra == "gcp"
144
- Requires-Dist: google-generativeai>=0.8.3; extra == "gcp"
145
- Requires-Dist: langchain; extra == "gcp"
146
- Requires-Dist: langchain-google-genai>=2.0.0; extra == "gcp"
147
- Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
148
- Requires-Dist: langchain-google-vertexai; extra == "gcp"
149
- Requires-Dist: pillow; extra == "gcp"
150
- Provides-Extra: ollama
151
- Requires-Dist: pillow; extra == "ollama"
152
- Requires-Dist: ollama>=0.4.7; extra == "ollama"
153
- Provides-Extra: openai
154
- Requires-Dist: langchain-openai>=0.3.2; extra == "openai"
155
- Requires-Dist: tiktoken; extra == "openai"
156
- Provides-Extra: anthropic
157
- Requires-Dist: langchain-anthropic>=0.1.23; extra == "anthropic"
158
- Requires-Dist: mcp; extra == "anthropic"
159
- Provides-Extra: tools
160
- Requires-Dist: openapi-spec-validator; extra == "tools"
161
- Requires-Dist: playwright; extra == "tools"
162
- Provides-Extra: http
163
- Requires-Dist: fastapi; extra == "http"
164
- Requires-Dist: flask; extra == "http"
165
- Requires-Dist: gunicorn; extra == "http"
166
- Requires-Dist: httpcore; extra == "http"
167
- Requires-Dist: httpx; extra == "http"
168
- Requires-Dist: langchain; extra == "http"
169
- Requires-Dist: langfuse; extra == "http"
170
- Requires-Dist: python-socketio; extra == "http"
171
- Requires-Dist: requests; extra == "http"
172
- Requires-Dist: tenacity; extra == "http"
173
- Provides-Extra: excel
174
- Requires-Dist: xlwings; extra == "excel"
175
- Requires-Dist: requests; extra == "excel"
176
- Requires-Dist: rich; extra == "excel"
177
- Provides-Extra: iac
178
- Requires-Dist: python-hcl2; extra == "iac"
179
- Provides-Extra: tts
180
- Requires-Dist: google-cloud-texttospeech; extra == "tts"
181
- Requires-Dist: numpy; extra == "tts"
182
- Requires-Dist: sounddevice; extra == "tts"
183
- Provides-Extra: video
184
- Requires-Dist: opencv-python; extra == "video"
185
- Dynamic: license-file
186
-
187
- [![PyPi Version](https://img.shields.io/pypi/v/sunholo.svg)](https://pypi.python.org/pypi/sunholo/)
188
-
189
- ## Introduction
190
- This is the Sunholo Python project, a comprehensive toolkit for working with language models and vector stores on Google Cloud Platform. It provides a wide range of functionalities and utilities to facilitate the development and deployment of language model applications.
191
-
192
- Please refer to the website for full documentation at https://dev.sunholo.com/
193
-
194
- ## Listen to the audio file:
195
-
196
- A [NotebookLM](https://notebooklm.google/) generated podcast of the codebase that may help give you an overview of what the library is capable of:
197
-
198
- [Listen to the audio file from Google Drive](https://drive.google.com/file/d/1GvwRmiYDjPjN2hXQ8plhnVDByu6TmgCQ/view?usp=drive_link) or on the website at https://dev.sunholo.com/docs/
199
-
200
- > "Ever wish you could build your own AI?..."
201
-
202
- ## Tests via pytest
203
-
204
- If loading from GitHub, run tests:
205
-
206
- ```bash
207
- pip install pytest
208
- pip install . --use-feature=in-tree-build
209
- pytest tests
210
- ```
211
-
212
- ## Local dev
213
-
214
- ```sh
215
- uv tool install --from "sunholo[cli]" sunholo --with ".[all]"
216
- ```
217
-
218
- ## Demos
219
-
220
- Using https://github.com/charmbracelet/vhs
221
-
222
- ```sh
223
- vhs record > cassette.tape
224
- ```
225
-
226
- Then make gif:
227
-
228
- ```sh
229
- vhs docs/tapes/config-list.tape
230
- ```
231
-
232
-
233
-
234
- ```
235
- Copyright [2024] [Holosun ApS]
236
-
237
- Licensed under the Apache License, Version 2.0 (the "License");
238
- you may not use this file except in compliance with the License.
239
- You may obtain a copy of the License at
240
-
241
- http://www.apache.org/licenses/LICENSE-2.0
242
-
243
- Unless required by applicable law or agreed to in writing, software
244
- distributed under the License is distributed on an "AS IS" BASIS,
245
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
246
- See the License for the specific language governing permissions and
247
- limitations under the License.
248
- ```
249
-