diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..c7d9f3332a950355d5a77d85000f05e6f45435ea
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,34 @@
+*.7z filter=lfs diff=lfs merge=lfs -text
+*.arrow filter=lfs diff=lfs merge=lfs -text
+*.bin filter=lfs diff=lfs merge=lfs -text
+*.bz2 filter=lfs diff=lfs merge=lfs -text
+*.ckpt filter=lfs diff=lfs merge=lfs -text
+*.ftz filter=lfs diff=lfs merge=lfs -text
+*.gz filter=lfs diff=lfs merge=lfs -text
+*.h5 filter=lfs diff=lfs merge=lfs -text
+*.joblib filter=lfs diff=lfs merge=lfs -text
+*.lfs.* filter=lfs diff=lfs merge=lfs -text
+*.mlmodel filter=lfs diff=lfs merge=lfs -text
+*.model filter=lfs diff=lfs merge=lfs -text
+*.msgpack filter=lfs diff=lfs merge=lfs -text
+*.npy filter=lfs diff=lfs merge=lfs -text
+*.npz filter=lfs diff=lfs merge=lfs -text
+*.onnx filter=lfs diff=lfs merge=lfs -text
+*.ot filter=lfs diff=lfs merge=lfs -text
+*.parquet filter=lfs diff=lfs merge=lfs -text
+*.pb filter=lfs diff=lfs merge=lfs -text
+*.pickle filter=lfs diff=lfs merge=lfs -text
+*.pkl filter=lfs diff=lfs merge=lfs -text
+*.pt filter=lfs diff=lfs merge=lfs -text
+*.pth filter=lfs diff=lfs merge=lfs -text
+*.rar filter=lfs diff=lfs merge=lfs -text
+*.safetensors filter=lfs diff=lfs merge=lfs -text
+saved_model/**/* filter=lfs diff=lfs merge=lfs -text
+*.tar.* filter=lfs diff=lfs merge=lfs -text
+*.tflite filter=lfs diff=lfs merge=lfs -text
+*.tgz filter=lfs diff=lfs merge=lfs -text
+*.wasm filter=lfs diff=lfs merge=lfs -text
+*.xz filter=lfs diff=lfs merge=lfs -text
+*.zip filter=lfs diff=lfs merge=lfs -text
+*.zst filter=lfs diff=lfs merge=lfs -text
+*tfevents* filter=lfs diff=lfs merge=lfs -text
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..04a65446f300f8648d950055761c4c2493cc75a8
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,17 @@
+FROM python:3.10
+
+WORKDIR /app
+
+COPY requirements.txt .
+RUN pip install -r requirements.txt
+
+RUN mkdir /.cache && chmod -R 777 /.cache
+RUN mkdir .chroma && chmod -R 777 .chroma
+
+COPY . .
+
+RUN chmod -R 777 /app
+
+EXPOSE 7860
+
+CMD ["python", "server.py", "--cpu", "--share", "--secure", "--enable-modules=summarize,classify,silero-tts,edge-tts,chromadb", "--classification-model=joeddav/distilbert-base-uncased-go-emotions-student", "--summarization-model=slauw87/bart_summarisation"]
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..54bdf565cf8696ff5b40892c78b7f853cde7d0ac
--- /dev/null
+++ b/README.md
@@ -0,0 +1,11 @@
+---
+title: zeeka5456
+emoji: 🐠
+colorFrom: pink
+colorTo: yellow
+sdk: docker
+pinned: false
+license: mit
+duplicated_from: doctord98/zeeka5456
+---
+Doctord98 is the boss
\ No newline at end of file
diff --git a/constants.py b/constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..66c62a64e5d02d65c70c89b39affa6b689b5ac9b
--- /dev/null
+++ b/constants.py
@@ -0,0 +1,49 @@
+# Constants
+# Also try: 'Qiliang/bart-large-cnn-samsum-ElectrifAi_v10'
+DEFAULT_SUMMARIZATION_MODEL = "Qiliang/bart-large-cnn-samsum-ChatGPT_v3"
+# Also try: 'joeddav/distilbert-base-uncased-go-emotions-student'
+DEFAULT_CLASSIFICATION_MODEL = "nateraw/bert-base-uncased-emotion"
+# Also try: 'Salesforce/blip-image-captioning-base'
+DEFAULT_CAPTIONING_MODEL = "Salesforce/blip-image-captioning-large"
+DEFAULT_SD_MODEL = "ckpt/anything-v4.5-vae-swapped"
+DEFAULT_EMBEDDING_MODEL = "sentence-transformers/all-mpnet-base-v2"
+DEFAULT_REMOTE_SD_HOST = "127.0.0.1"
+DEFAULT_REMOTE_SD_PORT = 7860
+DEFAULT_CHROMA_PORT = 8000
+SILERO_SAMPLES_PATH = "tts_samples"
+SILERO_SAMPLE_TEXT = "The quick brown fox jumps over the lazy dog"
+# ALL_MODULES = ['caption', 'summarize', 'classify', 'keywords', 'prompt', 'sd']
+DEFAULT_SUMMARIZE_PARAMS = {
+ "temperature": 1.0,
+ "repetition_penalty": 1.0,
+ "max_length": 500,
+ "min_length": 200,
+ "length_penalty": 1.5,
+ "bad_words": [
+ "\n",
+ '"',
+ "*",
+ "[",
+ "]",
+ "{",
+ "}",
+ ":",
+ "(",
+ ")",
+ "<",
+ ">",
+ "Â",
+ "The text ends",
+ "The story ends",
+ "The text is",
+ "The story is",
+ ],
+}
+
+PROMPT_PREFIX = "best quality, absurdres, "
+NEGATIVE_PROMPT = """lowres, bad anatomy, error body, error hair, error arm,
+error hands, bad hands, error fingers, bad fingers, missing fingers
+error legs, bad legs, multiple legs, missing legs, error lighting,
+error shadow, error reflection, text, error, extra digit, fewer digits,
+cropped, worst quality, low quality, normal quality, jpeg artifacts,
+signature, watermark, username, blurry"""
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..40e6f8ca42fc80f9613490a78f0a176302f4c52f
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,20 @@
+flask
+flask-cloudflared
+flask-cors
+flask-compress
+markdown
+Pillow
+colorama
+webuiapi
+--extra-index-url https://download.pytorch.org/whl/cu117
+torch==2.0.0+cu117
+torchvision==0.15.1
+torchaudio==2.0.1+cu117
+accelerate
+transformers==4.28.1
+diffusers==0.16.1
+silero-api-server
+chromadb
+sentence_transformers
+edge-tts
+Werkzeug
\ No newline at end of file
diff --git a/server.py b/server.py
new file mode 100644
index 0000000000000000000000000000000000000000..c24e7ab2059ea9554094663fccf8d9145439fbf0
--- /dev/null
+++ b/server.py
@@ -0,0 +1,844 @@
+from functools import wraps
+from flask import (
+ Flask,
+ jsonify,
+ request,
+ Response,
+ render_template_string,
+ abort,
+ send_from_directory,
+ send_file,
+)
+from flask_cors import CORS
+from flask_compress import Compress
+import markdown
+import argparse
+from transformers import AutoTokenizer, AutoProcessor, pipeline
+from transformers import AutoModelForCausalLM, AutoModelForSeq2SeqLM
+from transformers import BlipForConditionalGeneration
+import unicodedata
+import torch
+import time
+import os
+import gc
+import secrets
+from PIL import Image
+import base64
+from io import BytesIO
+from random import randint
+import webuiapi
+import hashlib
+from constants import *
+from colorama import Fore, Style, init as colorama_init
+
+colorama_init()
+
+
+class SplitArgs(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ setattr(
+ namespace, self.dest, values.replace('"', "").replace("'", "").split(",")
+ )
+
+
+# Script arguments
+parser = argparse.ArgumentParser(
+ prog="SillyTavern Extras", description="Web API for transformers models"
+)
+parser.add_argument(
+ "--port", type=int, help="Specify the port on which the application is hosted"
+)
+parser.add_argument(
+ "--listen", action="store_true", help="Host the app on the local network"
+)
+parser.add_argument(
+ "--share", action="store_true", help="Share the app on CloudFlare tunnel"
+)
+parser.add_argument("--cpu", action="store_true", help="Run the models on the CPU")
+parser.add_argument("--summarization-model", help="Load a custom summarization model")
+parser.add_argument(
+ "--classification-model", help="Load a custom text classification model"
+)
+parser.add_argument("--captioning-model", help="Load a custom captioning model")
+parser.add_argument("--embedding-model", help="Load a custom text embedding model")
+parser.add_argument("--chroma-host", help="Host IP for a remote ChromaDB instance")
+parser.add_argument("--chroma-port", help="HTTP port for a remote ChromaDB instance (defaults to 8000)")
+parser.add_argument("--chroma-folder", help="Path for chromadb persistence folder", default='.chroma_db')
+parser.add_argument(
+ "--secure", action="store_true", help="Enforces the use of an API key"
+)
+
+sd_group = parser.add_mutually_exclusive_group()
+
+local_sd = sd_group.add_argument_group("sd-local")
+local_sd.add_argument("--sd-model", help="Load a custom SD image generation model")
+local_sd.add_argument("--sd-cpu", help="Force the SD pipeline to run on the CPU")
+
+remote_sd = sd_group.add_argument_group("sd-remote")
+remote_sd.add_argument(
+ "--sd-remote", action="store_true", help="Use a remote backend for SD"
+)
+remote_sd.add_argument(
+ "--sd-remote-host", type=str, help="Specify the host of the remote SD backend"
+)
+remote_sd.add_argument(
+ "--sd-remote-port", type=int, help="Specify the port of the remote SD backend"
+)
+remote_sd.add_argument(
+ "--sd-remote-ssl", action="store_true", help="Use SSL for the remote SD backend"
+)
+remote_sd.add_argument(
+ "--sd-remote-auth",
+ type=str,
+ help="Specify the username:password for the remote SD backend (if required)",
+)
+
+parser.add_argument(
+ "--enable-modules",
+ action=SplitArgs,
+ default=[],
+ help="Override a list of enabled modules",
+)
+
+args = parser.parse_args()
+
+port = 7860
+host = "0.0.0.0"
+summarization_model = (
+ args.summarization_model
+ if args.summarization_model
+ else DEFAULT_SUMMARIZATION_MODEL
+)
+classification_model = (
+ args.classification_model
+ if args.classification_model
+ else DEFAULT_CLASSIFICATION_MODEL
+)
+captioning_model = (
+ args.captioning_model if args.captioning_model else DEFAULT_CAPTIONING_MODEL
+)
+embedding_model = (
+ args.embedding_model if args.embedding_model else DEFAULT_EMBEDDING_MODEL
+)
+
+sd_use_remote = False if args.sd_model else True
+sd_model = args.sd_model if args.sd_model else DEFAULT_SD_MODEL
+sd_remote_host = args.sd_remote_host if args.sd_remote_host else DEFAULT_REMOTE_SD_HOST
+sd_remote_port = args.sd_remote_port if args.sd_remote_port else DEFAULT_REMOTE_SD_PORT
+sd_remote_ssl = args.sd_remote_ssl
+sd_remote_auth = args.sd_remote_auth
+
+modules = (
+ args.enable_modules if args.enable_modules and len(args.enable_modules) > 0 else []
+)
+
+if len(modules) == 0:
+ print(
+ f"{Fore.RED}{Style.BRIGHT}You did not select any modules to run! Choose them by adding an --enable-modules option"
+ )
+ print(f"Example: --enable-modules=caption,summarize{Style.RESET_ALL}")
+
+# Models init
+device_string = "cuda:0" if torch.cuda.is_available() and not args.cpu else "cpu"
+device = torch.device(device_string)
+torch_dtype = torch.float32 if device_string == "cpu" else torch.float16
+
+if "caption" in modules:
+ print("Initializing an image captioning model...")
+ captioning_processor = AutoProcessor.from_pretrained(captioning_model)
+ if "blip" in captioning_model:
+ captioning_transformer = BlipForConditionalGeneration.from_pretrained(
+ captioning_model, torch_dtype=torch_dtype
+ ).to(device)
+ else:
+ captioning_transformer = AutoModelForCausalLM.from_pretrained(
+ captioning_model, torch_dtype=torch_dtype
+ ).to(device)
+
+if "summarize" in modules:
+ print("Initializing a text summarization model...")
+ summarization_tokenizer = AutoTokenizer.from_pretrained(summarization_model)
+ summarization_transformer = AutoModelForSeq2SeqLM.from_pretrained(
+ summarization_model, torch_dtype=torch_dtype
+ ).to(device)
+
+if "classify" in modules:
+ print("Initializing a sentiment classification pipeline...")
+ classification_pipe = pipeline(
+ "text-classification",
+ model=classification_model,
+ top_k=None,
+ device=device,
+ torch_dtype=torch_dtype,
+ )
+
+if "sd" in modules and not sd_use_remote:
+ from diffusers import StableDiffusionPipeline
+ from diffusers import EulerAncestralDiscreteScheduler
+
+ print("Initializing Stable Diffusion pipeline")
+ sd_device_string = (
+ "cuda" if torch.cuda.is_available() and not args.sd_cpu else "cpu"
+ )
+ sd_device = torch.device(sd_device_string)
+ sd_torch_dtype = torch.float32 if sd_device_string == "cpu" else torch.float16
+ sd_pipe = StableDiffusionPipeline.from_pretrained(
+ sd_model, custom_pipeline="lpw_stable_diffusion", torch_dtype=sd_torch_dtype
+ ).to(sd_device)
+ sd_pipe.safety_checker = lambda images, clip_input: (images, False)
+ sd_pipe.enable_attention_slicing()
+ # pipe.scheduler = KarrasVeScheduler.from_config(pipe.scheduler.config)
+ sd_pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(
+ sd_pipe.scheduler.config
+ )
+elif "sd" in modules and sd_use_remote:
+ print("Initializing Stable Diffusion connection")
+ try:
+ sd_remote = webuiapi.WebUIApi(
+ host=sd_remote_host, port=sd_remote_port, use_https=sd_remote_ssl
+ )
+ if sd_remote_auth:
+ username, password = sd_remote_auth.split(":")
+ sd_remote.set_auth(username, password)
+ sd_remote.util_wait_for_ready()
+ except Exception as e:
+ # remote sd from modules
+ print(
+ f"{Fore.RED}{Style.BRIGHT}Could not connect to remote SD backend at http{'s' if sd_remote_ssl else ''}://{sd_remote_host}:{sd_remote_port}! Disabling SD module...{Style.RESET_ALL}"
+ )
+ modules.remove("sd")
+
+if "tts" in modules:
+ print("tts module is deprecated. Please use silero-tts instead.")
+ modules.remove("tts")
+ modules.append("silero-tts")
+
+
+if "silero-tts" in modules:
+ if not os.path.exists(SILERO_SAMPLES_PATH):
+ os.makedirs(SILERO_SAMPLES_PATH)
+ print("Initializing Silero TTS server")
+ from silero_api_server import tts
+
+ tts_service = tts.SileroTtsService(SILERO_SAMPLES_PATH)
+ if len(os.listdir(SILERO_SAMPLES_PATH)) == 0:
+ print("Generating Silero TTS samples...")
+ tts_service.update_sample_text(SILERO_SAMPLE_TEXT)
+ tts_service.generate_samples()
+
+
+if "edge-tts" in modules:
+ print("Initializing Edge TTS client")
+ import tts_edge as edge
+
+
+if "chromadb" in modules:
+ print("Initializing ChromaDB")
+ import chromadb
+ import posthog
+ from chromadb.config import Settings
+ from sentence_transformers import SentenceTransformer
+
+ # Assume that the user wants in-memory unless a host is specified
+ # Also disable chromadb telemetry
+ posthog.capture = lambda *args, **kwargs: None
+ if args.chroma_host is None:
+ chromadb_client = chromadb.Client(Settings(anonymized_telemetry=False, persist_directory=args.chroma_folder, chroma_db_impl='duckdb+parquet'))
+ print(f"ChromaDB is running in-memory with persistence. Persistence is stored in {args.chroma_folder}. Can be cleared by deleting the folder or purging db.")
+ else:
+ chroma_port=(
+ args.chroma_port if args.chroma_port else DEFAULT_CHROMA_PORT
+ )
+ chromadb_client = chromadb.Client(
+ Settings(
+ anonymized_telemetry=False,
+ chroma_api_impl="rest",
+ chroma_server_host=args.chroma_host,
+ chroma_server_http_port=chroma_port
+ )
+ )
+ print(f"ChromaDB is remotely configured at {args.chroma_host}:{chroma_port}")
+
+ chromadb_embedder = SentenceTransformer(embedding_model)
+ chromadb_embed_fn = lambda *args, **kwargs: chromadb_embedder.encode(*args, **kwargs).tolist()
+
+ # Check if the db is connected and running, otherwise tell the user
+ try:
+ chromadb_client.heartbeat()
+ print("Successfully pinged ChromaDB! Your client is successfully connected.")
+ except:
+ print("Could not ping ChromaDB! If you are running remotely, please check your host and port!")
+
+# Flask init
+app = Flask(__name__)
+CORS(app) # allow cross-domain requests
+Compress(app) # compress responses
+app.config["MAX_CONTENT_LENGTH"] = 100 * 1024 * 1024
+
+
+def require_module(name):
+ def wrapper(fn):
+ @wraps(fn)
+ def decorated_view(*args, **kwargs):
+ if name not in modules:
+ abort(403, "Module is disabled by config")
+ return fn(*args, **kwargs)
+
+ return decorated_view
+
+ return wrapper
+
+
+# AI stuff
+def classify_text(text: str) -> list:
+ output = classification_pipe(
+ text,
+ truncation=True,
+ max_length=classification_pipe.model.config.max_position_embeddings,
+ )[0]
+ return sorted(output, key=lambda x: x["score"], reverse=True)
+
+
+def caption_image(raw_image: Image, max_new_tokens: int = 20) -> str:
+ inputs = captioning_processor(raw_image.convert("RGB"), return_tensors="pt").to(
+ device, torch_dtype
+ )
+ outputs = captioning_transformer.generate(**inputs, max_new_tokens=max_new_tokens)
+ caption = captioning_processor.decode(outputs[0], skip_special_tokens=True)
+ return caption
+
+
+def summarize_chunks(text: str, params: dict) -> str:
+ try:
+ return summarize(text, params)
+ except IndexError:
+ print(
+ "Sequence length too large for model, cutting text in half and calling again"
+ )
+ new_params = params.copy()
+ new_params["max_length"] = new_params["max_length"] // 2
+ new_params["min_length"] = new_params["min_length"] // 2
+ return summarize_chunks(
+ text[: (len(text) // 2)], new_params
+ ) + summarize_chunks(text[(len(text) // 2) :], new_params)
+
+
+def summarize(text: str, params: dict) -> str:
+ # Tokenize input
+ inputs = summarization_tokenizer(text, return_tensors="pt").to(device)
+ token_count = len(inputs[0])
+
+ bad_words_ids = [
+ summarization_tokenizer(bad_word, add_special_tokens=False).input_ids
+ for bad_word in params["bad_words"]
+ ]
+ summary_ids = summarization_transformer.generate(
+ inputs["input_ids"],
+ num_beams=2,
+ max_new_tokens=max(token_count, int(params["max_length"])),
+ min_new_tokens=min(token_count, int(params["min_length"])),
+ repetition_penalty=float(params["repetition_penalty"]),
+ temperature=float(params["temperature"]),
+ length_penalty=float(params["length_penalty"]),
+ bad_words_ids=bad_words_ids,
+ )
+ summary = summarization_tokenizer.batch_decode(
+ summary_ids, skip_special_tokens=True, clean_up_tokenization_spaces=True
+ )[0]
+ summary = normalize_string(summary)
+ return summary
+
+
+def normalize_string(input: str) -> str:
+ output = " ".join(unicodedata.normalize("NFKC", input).strip().split())
+ return output
+
+
+def generate_image(data: dict) -> Image:
+ prompt = normalize_string(f'{data["prompt_prefix"]} {data["prompt"]}')
+
+ if sd_use_remote:
+ image = sd_remote.txt2img(
+ prompt=prompt,
+ negative_prompt=data["negative_prompt"],
+ sampler_name=data["sampler"],
+ steps=data["steps"],
+ cfg_scale=data["scale"],
+ width=data["width"],
+ height=data["height"],
+ restore_faces=data["restore_faces"],
+ enable_hr=data["enable_hr"],
+ save_images=True,
+ send_images=True,
+ do_not_save_grid=False,
+ do_not_save_samples=False,
+ ).image
+ else:
+ image = sd_pipe(
+ prompt=prompt,
+ negative_prompt=data["negative_prompt"],
+ num_inference_steps=data["steps"],
+ guidance_scale=data["scale"],
+ width=data["width"],
+ height=data["height"],
+ ).images[0]
+
+ image.save("./debug.png")
+ return image
+
+
+def image_to_base64(image: Image, quality: int = 75) -> str:
+ buffer = BytesIO()
+ image.convert("RGB")
+ image.save(buffer, format="JPEG", quality=quality)
+ img_str = base64.b64encode(buffer.getvalue()).decode("utf-8")
+ return img_str
+
+# Reads an API key from an already existing file. If that file doesn't exist, create it.
+if args.secure:
+ try:
+ with open("api_key.txt", "r") as txt:
+ api_key = txt.read().replace('\n', '')
+ except:
+ api_key = secrets.token_hex(5)
+ with open("api_key.txt", "w") as txt:
+ txt.write(api_key)
+
+ print(f"Your API key is {api_key}")
+elif args.share and args.secure != True:
+ print("WARNING: This instance is publicly exposed without an API key! It is highly recommended to restart with the \"--secure\" argument!")
+else:
+ print("No API key given because you are running locally.")
+
+@app.before_request
+def before_request():
+ # Request time measuring
+ request.start_time = time.time()
+
+ # Checks if an API key is present and valid, otherwise return unauthorized
+ # The options check is required so CORS doesn't get angry
+ try:
+ if request.method != 'OPTIONS' and args.secure and request.authorization.token != api_key:
+ print(f"WARNING: Unauthorized API key access from {request.remote_addr}")
+ response = jsonify({ 'error': '401: Invalid API key' })
+ response.status_code = 401
+ return response
+ except Exception as e:
+ print(f"API key check error: {e}")
+ return "401 Unauthorized\n{}\n\n".format(e), 401
+
+
+@app.after_request
+def after_request(response):
+ duration = time.time() - request.start_time
+ response.headers["X-Request-Duration"] = str(duration)
+ return response
+
+
+@app.route("/", methods=["GET"])
+def index():
+ with open("./README.md", "r", encoding="utf8") as f:
+ content = f.read()
+ return render_template_string(markdown.markdown(content, extensions=["tables"]))
+
+
+@app.route("/api/extensions", methods=["GET"])
+def get_extensions():
+ extensions = dict(
+ {
+ "extensions": [
+ {
+ "name": "not-supported",
+ "metadata": {
+ "display_name": """Extensions serving using Extensions API is no longer supported. Please update the mod from: https://github.com/Cohee1207/SillyTavern""",
+ "requires": [],
+ "assets": [],
+ },
+ }
+ ]
+ }
+ )
+ return jsonify(extensions)
+
+
+@app.route("/api/caption", methods=["POST"])
+@require_module("caption")
+def api_caption():
+ data = request.get_json()
+
+ if "image" not in data or not isinstance(data["image"], str):
+ abort(400, '"image" is required')
+
+ image = Image.open(BytesIO(base64.b64decode(data["image"])))
+ image = image.convert("RGB")
+ image.thumbnail((512, 512))
+ caption = caption_image(image)
+ thumbnail = image_to_base64(image)
+ print("Caption:", caption, sep="\n")
+ gc.collect()
+ return jsonify({"caption": caption, "thumbnail": thumbnail})
+
+
+@app.route("/api/summarize", methods=["POST"])
+@require_module("summarize")
+def api_summarize():
+ data = request.get_json()
+
+ if "text" not in data or not isinstance(data["text"], str):
+ abort(400, '"text" is required')
+
+ params = DEFAULT_SUMMARIZE_PARAMS.copy()
+
+ if "params" in data and isinstance(data["params"], dict):
+ params.update(data["params"])
+
+ print("Summary input:", data["text"], sep="\n")
+ summary = summarize_chunks(data["text"], params)
+ print("Summary output:", summary, sep="\n")
+ gc.collect()
+ return jsonify({"summary": summary})
+
+
+@app.route("/api/classify", methods=["POST"])
+@require_module("classify")
+def api_classify():
+ data = request.get_json()
+
+ if "text" not in data or not isinstance(data["text"], str):
+ abort(400, '"text" is required')
+
+ print("Classification input:", data["text"], sep="\n")
+ classification = classify_text(data["text"])
+ print("Classification output:", classification, sep="\n")
+ gc.collect()
+ return jsonify({"classification": classification})
+
+
+@app.route("/api/classify/labels", methods=["GET"])
+@require_module("classify")
+def api_classify_labels():
+ classification = classify_text("")
+ labels = [x["label"] for x in classification]
+ return jsonify({"labels": labels})
+
+
+@app.route("/api/image", methods=["POST"])
+@require_module("sd")
+def api_image():
+ required_fields = {
+ "prompt": str,
+ }
+
+ optional_fields = {
+ "steps": 30,
+ "scale": 6,
+ "sampler": "DDIM",
+ "width": 512,
+ "height": 512,
+ "restore_faces": False,
+ "enable_hr": False,
+ "prompt_prefix": PROMPT_PREFIX,
+ "negative_prompt": NEGATIVE_PROMPT,
+ }
+
+ data = request.get_json()
+
+ # Check required fields
+ for field, field_type in required_fields.items():
+ if field not in data or not isinstance(data[field], field_type):
+ abort(400, f'"{field}" is required')
+
+ # Set optional fields to default values if not provided
+ for field, default_value in optional_fields.items():
+ type_match = (
+ (int, float)
+ if isinstance(default_value, (int, float))
+ else type(default_value)
+ )
+ if field not in data or not isinstance(data[field], type_match):
+ data[field] = default_value
+
+ try:
+ print("SD inputs:", data, sep="\n")
+ image = generate_image(data)
+ base64image = image_to_base64(image, quality=90)
+ return jsonify({"image": base64image})
+ except RuntimeError as e:
+ abort(400, str(e))
+
+
+@app.route("/api/image/model", methods=["POST"])
+@require_module("sd")
+def api_image_model_set():
+ data = request.get_json()
+
+ if not sd_use_remote:
+ abort(400, "Changing model for local sd is not supported.")
+ if "model" not in data or not isinstance(data["model"], str):
+ abort(400, '"model" is required')
+
+ old_model = sd_remote.util_get_current_model()
+ sd_remote.util_set_model(data["model"], find_closest=False)
+ # sd_remote.util_set_model(data['model'])
+ sd_remote.util_wait_for_ready()
+ new_model = sd_remote.util_get_current_model()
+
+ return jsonify({"previous_model": old_model, "current_model": new_model})
+
+
+@app.route("/api/image/model", methods=["GET"])
+@require_module("sd")
+def api_image_model_get():
+ model = sd_model
+
+ if sd_use_remote:
+ model = sd_remote.util_get_current_model()
+
+ return jsonify({"model": model})
+
+
+@app.route("/api/image/models", methods=["GET"])
+@require_module("sd")
+def api_image_models():
+ models = [sd_model]
+
+ if sd_use_remote:
+ models = sd_remote.util_get_model_names()
+
+ return jsonify({"models": models})
+
+
+@app.route("/api/image/samplers", methods=["GET"])
+@require_module("sd")
+def api_image_samplers():
+ samplers = ["Euler a"]
+
+ if sd_use_remote:
+ samplers = [sampler["name"] for sampler in sd_remote.get_samplers()]
+
+ return jsonify({"samplers": samplers})
+
+
+@app.route("/api/modules", methods=["GET"])
+def get_modules():
+ return jsonify({"modules": modules})
+
+
+@app.route("/api/tts/speakers", methods=["GET"])
+@require_module("silero-tts")
+def tts_speakers():
+ voices = [
+ {
+ "name": speaker,
+ "voice_id": speaker,
+ "preview_url": f"{str(request.url_root)}api/tts/sample/{speaker}",
+ }
+ for speaker in tts_service.get_speakers()
+ ]
+ return jsonify(voices)
+
+
+@app.route("/api/tts/generate", methods=["POST"])
+@require_module("silero-tts")
+def tts_generate():
+ voice = request.get_json()
+ if "text" not in voice or not isinstance(voice["text"], str):
+ abort(400, '"text" is required')
+ if "speaker" not in voice or not isinstance(voice["speaker"], str):
+ abort(400, '"speaker" is required')
+ # Remove asterisks
+ voice["text"] = voice["text"].replace("*", "")
+ try:
+ audio = tts_service.generate(voice["speaker"], voice["text"])
+ return send_file(audio, mimetype="audio/x-wav")
+ except Exception as e:
+ print(e)
+ abort(500, voice["speaker"])
+
+
+@app.route("/api/tts/sample/", methods=["GET"])
+@require_module("silero-tts")
+def tts_play_sample(speaker: str):
+ return send_from_directory(SILERO_SAMPLES_PATH, f"{speaker}.wav")
+
+
+@app.route("/api/edge-tts/list", methods=["GET"])
+@require_module("edge-tts")
+def edge_tts_list():
+ voices = edge.get_voices()
+ return jsonify(voices)
+
+
+@app.route("/api/edge-tts/generate", methods=["POST"])
+@require_module("edge-tts")
+def edge_tts_generate():
+ data = request.get_json()
+ if "text" not in data or not isinstance(data["text"], str):
+ abort(400, '"text" is required')
+ if "voice" not in data or not isinstance(data["voice"], str):
+ abort(400, '"voice" is required')
+ if "rate" in data and isinstance(data['rate'], int):
+ rate = data['rate']
+ else:
+ rate = 0
+ # Remove asterisks
+ data["text"] = data["text"].replace("*", "")
+ try:
+ audio = edge.generate_audio(text=data["text"], voice=data["voice"], rate=rate)
+ return Response(audio, mimetype="audio/mpeg")
+ except Exception as e:
+ print(e)
+ abort(500, data["voice"])
+
+
+@app.route("/api/chromadb", methods=["POST"])
+@require_module("chromadb")
+def chromadb_add_messages():
+ data = request.get_json()
+ if "chat_id" not in data or not isinstance(data["chat_id"], str):
+ abort(400, '"chat_id" is required')
+ if "messages" not in data or not isinstance(data["messages"], list):
+ abort(400, '"messages" is required')
+
+ chat_id_md5 = hashlib.md5(data["chat_id"].encode()).hexdigest()
+ collection = chromadb_client.get_or_create_collection(
+ name=f"chat-{chat_id_md5}", embedding_function=chromadb_embed_fn
+ )
+
+ documents = [m["content"] for m in data["messages"]]
+ ids = [m["id"] for m in data["messages"]]
+ metadatas = [
+ {"role": m["role"], "date": m["date"], "meta": m.get("meta", "")}
+ for m in data["messages"]
+ ]
+
+ collection.upsert(
+ ids=ids,
+ documents=documents,
+ metadatas=metadatas,
+ )
+
+ return jsonify({"count": len(ids)})
+
+
+@app.route("/api/chromadb/purge", methods=["POST"])
+@require_module("chromadb")
+def chromadb_purge():
+ data = request.get_json()
+ if "chat_id" not in data or not isinstance(data["chat_id"], str):
+ abort(400, '"chat_id" is required')
+
+ chat_id_md5 = hashlib.md5(data["chat_id"].encode()).hexdigest()
+ collection = chromadb_client.get_or_create_collection(
+ name=f"chat-{chat_id_md5}", embedding_function=chromadb_embed_fn
+ )
+
+ count = collection.count()
+ collection.delete()
+ #Write deletion to persistent folder
+ chromadb_client.persist()
+ print("ChromaDB embeddings deleted", count)
+ return 'Ok', 200
+
+
+@app.route("/api/chromadb/query", methods=["POST"])
+@require_module("chromadb")
+def chromadb_query():
+ data = request.get_json()
+ if "chat_id" not in data or not isinstance(data["chat_id"], str):
+ abort(400, '"chat_id" is required')
+ if "query" not in data or not isinstance(data["query"], str):
+ abort(400, '"query" is required')
+
+ if "n_results" not in data or not isinstance(data["n_results"], int):
+ n_results = 1
+ else:
+ n_results = data["n_results"]
+
+ chat_id_md5 = hashlib.md5(data["chat_id"].encode()).hexdigest()
+ collection = chromadb_client.get_or_create_collection(
+ name=f"chat-{chat_id_md5}", embedding_function=chromadb_embed_fn
+ )
+
+ n_results = min(collection.count(), n_results)
+ query_result = collection.query(
+ query_texts=[data["query"]],
+ n_results=n_results,
+ )
+
+ documents = query_result["documents"][0]
+ ids = query_result["ids"][0]
+ metadatas = query_result["metadatas"][0]
+ distances = query_result["distances"][0]
+
+ messages = [
+ {
+ "id": ids[i],
+ "date": metadatas[i]["date"],
+ "role": metadatas[i]["role"],
+ "meta": metadatas[i]["meta"],
+ "content": documents[i],
+ "distance": distances[i],
+ }
+ for i in range(len(ids))
+ ]
+
+ return jsonify(messages)
+
+
+@app.route("/api/chromadb/export", methods=["POST"])
+@require_module("chromadb")
+def chromadb_export():
+ data = request.get_json()
+ if "chat_id" not in data or not isinstance(data["chat_id"], str):
+ abort(400, '"chat_id" is required')
+
+ chat_id_md5 = hashlib.md5(data["chat_id"].encode()).hexdigest()
+ collection = chromadb_client.get_or_create_collection(
+ name=f"chat-{chat_id_md5}", embedding_function=chromadb_embed_fn
+ )
+ collection_content = collection.get()
+ documents = collection_content.get('documents', [])
+ ids = collection_content.get('ids', [])
+ metadatas = collection_content.get('metadatas', [])
+
+ content = [
+ {
+ "id": ids[i],
+ "metadata": metadatas[i],
+ "document": documents[i],
+ }
+ for i in range(len(ids))
+ ]
+
+ export = {
+ "chat_id": data["chat_id"],
+ "content": content
+ }
+
+
+ return jsonify(export)
+
+@app.route("/api/chromadb/import", methods=["POST"])
+@require_module("chromadb")
+def chromadb_import():
+ data = request.get_json()
+ content = data['content']
+ if "chat_id" not in data or not isinstance(data["chat_id"], str):
+ abort(400, '"chat_id" is required')
+
+ chat_id_md5 = hashlib.md5(data["chat_id"].encode()).hexdigest()
+ collection = chromadb_client.get_or_create_collection(
+ name=f"chat-{chat_id_md5}", embedding_function=chromadb_embed_fn
+ )
+
+ documents = [item['document'] for item in content]
+ metadatas = [item['metadata'] for item in content]
+ ids = [item['id'] for item in content]
+
+
+ collection.upsert(documents=documents, metadatas=metadatas, ids=ids)
+
+ return jsonify({"count": len(ids)})
+
+app.run(host=host, port=port)
diff --git a/tts_edge.py b/tts_edge.py
new file mode 100644
index 0000000000000000000000000000000000000000..7031e18e0b836ec64254e5637f7e10b775c871a0
--- /dev/null
+++ b/tts_edge.py
@@ -0,0 +1,34 @@
+import io
+import edge_tts
+import asyncio
+
+
+def get_voices():
+ voices = asyncio.run(edge_tts.list_voices())
+ return voices
+
+
+async def _iterate_chunks(audio):
+ async for chunk in audio.stream():
+ if chunk["type"] == "audio":
+ yield chunk["data"]
+
+
+async def _async_generator_to_list(async_gen):
+ result = []
+ async for item in async_gen:
+ result.append(item)
+ return result
+
+
+def generate_audio(text: str, voice: str, rate: int) -> bytes:
+ sign = '+' if rate > 0 else '-'
+ rate = f'{sign}{abs(rate)}%'
+ audio = edge_tts.Communicate(text=text, voice=voice, rate=rate)
+ chunks = asyncio.run(_async_generator_to_list(_iterate_chunks(audio)))
+ buffer = io.BytesIO()
+
+ for chunk in chunks:
+ buffer.write(chunk)
+
+ return buffer.getvalue()
diff --git a/tts_samples/en_0.wav b/tts_samples/en_0.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cf0b895801ee29d2d1a3cbf4179d23852aa5562b
Binary files /dev/null and b/tts_samples/en_0.wav differ
diff --git a/tts_samples/en_1.wav b/tts_samples/en_1.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cd4c1f9a57b22f768b1f0c93c01c32a399932455
Binary files /dev/null and b/tts_samples/en_1.wav differ
diff --git a/tts_samples/en_10.wav b/tts_samples/en_10.wav
new file mode 100644
index 0000000000000000000000000000000000000000..22bce4147624cfa1772c9a3601c86c397367bcff
Binary files /dev/null and b/tts_samples/en_10.wav differ
diff --git a/tts_samples/en_11.wav b/tts_samples/en_11.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a208fa40c4429e92cd4dbecb9f9c3c713874656d
Binary files /dev/null and b/tts_samples/en_11.wav differ
diff --git a/tts_samples/en_114.wav b/tts_samples/en_114.wav
new file mode 100644
index 0000000000000000000000000000000000000000..361e7e9f4be035e030835b2ac17c5262859c7896
Binary files /dev/null and b/tts_samples/en_114.wav differ
diff --git a/tts_samples/en_115.wav b/tts_samples/en_115.wav
new file mode 100644
index 0000000000000000000000000000000000000000..b0d0988f1d5e615216273c9f8a35fa32b6142c17
Binary files /dev/null and b/tts_samples/en_115.wav differ
diff --git a/tts_samples/en_116.wav b/tts_samples/en_116.wav
new file mode 100644
index 0000000000000000000000000000000000000000..dc903b0e7efc807cc489d8070dea423fbdd06eeb
Binary files /dev/null and b/tts_samples/en_116.wav differ
diff --git a/tts_samples/en_117.wav b/tts_samples/en_117.wav
new file mode 100644
index 0000000000000000000000000000000000000000..dbe708c5d1f6b894c8d4185732df9571148cf1bb
Binary files /dev/null and b/tts_samples/en_117.wav differ
diff --git a/tts_samples/en_12.wav b/tts_samples/en_12.wav
new file mode 100644
index 0000000000000000000000000000000000000000..78e4a8b87ff9ecf2cabbedae513ae1cbf4e46b82
Binary files /dev/null and b/tts_samples/en_12.wav differ
diff --git a/tts_samples/en_13.wav b/tts_samples/en_13.wav
new file mode 100644
index 0000000000000000000000000000000000000000..24275094c50d8cc8eb7985d06b102fa46a674f15
Binary files /dev/null and b/tts_samples/en_13.wav differ
diff --git a/tts_samples/en_14.wav b/tts_samples/en_14.wav
new file mode 100644
index 0000000000000000000000000000000000000000..41393be1920ff6a3641f2c7fa22a4481f381e0ea
Binary files /dev/null and b/tts_samples/en_14.wav differ
diff --git a/tts_samples/en_15.wav b/tts_samples/en_15.wav
new file mode 100644
index 0000000000000000000000000000000000000000..8462926ceab158938ea3e2a35ed1805b8fc715aa
Binary files /dev/null and b/tts_samples/en_15.wav differ
diff --git a/tts_samples/en_16.wav b/tts_samples/en_16.wav
new file mode 100644
index 0000000000000000000000000000000000000000..e66c91cf1aff07342e45de706a22935962036445
Binary files /dev/null and b/tts_samples/en_16.wav differ
diff --git a/tts_samples/en_17.wav b/tts_samples/en_17.wav
new file mode 100644
index 0000000000000000000000000000000000000000..29e7a815172cb00b5d9f33c8fd28a0f167dd770c
Binary files /dev/null and b/tts_samples/en_17.wav differ
diff --git a/tts_samples/en_18.wav b/tts_samples/en_18.wav
new file mode 100644
index 0000000000000000000000000000000000000000..240260b1ebd5467d80b77278baa2c97f0eb9ff61
Binary files /dev/null and b/tts_samples/en_18.wav differ
diff --git a/tts_samples/en_19.wav b/tts_samples/en_19.wav
new file mode 100644
index 0000000000000000000000000000000000000000..0e9e9e1d68603ea74ec66c351a252ca39df0592e
Binary files /dev/null and b/tts_samples/en_19.wav differ
diff --git a/tts_samples/en_2.wav b/tts_samples/en_2.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cd47f06b20f581b09681f67b8fb0b4e6ed610918
Binary files /dev/null and b/tts_samples/en_2.wav differ
diff --git a/tts_samples/en_20.wav b/tts_samples/en_20.wav
new file mode 100644
index 0000000000000000000000000000000000000000..9e0246100815bfd7ffa6ce98dd6443b4d0f9a292
Binary files /dev/null and b/tts_samples/en_20.wav differ
diff --git a/tts_samples/en_21.wav b/tts_samples/en_21.wav
new file mode 100644
index 0000000000000000000000000000000000000000..6d6e70077d6bb642040c6d900c8d9f2393effcea
Binary files /dev/null and b/tts_samples/en_21.wav differ
diff --git a/tts_samples/en_22.wav b/tts_samples/en_22.wav
new file mode 100644
index 0000000000000000000000000000000000000000..162d86dbb1ca3e3f813f0e3bf00df9ba81dd25b8
Binary files /dev/null and b/tts_samples/en_22.wav differ
diff --git a/tts_samples/en_23.wav b/tts_samples/en_23.wav
new file mode 100644
index 0000000000000000000000000000000000000000..075395390e750456655028fcd134c25a6e68506e
Binary files /dev/null and b/tts_samples/en_23.wav differ
diff --git a/tts_samples/en_24.wav b/tts_samples/en_24.wav
new file mode 100644
index 0000000000000000000000000000000000000000..c5f0d98dce84cbdd4e1d2036a559919e79ce841b
Binary files /dev/null and b/tts_samples/en_24.wav differ
diff --git a/tts_samples/en_25.wav b/tts_samples/en_25.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a60b107b495d8fb430905ae6671172e1262d6132
Binary files /dev/null and b/tts_samples/en_25.wav differ
diff --git a/tts_samples/en_26.wav b/tts_samples/en_26.wav
new file mode 100644
index 0000000000000000000000000000000000000000..d97742831700168bf04310edc42104d61e9f1edf
Binary files /dev/null and b/tts_samples/en_26.wav differ
diff --git a/tts_samples/en_27.wav b/tts_samples/en_27.wav
new file mode 100644
index 0000000000000000000000000000000000000000..622cde347214932bb21a2d8909083274886ba6b6
Binary files /dev/null and b/tts_samples/en_27.wav differ
diff --git a/tts_samples/en_28.wav b/tts_samples/en_28.wav
new file mode 100644
index 0000000000000000000000000000000000000000..6f29462405a1e45b27491cc4bd7cea8678073178
Binary files /dev/null and b/tts_samples/en_28.wav differ
diff --git a/tts_samples/en_29.wav b/tts_samples/en_29.wav
new file mode 100644
index 0000000000000000000000000000000000000000..79171d7088d80d94d44e4e191c58754d8c61dea3
Binary files /dev/null and b/tts_samples/en_29.wav differ
diff --git a/tts_samples/en_3.wav b/tts_samples/en_3.wav
new file mode 100644
index 0000000000000000000000000000000000000000..201f72216e459f1fa22561661b0a954cc1445efd
Binary files /dev/null and b/tts_samples/en_3.wav differ
diff --git a/tts_samples/en_30.wav b/tts_samples/en_30.wav
new file mode 100644
index 0000000000000000000000000000000000000000..0909b3e5b3f9f4d49cd7d87ce00ea920b1b38084
Binary files /dev/null and b/tts_samples/en_30.wav differ
diff --git a/tts_samples/en_31.wav b/tts_samples/en_31.wav
new file mode 100644
index 0000000000000000000000000000000000000000..775354ac13aafae98e8aa2abbdc466931401605a
Binary files /dev/null and b/tts_samples/en_31.wav differ
diff --git a/tts_samples/en_32.wav b/tts_samples/en_32.wav
new file mode 100644
index 0000000000000000000000000000000000000000..29abb9807fd3ea42c205af3800dbedc634008f77
Binary files /dev/null and b/tts_samples/en_32.wav differ
diff --git a/tts_samples/en_33.wav b/tts_samples/en_33.wav
new file mode 100644
index 0000000000000000000000000000000000000000..9f13c730d4446fcc66b510eaabf250785729e8e9
Binary files /dev/null and b/tts_samples/en_33.wav differ
diff --git a/tts_samples/en_34.wav b/tts_samples/en_34.wav
new file mode 100644
index 0000000000000000000000000000000000000000..7209ce26a208ef5c0af88b8e0020c84c9a1f4d63
Binary files /dev/null and b/tts_samples/en_34.wav differ
diff --git a/tts_samples/en_35.wav b/tts_samples/en_35.wav
new file mode 100644
index 0000000000000000000000000000000000000000..88c4296680e665c02801a69395e20f0529a5dd3a
Binary files /dev/null and b/tts_samples/en_35.wav differ
diff --git a/tts_samples/en_36.wav b/tts_samples/en_36.wav
new file mode 100644
index 0000000000000000000000000000000000000000..30a9a0cd53f7d4c8cb479317924b1de9e4f66e5f
Binary files /dev/null and b/tts_samples/en_36.wav differ
diff --git a/tts_samples/en_37.wav b/tts_samples/en_37.wav
new file mode 100644
index 0000000000000000000000000000000000000000..094dbbfe525bf839250d6feca2fa84c8620ce1be
Binary files /dev/null and b/tts_samples/en_37.wav differ
diff --git a/tts_samples/en_38.wav b/tts_samples/en_38.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cfd197b1f8b555d6dbe19ddbdc169e35cfffbd0a
Binary files /dev/null and b/tts_samples/en_38.wav differ
diff --git a/tts_samples/en_39.wav b/tts_samples/en_39.wav
new file mode 100644
index 0000000000000000000000000000000000000000..3c83a38920e16d32d36c150fe3053a7cdbc17726
Binary files /dev/null and b/tts_samples/en_39.wav differ
diff --git a/tts_samples/en_4.wav b/tts_samples/en_4.wav
new file mode 100644
index 0000000000000000000000000000000000000000..c39f1340450debb1e36b2a646b7a52a297154ae8
Binary files /dev/null and b/tts_samples/en_4.wav differ
diff --git a/tts_samples/en_40.wav b/tts_samples/en_40.wav
new file mode 100644
index 0000000000000000000000000000000000000000..592084ce134f4de50526df8a360f69d04ea3daa8
Binary files /dev/null and b/tts_samples/en_40.wav differ
diff --git a/tts_samples/en_41.wav b/tts_samples/en_41.wav
new file mode 100644
index 0000000000000000000000000000000000000000..8f5d4596b3707fd7ff858c9eae0ddfd6c66f3e9c
Binary files /dev/null and b/tts_samples/en_41.wav differ
diff --git a/tts_samples/en_42.wav b/tts_samples/en_42.wav
new file mode 100644
index 0000000000000000000000000000000000000000..b0a8198cd3e9c02b16bf735d954584266131cd2a
Binary files /dev/null and b/tts_samples/en_42.wav differ
diff --git a/tts_samples/en_43.wav b/tts_samples/en_43.wav
new file mode 100644
index 0000000000000000000000000000000000000000..0a0f8ee19307ab1d9f4226821ea63cb90be6ae66
Binary files /dev/null and b/tts_samples/en_43.wav differ
diff --git a/tts_samples/en_44.wav b/tts_samples/en_44.wav
new file mode 100644
index 0000000000000000000000000000000000000000..3cac802a96a0d82029ca5fe3c79f4aecc0cb6a41
Binary files /dev/null and b/tts_samples/en_44.wav differ
diff --git a/tts_samples/en_45.wav b/tts_samples/en_45.wav
new file mode 100644
index 0000000000000000000000000000000000000000..21a012a0d0e5ce441ccf06a848583ead60b28a5e
Binary files /dev/null and b/tts_samples/en_45.wav differ
diff --git a/tts_samples/en_46.wav b/tts_samples/en_46.wav
new file mode 100644
index 0000000000000000000000000000000000000000..f5bc0b67d64ffc6bd6ef2a35bce9c536e6192446
Binary files /dev/null and b/tts_samples/en_46.wav differ
diff --git a/tts_samples/en_47.wav b/tts_samples/en_47.wav
new file mode 100644
index 0000000000000000000000000000000000000000..f0407872d08ba2e526d070745c7ac211a9530385
Binary files /dev/null and b/tts_samples/en_47.wav differ
diff --git a/tts_samples/en_48.wav b/tts_samples/en_48.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cf431e8b530cf88adf7bffd43d5c4a711a7e90be
Binary files /dev/null and b/tts_samples/en_48.wav differ
diff --git a/tts_samples/en_49.wav b/tts_samples/en_49.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4fe382f652d6ab4829cd7c05783574aa0a960ddd
Binary files /dev/null and b/tts_samples/en_49.wav differ
diff --git a/tts_samples/en_5.wav b/tts_samples/en_5.wav
new file mode 100644
index 0000000000000000000000000000000000000000..7e9a49f78320d2655a54bff3f0922051460a5ded
Binary files /dev/null and b/tts_samples/en_5.wav differ
diff --git a/tts_samples/en_50.wav b/tts_samples/en_50.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4f1f0a459a34be10b7935d99a4a70bb2b75ec3ed
Binary files /dev/null and b/tts_samples/en_50.wav differ
diff --git a/tts_samples/en_51.wav b/tts_samples/en_51.wav
new file mode 100644
index 0000000000000000000000000000000000000000..3a5165dfed2b830b3550034c4a1aa2c0facda722
Binary files /dev/null and b/tts_samples/en_51.wav differ
diff --git a/tts_samples/en_52.wav b/tts_samples/en_52.wav
new file mode 100644
index 0000000000000000000000000000000000000000..13c5e9d9769f8f8defda17a54d2f85a107b257ae
Binary files /dev/null and b/tts_samples/en_52.wav differ
diff --git a/tts_samples/en_53.wav b/tts_samples/en_53.wav
new file mode 100644
index 0000000000000000000000000000000000000000..58e73e10b3649d003eed620bfbbc6fc01778c7f2
Binary files /dev/null and b/tts_samples/en_53.wav differ
diff --git a/tts_samples/en_54.wav b/tts_samples/en_54.wav
new file mode 100644
index 0000000000000000000000000000000000000000..2fb0cfc69502a816a2b424e55b08324e481ca6c3
Binary files /dev/null and b/tts_samples/en_54.wav differ
diff --git a/tts_samples/en_55.wav b/tts_samples/en_55.wav
new file mode 100644
index 0000000000000000000000000000000000000000..6ac094e0745e0d8065dce3942af4f0bb4dd1232f
Binary files /dev/null and b/tts_samples/en_55.wav differ
diff --git a/tts_samples/en_56.wav b/tts_samples/en_56.wav
new file mode 100644
index 0000000000000000000000000000000000000000..8261f8f8723d85257eb31c1232c7cf18d8e4f62e
Binary files /dev/null and b/tts_samples/en_56.wav differ
diff --git a/tts_samples/en_57.wav b/tts_samples/en_57.wav
new file mode 100644
index 0000000000000000000000000000000000000000..2e807664f4e84452069307b3a4dfa43712edfa32
Binary files /dev/null and b/tts_samples/en_57.wav differ
diff --git a/tts_samples/en_58.wav b/tts_samples/en_58.wav
new file mode 100644
index 0000000000000000000000000000000000000000..576f505ef3e9c5041cadefc3f85b7f2aa03d28e2
Binary files /dev/null and b/tts_samples/en_58.wav differ
diff --git a/tts_samples/en_59.wav b/tts_samples/en_59.wav
new file mode 100644
index 0000000000000000000000000000000000000000..d8551b537b7519b54d32de9180bac6ea32e20d74
Binary files /dev/null and b/tts_samples/en_59.wav differ
diff --git a/tts_samples/en_6.wav b/tts_samples/en_6.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cd312884349a93671be4f804db4b170f0184f07c
Binary files /dev/null and b/tts_samples/en_6.wav differ
diff --git a/tts_samples/en_60.wav b/tts_samples/en_60.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a6784293cc9a6fc9a001d534a1643cc0db22ae20
Binary files /dev/null and b/tts_samples/en_60.wav differ
diff --git a/tts_samples/en_61.wav b/tts_samples/en_61.wav
new file mode 100644
index 0000000000000000000000000000000000000000..c7490b557af6d016e917e30651baaaf95b5f5ee2
Binary files /dev/null and b/tts_samples/en_61.wav differ
diff --git a/tts_samples/en_62.wav b/tts_samples/en_62.wav
new file mode 100644
index 0000000000000000000000000000000000000000..3a0eea6d7e94f15f584d3c90c306ce8d1d342b9c
Binary files /dev/null and b/tts_samples/en_62.wav differ
diff --git a/tts_samples/en_63.wav b/tts_samples/en_63.wav
new file mode 100644
index 0000000000000000000000000000000000000000..30d885aec6d690e3ea235051a9d11f2e7c24e2e1
Binary files /dev/null and b/tts_samples/en_63.wav differ
diff --git a/tts_samples/en_64.wav b/tts_samples/en_64.wav
new file mode 100644
index 0000000000000000000000000000000000000000..2b59028499921648cc91c3b77c021ef0fb238428
Binary files /dev/null and b/tts_samples/en_64.wav differ
diff --git a/tts_samples/en_65.wav b/tts_samples/en_65.wav
new file mode 100644
index 0000000000000000000000000000000000000000..6908f663de319e983eff451c3182116e834f2b9f
Binary files /dev/null and b/tts_samples/en_65.wav differ
diff --git a/tts_samples/en_66.wav b/tts_samples/en_66.wav
new file mode 100644
index 0000000000000000000000000000000000000000..1cd13462ecba6a6bf51848532ef7fddb0a1d2272
Binary files /dev/null and b/tts_samples/en_66.wav differ
diff --git a/tts_samples/en_67.wav b/tts_samples/en_67.wav
new file mode 100644
index 0000000000000000000000000000000000000000..bcabb01eb7691089113f234c25fcc5be9c1923f5
Binary files /dev/null and b/tts_samples/en_67.wav differ
diff --git a/tts_samples/en_68.wav b/tts_samples/en_68.wav
new file mode 100644
index 0000000000000000000000000000000000000000..100eec2722ddf12be87bb751e54f41ba873233d9
Binary files /dev/null and b/tts_samples/en_68.wav differ
diff --git a/tts_samples/en_69.wav b/tts_samples/en_69.wav
new file mode 100644
index 0000000000000000000000000000000000000000..7fd472cfe6dc4f185056c2c177b8c417f2e1837d
Binary files /dev/null and b/tts_samples/en_69.wav differ
diff --git a/tts_samples/en_7.wav b/tts_samples/en_7.wav
new file mode 100644
index 0000000000000000000000000000000000000000..6294aac97ae0e2143c6ffd3735d4d7c9c1f8d786
Binary files /dev/null and b/tts_samples/en_7.wav differ
diff --git a/tts_samples/en_70.wav b/tts_samples/en_70.wav
new file mode 100644
index 0000000000000000000000000000000000000000..0173a3e6e869724c711038059e8472eae29c4ccd
Binary files /dev/null and b/tts_samples/en_70.wav differ
diff --git a/tts_samples/en_71.wav b/tts_samples/en_71.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cca3b7fa01bc878150291dca5ad3354d46161d8b
Binary files /dev/null and b/tts_samples/en_71.wav differ
diff --git a/tts_samples/en_72.wav b/tts_samples/en_72.wav
new file mode 100644
index 0000000000000000000000000000000000000000..6791895448e4a4e2aef85acfef06be6152bcc7fd
Binary files /dev/null and b/tts_samples/en_72.wav differ
diff --git a/tts_samples/en_73.wav b/tts_samples/en_73.wav
new file mode 100644
index 0000000000000000000000000000000000000000..535b1d7e28c4b9e4b6e0905079d5774ae3613b6d
Binary files /dev/null and b/tts_samples/en_73.wav differ
diff --git a/tts_samples/en_74.wav b/tts_samples/en_74.wav
new file mode 100644
index 0000000000000000000000000000000000000000..9baa790e0d17189e3a38a4fa48ffb876e9ded173
Binary files /dev/null and b/tts_samples/en_74.wav differ
diff --git a/tts_samples/en_75.wav b/tts_samples/en_75.wav
new file mode 100644
index 0000000000000000000000000000000000000000..cd2b3ba085059c77cc3462b0a11a709334ece1cf
Binary files /dev/null and b/tts_samples/en_75.wav differ
diff --git a/tts_samples/en_76.wav b/tts_samples/en_76.wav
new file mode 100644
index 0000000000000000000000000000000000000000..bc09734d53fddde5c751cad17fc81c263537d262
Binary files /dev/null and b/tts_samples/en_76.wav differ
diff --git a/tts_samples/en_77.wav b/tts_samples/en_77.wav
new file mode 100644
index 0000000000000000000000000000000000000000..5449b1f9f3f19e535e6717b49fc7fad52f13a68b
Binary files /dev/null and b/tts_samples/en_77.wav differ
diff --git a/tts_samples/en_78.wav b/tts_samples/en_78.wav
new file mode 100644
index 0000000000000000000000000000000000000000..46843ae0028ad4e6d547d4e83aadd48a5f08886d
Binary files /dev/null and b/tts_samples/en_78.wav differ
diff --git a/tts_samples/en_79.wav b/tts_samples/en_79.wav
new file mode 100644
index 0000000000000000000000000000000000000000..3cde5044967dac98e13b6b163db2af3f121bc4af
Binary files /dev/null and b/tts_samples/en_79.wav differ
diff --git a/tts_samples/en_8.wav b/tts_samples/en_8.wav
new file mode 100644
index 0000000000000000000000000000000000000000..5169a2be020a136cd50f2c1546240145093a8918
Binary files /dev/null and b/tts_samples/en_8.wav differ
diff --git a/tts_samples/en_80.wav b/tts_samples/en_80.wav
new file mode 100644
index 0000000000000000000000000000000000000000..34fd4ab10ba75dc3c0e55d1d414b6d3b89ab57ce
Binary files /dev/null and b/tts_samples/en_80.wav differ
diff --git a/tts_samples/en_81.wav b/tts_samples/en_81.wav
new file mode 100644
index 0000000000000000000000000000000000000000..a39784fb6cd78cc9fe5686d3225e1256496b069a
Binary files /dev/null and b/tts_samples/en_81.wav differ
diff --git a/tts_samples/en_82.wav b/tts_samples/en_82.wav
new file mode 100644
index 0000000000000000000000000000000000000000..8a459daefd87df081885452d297e0aedf0115e81
Binary files /dev/null and b/tts_samples/en_82.wav differ
diff --git a/tts_samples/en_83.wav b/tts_samples/en_83.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4e34ad50246a6c85e0c68bf349e83e73a476a714
Binary files /dev/null and b/tts_samples/en_83.wav differ
diff --git a/tts_samples/en_84.wav b/tts_samples/en_84.wav
new file mode 100644
index 0000000000000000000000000000000000000000..085e751bcfd359f1cea31aaf101ac0a86092babc
Binary files /dev/null and b/tts_samples/en_84.wav differ
diff --git a/tts_samples/en_85.wav b/tts_samples/en_85.wav
new file mode 100644
index 0000000000000000000000000000000000000000..de71ae98a378bd42b2afc20aa6b68d2a6298f8e8
Binary files /dev/null and b/tts_samples/en_85.wav differ
diff --git a/tts_samples/en_86.wav b/tts_samples/en_86.wav
new file mode 100644
index 0000000000000000000000000000000000000000..dbbb7096fe92b608cb8af20b419261f02471e32d
Binary files /dev/null and b/tts_samples/en_86.wav differ
diff --git a/tts_samples/en_87.wav b/tts_samples/en_87.wav
new file mode 100644
index 0000000000000000000000000000000000000000..961e063ed737aed610f5fd16ebde8a6e320a90cf
Binary files /dev/null and b/tts_samples/en_87.wav differ
diff --git a/tts_samples/en_88.wav b/tts_samples/en_88.wav
new file mode 100644
index 0000000000000000000000000000000000000000..98df7579b45a4bd366a7eeff70934d42eba3b87c
Binary files /dev/null and b/tts_samples/en_88.wav differ
diff --git a/tts_samples/en_89.wav b/tts_samples/en_89.wav
new file mode 100644
index 0000000000000000000000000000000000000000..446bdc5d257386adfb0c078177f863e0a4f3c37d
Binary files /dev/null and b/tts_samples/en_89.wav differ
diff --git a/tts_samples/en_9.wav b/tts_samples/en_9.wav
new file mode 100644
index 0000000000000000000000000000000000000000..23387cc66439a8e208b35ff1d2f3257aef3260a7
Binary files /dev/null and b/tts_samples/en_9.wav differ
diff --git a/tts_samples/en_90.wav b/tts_samples/en_90.wav
new file mode 100644
index 0000000000000000000000000000000000000000..ddbd0f15679a823f707c1d07e0928586f5b72dee
Binary files /dev/null and b/tts_samples/en_90.wav differ
diff --git a/tts_samples/en_91.wav b/tts_samples/en_91.wav
new file mode 100644
index 0000000000000000000000000000000000000000..79bd6d9210ae6cafeaacacccf30d3204c869a118
Binary files /dev/null and b/tts_samples/en_91.wav differ
diff --git a/tts_samples/en_92.wav b/tts_samples/en_92.wav
new file mode 100644
index 0000000000000000000000000000000000000000..b9aae831a406df66d5e2b396d318f7c7453d0a39
Binary files /dev/null and b/tts_samples/en_92.wav differ
diff --git a/tts_samples/en_93.wav b/tts_samples/en_93.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4b7384946970d50b46861b82a7fb539310f3d7af
Binary files /dev/null and b/tts_samples/en_93.wav differ
diff --git a/tts_samples/en_94.wav b/tts_samples/en_94.wav
new file mode 100644
index 0000000000000000000000000000000000000000..b1e4676a47fb4650780beb7774e0d31cdf16f7eb
Binary files /dev/null and b/tts_samples/en_94.wav differ