sunholo 0.62.18__tar.gz → 0.64.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sunholo-0.62.18/sunholo.egg-info → sunholo-0.64.3}/PKG-INFO +10 -42
- sunholo-0.64.3/README.md +37 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/setup.py +2 -1
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/flask/qna_routes.py +148 -9
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/auth/run.py +19 -22
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/chat_vac.py +62 -36
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/langfuse/callback.py +3 -4
- sunholo-0.64.3/sunholo/utils/version.py +3 -0
- {sunholo-0.62.18 → sunholo-0.64.3/sunholo.egg-info}/PKG-INFO +10 -42
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo.egg-info/SOURCES.txt +2 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo.egg-info/requires.txt +1 -0
- sunholo-0.64.3/tests/test_chunker.py +23 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/tests/test_dispatch_to_qa.py +7 -1
- sunholo-0.62.18/README.md +0 -70
- {sunholo-0.62.18 → sunholo-0.64.3}/LICENSE.txt +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/MANIFEST.in +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/setup.cfg +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/langserve.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/route.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/archive/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/archive/archive.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/auth/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/bots/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/bots/discord.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/bots/webapp.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/data_to_embed_pubsub.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/images.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/publish.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/cli.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/configs.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/deploy.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/embedder.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/components/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/components/llm.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/components/retriever.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/alloydb.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/database.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/lancedb.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/database/uuid.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/llamaindex/generate.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/logging.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/patches/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/patches/langchain/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/patches/langchain/lancedb.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/patches/langchain/vertexai.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/qna/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/qna/parsers.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/qna/retry.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/big_context.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/config.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/gcp.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/parsers.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/vertex/init.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo/vertex/safety.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/tests/test_chat_history.py +0 -0
- {sunholo-0.62.18 → sunholo-0.64.3}/tests/test_config.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.64.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.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.64.3.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
21
|
Requires-Dist: google-auth
|
|
22
|
+
Requires-Dist: tenacity==8.3.0
|
|
22
23
|
Requires-Dist: langchain
|
|
23
24
|
Requires-Dist: langchain_experimental
|
|
24
25
|
Requires-Dist: langchain-community
|
|
@@ -111,54 +112,21 @@ This is the Sunholo Python project, a comprehensive toolkit for working with lan
|
|
|
111
112
|
|
|
112
113
|
Please refer to the website for full documentation at https://dev.sunholo.com/
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
(draft release https://pypi.org/project/sunholo/ )
|
|
117
|
-
## Table of Contents
|
|
118
|
-
- [Agents](#agents)
|
|
119
|
-
- [Archive](#archive)
|
|
120
|
-
- [Bots](#bots)
|
|
121
|
-
- [Chunker](#chunker)
|
|
122
|
-
- [Components](#components)
|
|
123
|
-
- [Database](#database)
|
|
124
|
-
- [Embedder](#embedder)
|
|
125
|
-
- [PubSub](#pubsub)
|
|
126
|
-
- [QnA](#qna)
|
|
127
|
-
- [Streaming](#streaming)
|
|
128
|
-
- [Summarise](#summarise)
|
|
129
|
-
- [Utils](#utils)
|
|
115
|
+
## Demos
|
|
130
116
|
|
|
117
|
+
Using https://github.com/charmbracelet/vhs
|
|
131
118
|
|
|
132
119
|
```sh
|
|
133
|
-
|
|
120
|
+
vhs record > cassette.tape
|
|
134
121
|
```
|
|
135
122
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
`sunholo` provides utilities to help manage LLM operations on Google Cloud Platform at first, but it is hoped that making it open source will help it support other clouds in the future. A lot of the functionality is not Google Cloud Platform specific, so still may be helpful.
|
|
139
|
-
|
|
140
|
-
It is derived from the Edmonbrain project, the original blog post you can read here: https://code.markedmondson.me/running-llms-on-gcp/ and owes a lot to Langchain ( https://github.com/langchain-ai/langchain )
|
|
141
|
-
|
|
142
|
-
The package includes:
|
|
123
|
+
Then make gif:
|
|
143
124
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* `chunker/` - functions to slice up documents for sending into vector stores
|
|
148
|
-
* `components/` - functions to help configure which LLM, prompt, vectorstore or document retriever you will use based on a yaml config file
|
|
149
|
-
* `database/` - database setup functions and SQL to run on those sources such as Supabase
|
|
150
|
-
* `embedder/` - functions to send chunks into embedding vector stores
|
|
151
|
-
* `pubsub/` - use of PubSub for a message queue between components
|
|
152
|
-
* `qna/` - utilities for running agents such as retry strats and parsing of output/input
|
|
153
|
-
* `streaming/` - creation of streaming responses from LLM bots
|
|
154
|
-
* `summarise/` - creation of summaries of large documents
|
|
155
|
-
* `utils/` - reading configuration files, Google Cloud Platform metadata
|
|
156
|
-
|
|
157
|
-
## Configuration
|
|
125
|
+
```sh
|
|
126
|
+
vhs docs/tapes/config-list.tape
|
|
127
|
+
```
|
|
158
128
|
|
|
159
|
-
The library uses the config specifications that some examples are given in the `config/` folder.
|
|
160
129
|
|
|
161
|
-
When using the functions, make sure to have the `config/` folder in the root of where your application is running (usually `$HOME/config`)
|
|
162
130
|
|
|
163
131
|
```
|
|
164
132
|
Copyright [2024] [Holosun ApS]
|
sunholo-0.64.3/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
## Introduction
|
|
2
|
+
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.
|
|
3
|
+
|
|
4
|
+
Please refer to the website for full documentation at https://dev.sunholo.com/
|
|
5
|
+
|
|
6
|
+
## Demos
|
|
7
|
+
|
|
8
|
+
Using https://github.com/charmbracelet/vhs
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
vhs record > cassette.tape
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Then make gif:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
vhs docs/tapes/config-list.tape
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
Copyright [2024] [Holosun ApS]
|
|
24
|
+
|
|
25
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
26
|
+
you may not use this file except in compliance with the License.
|
|
27
|
+
You may obtain a copy of the License at
|
|
28
|
+
|
|
29
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
30
|
+
|
|
31
|
+
Unless required by applicable law or agreed to in writing, software
|
|
32
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
33
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
34
|
+
See the License for the specific language governing permissions and
|
|
35
|
+
limitations under the License.
|
|
36
|
+
```
|
|
37
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from setuptools import setup, find_packages
|
|
2
2
|
|
|
3
3
|
# Define your base version
|
|
4
|
-
version = '0.
|
|
4
|
+
version = '0.64.3'
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='sunholo',
|
|
@@ -29,6 +29,7 @@ setup(
|
|
|
29
29
|
install_requires=[
|
|
30
30
|
# Base dependencies
|
|
31
31
|
"google-auth", # to check if on gcp
|
|
32
|
+
"tenacity==8.3.0",
|
|
32
33
|
"langchain",
|
|
33
34
|
"langchain_experimental",
|
|
34
35
|
"langchain-community",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import json
|
|
17
17
|
import traceback
|
|
18
18
|
import datetime
|
|
19
|
+
import uuid
|
|
19
20
|
|
|
20
21
|
from ...agents import extract_chat_history, handle_special_commands
|
|
21
22
|
from ...qna.parsers import parse_output
|
|
@@ -23,7 +24,11 @@ from ...streaming import start_streaming_chat
|
|
|
23
24
|
from ...archive import archive_qa
|
|
24
25
|
from ...logging import log
|
|
25
26
|
from ...utils.config import load_config
|
|
26
|
-
|
|
27
|
+
from ...utils.version import sunholo_version
|
|
28
|
+
import os
|
|
29
|
+
from ...gcs.add_file import add_file_to_gcs
|
|
30
|
+
|
|
31
|
+
|
|
27
32
|
try:
|
|
28
33
|
from flask import request, jsonify, Response
|
|
29
34
|
except ImportError:
|
|
@@ -34,6 +39,7 @@ try:
|
|
|
34
39
|
except ImportError:
|
|
35
40
|
pass
|
|
36
41
|
|
|
42
|
+
|
|
37
43
|
def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
38
44
|
|
|
39
45
|
@app.route("/")
|
|
@@ -155,9 +161,114 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
155
161
|
span.end(output=jsonify(bot_output))
|
|
156
162
|
trace.update(output=jsonify(bot_output))
|
|
157
163
|
|
|
164
|
+
# {'answer': 'output'}
|
|
158
165
|
return jsonify(bot_output)
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
@app.route('/openai/v1/chat/completions', methods=['POST'])
|
|
168
|
+
def openai_compatible_endpoint():
|
|
169
|
+
data = request.get_json()
|
|
170
|
+
model = data.pop('model', None)
|
|
171
|
+
messages = data.pop('messages', None)
|
|
172
|
+
chat_history = data.pop('chat_history', None)
|
|
173
|
+
stream = data.pop('stream', False)
|
|
174
|
+
|
|
175
|
+
if not messages:
|
|
176
|
+
return jsonify({"error": "No messages provided"}), 400
|
|
177
|
+
|
|
178
|
+
user_message = next((msg['content'] for msg in messages if msg['role'] == 'user'), None)
|
|
179
|
+
if not user_message:
|
|
180
|
+
return jsonify({"error": "No user message provided"}), 400
|
|
181
|
+
|
|
182
|
+
all_input = {
|
|
183
|
+
"user_input": user_message,
|
|
184
|
+
"chat_history": chat_history,
|
|
185
|
+
"kwargs": data
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
observed_stream_interpreter = observe()(stream_interpreter)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
response_id = str(uuid.uuid4())
|
|
192
|
+
|
|
193
|
+
def generate_response_content():
|
|
194
|
+
for chunk in start_streaming_chat(question=user_message,
|
|
195
|
+
vector_name=model,
|
|
196
|
+
qna_func=observed_stream_interpreter,
|
|
197
|
+
chat_history=all_input["chat_history"],
|
|
198
|
+
wait_time=all_input.get("stream_wait_time", 1),
|
|
199
|
+
timeout=all_input.get("stream_timeout", 60),
|
|
200
|
+
**all_input["kwargs"]
|
|
201
|
+
):
|
|
202
|
+
if isinstance(chunk, dict) and 'content' in chunk:
|
|
203
|
+
openai_chunk = {
|
|
204
|
+
"id": response_id,
|
|
205
|
+
"object": "chat.completion.chunk",
|
|
206
|
+
"created": int(datetime.time()),
|
|
207
|
+
"model": model,
|
|
208
|
+
"system_fingerprint": sunholo_version(),
|
|
209
|
+
"choices": [{
|
|
210
|
+
"index": 0,
|
|
211
|
+
"delta": {"content": chunk['content']},
|
|
212
|
+
"logprobs": None,
|
|
213
|
+
"finish_reason": None
|
|
214
|
+
}]
|
|
215
|
+
}
|
|
216
|
+
yield json.dumps(openai_chunk) + "\n"
|
|
217
|
+
|
|
218
|
+
final_chunk = {
|
|
219
|
+
"id": response_id,
|
|
220
|
+
"object": "chat.completion.chunk",
|
|
221
|
+
"created": int(datetime.time()),
|
|
222
|
+
"model": model,
|
|
223
|
+
"system_fingerprint": sunholo_version(),
|
|
224
|
+
"choices": [{
|
|
225
|
+
"index": 0,
|
|
226
|
+
"delta": {},
|
|
227
|
+
"logprobs": None,
|
|
228
|
+
"finish_reason": "stop"
|
|
229
|
+
}]
|
|
230
|
+
}
|
|
231
|
+
yield json.dumps(final_chunk) + "\n"
|
|
232
|
+
|
|
233
|
+
if stream:
|
|
234
|
+
return Response(generate_response_content(), content_type='text/plain; charset=utf-8')
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
bot_output = observed_stream_interpreter(
|
|
238
|
+
question=user_message,
|
|
239
|
+
vector_name=model,
|
|
240
|
+
chat_history=all_input["chat_history"],
|
|
241
|
+
**all_input["kwargs"]
|
|
242
|
+
)
|
|
243
|
+
bot_output = parse_output(bot_output)
|
|
244
|
+
|
|
245
|
+
openai_response = {
|
|
246
|
+
"id": response_id,
|
|
247
|
+
"object": "chat.completion",
|
|
248
|
+
"created": int(datetime.time()),
|
|
249
|
+
"model": model,
|
|
250
|
+
"system_fingerprint": sunholo_version(),
|
|
251
|
+
"choices": [{
|
|
252
|
+
"index": 0,
|
|
253
|
+
"message": {
|
|
254
|
+
"role": "assistant",
|
|
255
|
+
"content": bot_output.get('answer', ''),
|
|
256
|
+
},
|
|
257
|
+
"logprobs": None,
|
|
258
|
+
"finish_reason": "stop"
|
|
259
|
+
}],
|
|
260
|
+
"usage": {
|
|
261
|
+
"prompt_tokens": len(user_message.split()),
|
|
262
|
+
"completion_tokens": len(bot_output.get('answer', '').split()),
|
|
263
|
+
"total_tokens": len(user_message.split()) + len(bot_output.get('answer', '').split())
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return jsonify(openai_response)
|
|
268
|
+
|
|
269
|
+
except Exception as err:
|
|
270
|
+
return jsonify({'error': f'QNA_ERROR: An error occurred: {str(err)} traceback: {traceback.format_exc()}'}), 500
|
|
271
|
+
|
|
161
272
|
|
|
162
273
|
def create_langfuse_trace(request, vector_name):
|
|
163
274
|
try:
|
|
@@ -172,10 +283,8 @@ def create_langfuse_trace(request, vector_name):
|
|
|
172
283
|
session_id = request.headers.get("X-Session-ID")
|
|
173
284
|
message_source = request.headers.get("X-Message-Source")
|
|
174
285
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
package_version = version('sunholo')
|
|
178
|
-
tags = [f"sunholo-v{package_version}"]
|
|
286
|
+
package_version = sunholo_version()
|
|
287
|
+
tags = [package_version]
|
|
179
288
|
if message_source:
|
|
180
289
|
tags.append(message_source)
|
|
181
290
|
|
|
@@ -191,8 +300,28 @@ def prep_vac(request, vector_name):
|
|
|
191
300
|
#trace = create_langfuse_trace(request, vector_name)
|
|
192
301
|
trace = None
|
|
193
302
|
span = None
|
|
194
|
-
|
|
303
|
+
|
|
304
|
+
if request.content_type.startswith('application/json'):
|
|
305
|
+
data = request.get_json()
|
|
306
|
+
elif request.content_type.startswith('multipart/form-data'):
|
|
307
|
+
data = request.form.to_dict()
|
|
308
|
+
if 'file' in request.files:
|
|
309
|
+
file = request.files['file']
|
|
310
|
+
if file.filename != '':
|
|
311
|
+
log.info(f"Found file: {file.filename} to upload to GCS")
|
|
312
|
+
try:
|
|
313
|
+
image_uri, mime_type = handle_file_upload(file, vector_name)
|
|
314
|
+
data["image_uri"] = image_uri
|
|
315
|
+
data["mime"] = mime_type
|
|
316
|
+
except Exception as e:
|
|
317
|
+
return jsonify({'error': str(e), 'traceback': traceback.format_exc()}), 500
|
|
318
|
+
else:
|
|
319
|
+
return jsonify({"error": "No file selected"}), 400
|
|
320
|
+
else:
|
|
321
|
+
return jsonify({"error": "Unsupported content type"}), 400
|
|
322
|
+
|
|
195
323
|
log.info(f"vac/{vector_name} got data: {data}")
|
|
324
|
+
|
|
196
325
|
config, _ = load_config("config/llm_config.yaml")
|
|
197
326
|
vac_configs = config.get("vac")
|
|
198
327
|
if vac_configs:
|
|
@@ -213,7 +342,7 @@ def prep_vac(request, vector_name):
|
|
|
213
342
|
'vector_name': vector_name,
|
|
214
343
|
'chat_history': paired_messages,
|
|
215
344
|
'stream_wait_time': stream_wait_time,
|
|
216
|
-
'stream_timeout':stream_timeout,
|
|
345
|
+
'stream_timeout': stream_timeout,
|
|
217
346
|
'kwargs': data}
|
|
218
347
|
|
|
219
348
|
if trace:
|
|
@@ -233,4 +362,14 @@ def prep_vac(request, vector_name):
|
|
|
233
362
|
"command_response": command_response,
|
|
234
363
|
"all_input": all_input,
|
|
235
364
|
"vac_config": vac_config
|
|
236
|
-
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def handle_file_upload(file, vector_name):
|
|
369
|
+
try:
|
|
370
|
+
file.save(file.filename)
|
|
371
|
+
image_uri = add_file_to_gcs(file.filename, vector_name)
|
|
372
|
+
os.remove(file.filename) # Clean up the saved file
|
|
373
|
+
return image_uri, file.mimetype
|
|
374
|
+
except Exception as e:
|
|
375
|
+
raise Exception(f'File upload failed: {str(e)}')
|
|
@@ -53,26 +53,23 @@ def get_header(vector_name) -> Optional[dict]:
|
|
|
53
53
|
else:
|
|
54
54
|
run_url = "http://127.0.0.1:8080"
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
else
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
56
|
+
# Append ID Token to make authenticated requests to Cloud Run services
|
|
57
|
+
frame = inspect.currentframe()
|
|
58
|
+
caller_frame = frame.f_back if frame is not None else None # One level up in the stack
|
|
59
|
+
deets = {
|
|
60
|
+
'message': 'Authenticating for run_url',
|
|
61
|
+
'run_url': run_url
|
|
62
|
+
}
|
|
63
|
+
if caller_frame:
|
|
62
64
|
deets = {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
log.info(f"Authenticating for run_url {run_url} from {caller_frame.f_code.co_name}")
|
|
75
|
-
id_token = get_id_token(run_url)
|
|
76
|
-
headers = {"Authorization": f"Bearer {id_token}"}
|
|
77
|
-
#log.info(f"id_token {id_token}")
|
|
78
|
-
return headers
|
|
65
|
+
'message': 'Authenticating for run_url',
|
|
66
|
+
'file': caller_frame.f_code.co_filename,
|
|
67
|
+
'line': str(caller_frame.f_lineno),
|
|
68
|
+
'function': caller_frame.f_code.co_name,
|
|
69
|
+
'run_url': run_url
|
|
70
|
+
}
|
|
71
|
+
log.info(f"Authenticating for run_url {run_url} from {caller_frame.f_code.co_name}")
|
|
72
|
+
id_token = get_id_token(run_url)
|
|
73
|
+
headers = {"Authorization": f"Bearer {id_token}"}
|
|
74
|
+
#log.info(f"id_token {id_token}")
|
|
75
|
+
return headers
|
|
@@ -149,46 +149,72 @@ def headless_mode(service_url, service_name, user_input, chat_history=None, stre
|
|
|
149
149
|
user_id = generate_user_id()
|
|
150
150
|
session_id = str(uuid.uuid4())
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
152
|
+
if not stream:
|
|
153
|
+
vac_response = send_to_qa(user_input,
|
|
154
|
+
vector_name=service_name,
|
|
155
|
+
chat_history=chat_history,
|
|
156
|
+
message_author=user_id,
|
|
157
|
+
#TODO: populate these
|
|
158
|
+
image_url=None,
|
|
159
|
+
source_filters=None,
|
|
160
|
+
search_kwargs=None,
|
|
161
|
+
private_docs=None,
|
|
162
|
+
whole_document=False,
|
|
163
|
+
source_filters_and_or=False,
|
|
164
|
+
# system kwargs
|
|
165
|
+
configurable={
|
|
166
|
+
"vector_name": service_name,
|
|
167
|
+
},
|
|
168
|
+
user_id=user_id,
|
|
169
|
+
session_id=session_id,
|
|
170
|
+
message_source="cli",
|
|
171
|
+
override_endpoint=service_url)
|
|
172
|
+
|
|
173
|
+
# ensures {'answer': answer}
|
|
174
|
+
answer = parse_output(vac_response)
|
|
175
|
+
|
|
176
|
+
console.print(answer.get('answer'))
|
|
177
|
+
else:
|
|
178
|
+
def stream_response():
|
|
179
|
+
generate = generate_proxy_stream(
|
|
180
|
+
send_to_qa,
|
|
181
|
+
user_input,
|
|
182
|
+
vector_name=service_name,
|
|
183
|
+
chat_history=chat_history,
|
|
184
|
+
generate_f_output=lambda x: x, # Replace with actual processing function
|
|
185
|
+
stream_wait_time=0.5,
|
|
186
|
+
stream_timeout=120,
|
|
187
|
+
message_author=user_id,
|
|
188
|
+
#TODO: populate these
|
|
189
|
+
image_url=None,
|
|
190
|
+
source_filters=None,
|
|
191
|
+
search_kwargs=None,
|
|
192
|
+
private_docs=None,
|
|
193
|
+
whole_document=False,
|
|
194
|
+
source_filters_and_or=False,
|
|
195
|
+
# system kwargs
|
|
196
|
+
configurable={
|
|
197
|
+
"vector_name": service_name,
|
|
198
|
+
},
|
|
199
|
+
user_id=user_id,
|
|
200
|
+
session_id=session_id,
|
|
201
|
+
message_source="cli",
|
|
202
|
+
override_endpoint=service_url
|
|
203
|
+
)
|
|
204
|
+
for part in generate():
|
|
205
|
+
yield part
|
|
180
206
|
|
|
181
|
-
|
|
207
|
+
answer = ""
|
|
182
208
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
209
|
+
for token in stream_response():
|
|
210
|
+
if isinstance(token, bytes):
|
|
211
|
+
token = token.decode('utf-8')
|
|
212
|
+
print(token, end='', flush=True)
|
|
213
|
+
answer += token
|
|
188
214
|
|
|
189
|
-
if
|
|
215
|
+
if answer:
|
|
190
216
|
chat_history.append({"name": "Human", "content": user_input})
|
|
191
|
-
chat_history.append({"name": "AI", "content":
|
|
217
|
+
chat_history.append({"name": "AI", "content": answer})
|
|
192
218
|
print() # For new line after streaming ends
|
|
193
219
|
|
|
194
220
|
return chat_history
|
|
@@ -7,6 +7,8 @@ try:
|
|
|
7
7
|
except ImportError:
|
|
8
8
|
CallbackHandler = None
|
|
9
9
|
|
|
10
|
+
from ..utils.version import sunholo_version
|
|
11
|
+
|
|
10
12
|
def create_langfuse_callback(**kwargs):
|
|
11
13
|
|
|
12
14
|
if not CallbackHandler:
|
|
@@ -40,10 +42,7 @@ def add_langfuse_tracing(
|
|
|
40
42
|
session_id = request.headers.get("X-Session-ID")
|
|
41
43
|
message_source = request.headers.get("X-Message-Source")
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
from importlib.metadata import version
|
|
45
|
-
package_version = version('sunholo')
|
|
46
|
-
tags = [f"sunholo-v{package_version}"]
|
|
45
|
+
tags = [sunholo_version()]
|
|
47
46
|
if message_source:
|
|
48
47
|
tags.append(message_source)
|
|
49
48
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.64.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.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.64.3.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
21
|
Requires-Dist: google-auth
|
|
22
|
+
Requires-Dist: tenacity==8.3.0
|
|
22
23
|
Requires-Dist: langchain
|
|
23
24
|
Requires-Dist: langchain_experimental
|
|
24
25
|
Requires-Dist: langchain-community
|
|
@@ -111,54 +112,21 @@ This is the Sunholo Python project, a comprehensive toolkit for working with lan
|
|
|
111
112
|
|
|
112
113
|
Please refer to the website for full documentation at https://dev.sunholo.com/
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
(draft release https://pypi.org/project/sunholo/ )
|
|
117
|
-
## Table of Contents
|
|
118
|
-
- [Agents](#agents)
|
|
119
|
-
- [Archive](#archive)
|
|
120
|
-
- [Bots](#bots)
|
|
121
|
-
- [Chunker](#chunker)
|
|
122
|
-
- [Components](#components)
|
|
123
|
-
- [Database](#database)
|
|
124
|
-
- [Embedder](#embedder)
|
|
125
|
-
- [PubSub](#pubsub)
|
|
126
|
-
- [QnA](#qna)
|
|
127
|
-
- [Streaming](#streaming)
|
|
128
|
-
- [Summarise](#summarise)
|
|
129
|
-
- [Utils](#utils)
|
|
115
|
+
## Demos
|
|
130
116
|
|
|
117
|
+
Using https://github.com/charmbracelet/vhs
|
|
131
118
|
|
|
132
119
|
```sh
|
|
133
|
-
|
|
120
|
+
vhs record > cassette.tape
|
|
134
121
|
```
|
|
135
122
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
`sunholo` provides utilities to help manage LLM operations on Google Cloud Platform at first, but it is hoped that making it open source will help it support other clouds in the future. A lot of the functionality is not Google Cloud Platform specific, so still may be helpful.
|
|
139
|
-
|
|
140
|
-
It is derived from the Edmonbrain project, the original blog post you can read here: https://code.markedmondson.me/running-llms-on-gcp/ and owes a lot to Langchain ( https://github.com/langchain-ai/langchain )
|
|
141
|
-
|
|
142
|
-
The package includes:
|
|
123
|
+
Then make gif:
|
|
143
124
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
* `chunker/` - functions to slice up documents for sending into vector stores
|
|
148
|
-
* `components/` - functions to help configure which LLM, prompt, vectorstore or document retriever you will use based on a yaml config file
|
|
149
|
-
* `database/` - database setup functions and SQL to run on those sources such as Supabase
|
|
150
|
-
* `embedder/` - functions to send chunks into embedding vector stores
|
|
151
|
-
* `pubsub/` - use of PubSub for a message queue between components
|
|
152
|
-
* `qna/` - utilities for running agents such as retry strats and parsing of output/input
|
|
153
|
-
* `streaming/` - creation of streaming responses from LLM bots
|
|
154
|
-
* `summarise/` - creation of summaries of large documents
|
|
155
|
-
* `utils/` - reading configuration files, Google Cloud Platform metadata
|
|
156
|
-
|
|
157
|
-
## Configuration
|
|
125
|
+
```sh
|
|
126
|
+
vhs docs/tapes/config-list.tape
|
|
127
|
+
```
|
|
158
128
|
|
|
159
|
-
The library uses the config specifications that some examples are given in the `config/` folder.
|
|
160
129
|
|
|
161
|
-
When using the functions, make sure to have the `config/` folder in the root of where your application is running (usually `$HOME/config`)
|
|
162
130
|
|
|
163
131
|
```
|
|
164
132
|
Copyright [2024] [Holosun ApS]
|
|
@@ -108,10 +108,12 @@ sunholo/utils/gcp_project.py
|
|
|
108
108
|
sunholo/utils/parsers.py
|
|
109
109
|
sunholo/utils/timedelta.py
|
|
110
110
|
sunholo/utils/user_ids.py
|
|
111
|
+
sunholo/utils/version.py
|
|
111
112
|
sunholo/vertex/__init__.py
|
|
112
113
|
sunholo/vertex/init.py
|
|
113
114
|
sunholo/vertex/memory_tools.py
|
|
114
115
|
sunholo/vertex/safety.py
|
|
115
116
|
tests/test_chat_history.py
|
|
117
|
+
tests/test_chunker.py
|
|
116
118
|
tests/test_config.py
|
|
117
119
|
tests/test_dispatch_to_qa.py
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import patch, MagicMock
|
|
3
|
+
from sunholo.chunker.data_to_embed_pubsub import data_to_embed_pubsub
|
|
4
|
+
|
|
5
|
+
# Mock external calls within the function
|
|
6
|
+
@patch('sunholo.chunker.data_to_embed_pubsub.process_pubsub_message', return_value=({}, {}, 'test_vector'))
|
|
7
|
+
@patch('sunholo.chunker.data_to_embed_pubsub.process_chunker_data', return_value='processed_data')
|
|
8
|
+
def test_data_to_embed_pubsub(mock_process_chunker_data, mock_process_pubsub_message):
|
|
9
|
+
# Test the function with various inputs including edge cases
|
|
10
|
+
assert data_to_embed_pubsub({}) == 'processed_data'
|
|
11
|
+
assert data_to_embed_pubsub({'key': 'value'}) == 'processed_data'
|
|
12
|
+
mock_process_pubsub_message.assert_called()
|
|
13
|
+
mock_process_chunker_data.assert_called()
|
|
14
|
+
|
|
15
|
+
# Ensure tests are self-contained and do not require external dependencies
|
|
16
|
+
mock_process_pubsub_message = MagicMock(return_value=({}, {}, 'test_vector'))
|
|
17
|
+
mock_process_chunker_data = MagicMock(return_value='processed_data')
|
|
18
|
+
assert data_to_embed_pubsub({'key': 'value'}) == 'processed_data'
|
|
19
|
+
|
|
20
|
+
# Validate the function's output against expected results
|
|
21
|
+
expected_output = 'processed_data'
|
|
22
|
+
actual_output = data_to_embed_pubsub({'key': 'value'})
|
|
23
|
+
assert actual_output == expected_output, f"Expected {expected_output}, got {actual_output}"
|
|
@@ -8,13 +8,19 @@ from sunholo.agents.dispatch_to_qa import prep_request_payload
|
|
|
8
8
|
# Additional test cases to cover all logic paths
|
|
9
9
|
("", [], "empty_input_vector", False, "http://example.com/invoke", {"user_input": "", "chat_history": [], "vector_name": "empty_input_vector"}),
|
|
10
10
|
("Valid input", ["Chat history present"], "history_vector", False, "http://example.com/invoke", {"user_input": "Valid input", "chat_history": ["Chat history present"], "vector_name": "history_vector"}),
|
|
11
|
-
("Stream request", [], "stream_vector", True, "http://example.com/stream", {"user_input": "Stream request", "chat_history": [], "vector_name": "stream_vector"})
|
|
11
|
+
("Stream request", [], "stream_vector", True, "http://example.com/stream", {"user_input": "Stream request", "chat_history": [], "vector_name": "stream_vector"}),
|
|
12
|
+
# New test cases for prep_request_payload function
|
|
13
|
+
("User input with override endpoint", [], "override_vector", False, "http://override.com/invoke", {"user_input": "User input with override endpoint", "chat_history": [], "vector_name": "override_vector"}),
|
|
14
|
+
("Stream with chat history and override endpoint", ["Chat history for override"], "override_stream_vector", True, "http://override.com/stream", {"user_input": "Stream with chat history and override endpoint", "chat_history": ["Chat history for override"], "vector_name": "override_stream_vector"})
|
|
12
15
|
])
|
|
13
16
|
@patch('sunholo.agents.dispatch_to_qa.load_config_key')
|
|
14
17
|
@patch('sunholo.agents.dispatch_to_qa.route_endpoint')
|
|
15
18
|
def test_prep_request_payload(mock_route_endpoint, mock_load_config_key, user_input, chat_history, vector_name, stream, expected_endpoint, expected_payload):
|
|
16
19
|
mock_route_endpoint.return_value = {"invoke": "http://example.com/invoke", "stream": "http://example.com/stream"}
|
|
17
20
|
mock_load_config_key.side_effect = lambda key, vector_name=None, kind=None: "my_vector" if key == "vector_name" else None
|
|
21
|
+
# Mocking for override endpoint scenario
|
|
22
|
+
if vector_name.startswith("override"):
|
|
23
|
+
mock_route_endpoint.return_value = {"invoke": "http://override.com/invoke", "stream": "http://override.com/stream"}
|
|
18
24
|
|
|
19
25
|
endpoint, payload = prep_request_payload(user_input, chat_history, vector_name, stream)
|
|
20
26
|
|
sunholo-0.62.18/README.md
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
## Introduction
|
|
2
|
-
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.
|
|
3
|
-
|
|
4
|
-
Please refer to the website for full documentation at https://dev.sunholo.com/
|
|
5
|
-
|
|
6
|
-
# sunholo-py
|
|
7
|
-
|
|
8
|
-
(draft release https://pypi.org/project/sunholo/ )
|
|
9
|
-
## Table of Contents
|
|
10
|
-
- [Agents](#agents)
|
|
11
|
-
- [Archive](#archive)
|
|
12
|
-
- [Bots](#bots)
|
|
13
|
-
- [Chunker](#chunker)
|
|
14
|
-
- [Components](#components)
|
|
15
|
-
- [Database](#database)
|
|
16
|
-
- [Embedder](#embedder)
|
|
17
|
-
- [PubSub](#pubsub)
|
|
18
|
-
- [QnA](#qna)
|
|
19
|
-
- [Streaming](#streaming)
|
|
20
|
-
- [Summarise](#summarise)
|
|
21
|
-
- [Utils](#utils)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```sh
|
|
25
|
-
pip install sunholo
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
A python library to enable LLMOps within cloud environments
|
|
29
|
-
|
|
30
|
-
`sunholo` provides utilities to help manage LLM operations on Google Cloud Platform at first, but it is hoped that making it open source will help it support other clouds in the future. A lot of the functionality is not Google Cloud Platform specific, so still may be helpful.
|
|
31
|
-
|
|
32
|
-
It is derived from the Edmonbrain project, the original blog post you can read here: https://code.markedmondson.me/running-llms-on-gcp/ and owes a lot to Langchain ( https://github.com/langchain-ai/langchain )
|
|
33
|
-
|
|
34
|
-
The package includes:
|
|
35
|
-
|
|
36
|
-
* `agents/` - functions for working with agents, including easy flask apps, parsing chat history and dispatching requests to different agent endpoints
|
|
37
|
-
* `archive/` - functions to record all Q&A activity to BigQuery via PubSub
|
|
38
|
-
* `bots/` - functions for special cases regarding frontend bots such as GChat, Web Apps, Discord and Slack
|
|
39
|
-
* `chunker/` - functions to slice up documents for sending into vector stores
|
|
40
|
-
* `components/` - functions to help configure which LLM, prompt, vectorstore or document retriever you will use based on a yaml config file
|
|
41
|
-
* `database/` - database setup functions and SQL to run on those sources such as Supabase
|
|
42
|
-
* `embedder/` - functions to send chunks into embedding vector stores
|
|
43
|
-
* `pubsub/` - use of PubSub for a message queue between components
|
|
44
|
-
* `qna/` - utilities for running agents such as retry strats and parsing of output/input
|
|
45
|
-
* `streaming/` - creation of streaming responses from LLM bots
|
|
46
|
-
* `summarise/` - creation of summaries of large documents
|
|
47
|
-
* `utils/` - reading configuration files, Google Cloud Platform metadata
|
|
48
|
-
|
|
49
|
-
## Configuration
|
|
50
|
-
|
|
51
|
-
The library uses the config specifications that some examples are given in the `config/` folder.
|
|
52
|
-
|
|
53
|
-
When using the functions, make sure to have the `config/` folder in the root of where your application is running (usually `$HOME/config`)
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
Copyright [2024] [Holosun ApS]
|
|
57
|
-
|
|
58
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
59
|
-
you may not use this file except in compliance with the License.
|
|
60
|
-
You may obtain a copy of the License at
|
|
61
|
-
|
|
62
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
63
|
-
|
|
64
|
-
Unless required by applicable law or agreed to in writing, software
|
|
65
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
66
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
67
|
-
See the License for the specific language governing permissions and
|
|
68
|
-
limitations under the License.
|
|
69
|
-
```
|
|
70
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|