Release of 1.17

Release of 1.17
This commit is contained in:
henk717 2022-02-06 11:59:58 +01:00 committed by GitHub
commit 03e017bffd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
118 changed files with 11974 additions and 800 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*.min.lua linguist-vendored
*documentation.html linguist-vendored

13
.gitignore vendored
View File

@ -1,15 +1,24 @@
# Ignore client settings file
client.settings
settings/*
# Ignore stories file except for test_story
stories/*
settings/*
!stories/sample_story.json
# Ignore stuff that would polute our Git
/.project
*.bak
miniconda3/*
*.settings
__pycache__
*.log
cache/*
userscripts/*
!userscripts/examples
!userscripts/kaipreset_*.lua
!userscripts/Readme.*
!userscripts/api_documentation.*
softprompts/*
# Ignore PyCharm project files.
.idea

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
'''
This is a MODIFIED version of arrmansa's low VRAM patch.
https://github.com/arrmansa/Basic-UI-for-GPT-J-6B-with-low-vram/blob/main/GPT-J-6B-Low-Vram-UI.ipynb
The ORIGINAL version of the patch is released under the Apache License 2.0
Copyright 2021 arrmansa
Copyright 2021 finetuneanon
Copyright 2018 The Hugging Face team
Released under the Apache License 2.0
Apache License
@ -215,6 +215,9 @@ import torch
import torch.cuda.comm
import copy
import gc
import sys
import itertools
import bisect
from transformers.modeling_outputs import BaseModelOutputWithPast
@ -222,17 +225,51 @@ from transformers.utils import logging
logger = logging.get_logger(__name__)
class MaxSharedRamBlocksException(Exception):
def __init__(self, i: int):
self.corrected_max_shared_ram_blocks = i
super().__init__('max_shared_ram_blocks is set too high, please set it to '+str(i))
breakmodel = True
gpu_device = 'cuda'
total_blocks = 24
ram_blocks = 7
max_shared_ram_blocks = None
gpu_blocks = []
primary_device = 0
def move_hidden_layers(transformer):
assert len(gpu_blocks) <= torch.cuda.device_count()
assert sum(gpu_blocks) <= len(transformer.h)
ram_blocks = len(transformer.h) - sum(gpu_blocks)
transformer.extrastorage = {}
torch.cuda.empty_cache()
able_to_pin_layers = True
for i in range(ram_blocks):
transformer.h[i].to("cpu")
transformer.extrastorage[i] = copy.deepcopy(transformer.h[i])
smalltensor = torch.tensor(0).to(primary_device)
for param1 in transformer.h[i].parameters():
param1.data = smalltensor
transformer.h[i].to(primary_device)
for param in transformer.extrastorage[i].parameters():
param.requires_grad = False
param.data = param.data.detach()
if able_to_pin_layers:
try:
param.data = param.data.pin_memory()
except:
able_to_pin_layers = False
print(f"WARNING: You only have enough shared GPU memory for {i} out of {ram_blocks} CPU layers. Expect suboptimal speed.", file=sys.stderr)
gc.collect()
torch.cuda.empty_cache()
if ram_blocks:
for param1,param2 in zip(transformer.h[0].parameters(),transformer.extrastorage[0].parameters()):
param1.data = param2.data.to(primary_device, non_blocking=False).detach()
for param1,param2 in zip(transformer.h[ram_blocks-1].parameters(),transformer.extrastorage[ram_blocks-1].parameters()):
param1.data = param2.data.to(primary_device, non_blocking=False).detach()
i = ram_blocks
for j in range(len(gpu_blocks)):
for _ in range(gpu_blocks[j]):
transformer.h[i].to(j)
i += 1
def new_forward(
@ -250,54 +287,11 @@ def new_forward(
return_dict=None,
embs=None,
):
global max_shared_ram_blocks
assert len(gpu_blocks) <= torch.cuda.device_count()
assert sum(gpu_blocks) <= len(self.h)
ram_blocks = len(self.h) - sum(gpu_blocks)
cumulative_gpu_blocks = tuple(itertools.accumulate(gpu_blocks))
if breakmodel:
if max_shared_ram_blocks is None:
max_shared_ram_blocks = total_blocks
if not hasattr(self, 'extrastorage'):
setattr(self,"extrastorage",{})
torch.cuda.empty_cache()
for i in range(ram_blocks,len(self.h)):
self.h[i].to(gpu_device)
for i in range(ram_blocks):
self.h[i].to("cpu")
self.extrastorage[i] = copy.deepcopy(self.h[i])
smalltensor = torch.tensor(0).to(gpu_device)
for param1 in self.h[i].parameters():
param1.data = smalltensor
self.h[i].to(gpu_device)
for i in range(len(self.h)):
for param in self.h[i].parameters():
param.requires_grad = False
param.data = param.data.detach()
gc.collect()
torch.cuda.empty_cache()
for i in range(ram_blocks):
for param in self.extrastorage[i].parameters():
param.requires_grad = False
if i < max_shared_ram_blocks:
try:
param.data = param.data.detach().pin_memory()
except:
raise MaxSharedRamBlocksException(i)
else:
param.data = param.data.detach()
gc.collect()
torch.cuda.empty_cache()
if ram_blocks:
for param1,param2 in zip(self.h[0].parameters(),self.extrastorage[0].parameters()):
param1.data = param2.data.to(gpu_device, non_blocking=False).detach()
for param1,param2 in zip(self.h[ram_blocks-1].parameters(),self.extrastorage[ram_blocks-1].parameters()):
param1.data = param2.data.to(gpu_device, non_blocking=False).detach()
#END MODEL BREAK EDITS
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
output_hidden_states = (
@ -331,7 +325,7 @@ def new_forward(
else:
past_length = past_key_values[0][0].size(-2)
device = input_ids.device if input_ids is not None else inputs_embeds.device
device = primary_device if breakmodel else input_ids.device if input_ids is not None else inputs_embeds.device
if position_ids is None:
position_ids = torch.arange(past_length, input_shape[-1] + past_length, dtype=torch.long, device=device)
position_ids = position_ids.unsqueeze(0).view(-1, input_shape[-1])
@ -339,35 +333,31 @@ def new_forward(
# Attention mask.
if attention_mask is not None:
assert batch_size > 0, "batch_size has to be defined and > 0"
global_attention_mask = attention_mask.view(batch_size, -1)
attention_mask = attention_mask.view(batch_size, -1)
# We create a 3D attention mask from a 2D tensor mask.
# Sizes are [batch_size, 1, 1, to_seq_length]
# So we can broadcast to [batch_size, num_heads, from_seq_length, to_seq_length]
# this attention mask is more simple than the triangular masking of causal attention
# used in OpenAI GPT, we just need to prepare the broadcast dimension here.
global_attention_mask = global_attention_mask[:, None, None, :]
attention_mask = attention_mask[:, None, None, :]
# Since global_attention_mask is 1.0 for positions we want to attend and 0.0 for
# Since attention_mask is 1.0 for positions we want to attend and 0.0 for
# masked positions, this operation will create a tensor which is 0.0 for
# positions we want to attend and -10000.0 for masked positions.
# Since we are adding it to the raw scores before the softmax, this is
# effectively the same as removing these entirely.
global_attention_mask = global_attention_mask.to(dtype=self.dtype) # fp16 compatibility
global_attention_mask = (1.0 - global_attention_mask) * -10000.0
else:
global_attention_mask = None
# Local causal attention mask
batch_size, seq_length = input_shape
full_seq_length = seq_length + past_length
attention_mask = attention_mask.to(dtype=self.dtype) # fp16 compatibility
attention_mask = (1.0 - attention_mask) * -10000.0
# Prepare head mask if needed
# 1.0 in head_mask indicate we keep the head
# attention_probs has shape bsz x num_heads x N x N
# head_mask has shape n_layer x batch x num_heads x N x N
head_mask = self.get_head_mask(head_mask, self.config.num_layers)
head_mask = self.get_head_mask(head_mask, getattr(self.config, "num_layers", None) or self.config.n_layer)
if inputs_embeds is None:
if breakmodel:
input_ids = input_ids.to(primary_device)
inputs_embeds = self.wte(input_ids)
if embs is not None and not (use_cache is not None and use_cache and past_key_values is not None and len(past_key_values) > 0 and past_key_values[0] is not None):
@ -379,10 +369,14 @@ def new_forward(
inputs_embeds[:, pos:pos+emb.shape[1]] = emb
offset += emb.shape[1]
if hasattr(self, 'rotary') and self.rotary:
if getattr(self, "wpe", None) is None:
hidden_states = inputs_embeds
else:
if breakmodel:
position_ids = position_ids.to(primary_device)
position_embeds = self.wpe(position_ids)
if breakmodel:
position_embeds = position_embeds.to(primary_device)
hidden_states = inputs_embeds + position_embeds
if token_type_ids is not None:
@ -397,9 +391,8 @@ def new_forward(
all_self_attentions = () if output_attentions else None
all_hidden_states = () if output_hidden_states else None
if breakmodel:
copystream = torch.cuda.Stream(device=0,priority = -1)
if breakmodel and ram_blocks:
copystream = torch.cuda.Stream(device=primary_device, priority=-1)
for i, (block, layer_past) in enumerate(zip(self.h, past_key_values)):
@ -412,10 +405,6 @@ def new_forward(
with torch.cuda.stream(copystream):
torch.cuda.comm.broadcast(param2.data,out = [param1.data])
attn_type = self.config.attention_layers[i]
attn_mask = global_attention_mask
if output_hidden_states:
all_hidden_states = all_hidden_states + (hidden_states.cpu(),)
@ -423,8 +412,7 @@ def new_forward(
if use_cache:
logger.warning(
"`use_cache=True` is incompatible with `config.gradient_checkpointing=True`. Setting "
"`use_cache=False`..."
"`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`..."
)
use_cache = False
@ -439,15 +427,17 @@ def new_forward(
create_custom_forward(block),
hidden_states,
None,
attn_mask,
attention_mask,
head_mask[i],
)
else:
if breakmodel:
device = primary_device if i < ram_blocks else bisect.bisect_right(cumulative_gpu_blocks, i - ram_blocks)
outputs = block(
hidden_states,
layer_past=layer_past,
attention_mask=attn_mask,
head_mask=head_mask[i],
hidden_states.to(device) if breakmodel and hidden_states is not None else hidden_states,
layer_past=tuple(v.to(device) for v in layer_past if v is not None) if breakmodel and layer_past is not None and i >= ram_blocks and len(layer_past) and layer_past[0].device.index != device else layer_past,
attention_mask=attention_mask.to(device) if breakmodel and attention_mask is not None else attention_mask,
head_mask=head_mask[i].to(device) if breakmodel and head_mask[i] is not None else head_mask[i],
use_cache=use_cache,
output_attentions=output_attentions,
)
@ -466,12 +456,13 @@ def new_forward(
torch.cuda.empty_cache()
if breakmodel:
del copystream
torch.cuda.empty_cache()
if ram_blocks:
del copystream
torch.cuda.empty_cache()
hidden_states = hidden_states.to(primary_device)
hidden_states = self.ln_f(hidden_states)
if breakmodel:
hidden_states = hidden_states.to(primary_device)
hidden_states = hidden_states.view(*output_shape)
# Add last hidden state
@ -480,7 +471,6 @@ def new_forward(
if not return_dict:
return tuple(v for v in [hidden_states, presents, all_hidden_states, all_self_attentions] if v is not None)
return BaseModelOutputWithPast(
last_hidden_state=hidden_states,
past_key_values=presents,

2063
bridge.lua Normal file

File diff suppressed because it is too large Load Diff

133
colab/GPU.ipynb Normal file
View File

@ -0,0 +1,133 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "ColabKobold GPU",
"private_outputs": true,
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyM1P6rS/XmJbyV/HZRzXohF",
"include_colab_link": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/henk717/KoboldAI/blob/united/colab/GPU.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kX9y5koxa58q"
},
"source": [
"# Welcome to KoboldAI on Google Colab, GPU Edition!\n",
"KoboldAI is a powerful and easy way to use a variety of AI based text generation experiences. You can use it to write stories, blog posts, play a text adventure game, use it like a chatbot and more! In some cases it might even help you with an assignment or programming task (But always make sure the information the AI mentions is correct, it loves to make stuff up).\n",
"\n",
"For more information about KoboldAI check our our Github readme : https://github.com/KoboldAI/KoboldAI-Client/blob/main/readme.md\n",
"\n",
"For the larger AI models (That are typically more coherent) check out our [TPU edition](https://colab.research.google.com/github/KoboldAI/KoboldAI-Client/blob/main/colab/TPU.ipynb)"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ewkXkyiFP2Hq"
},
"source": [
"#@title <-- Tap this if you play on Mobile { display-mode: \"form\" }\n",
"%%html\n",
"<b>Press play on the music player to keep the tab alive, then start KoboldAI below (Uses only 13MB of data)</b><br/>\n",
"<audio src=\"https://henk.tech/colabkobold/silence.m4a\" controls>"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "lVftocpwCoYw",
"cellView": "form"
},
"source": [
"#@title <b><-- Click this to start KoboldAI</b>\n",
"#@markdown You can find a description of the models below along with instructions on how to start KoboldAI.\n",
"\n",
"Model = \"KoboldAI/GPT-Neo-2.7B-Picard\" #@param [\"KoboldAI/GPT-Neo-2.7B-Picard\", \"KoboldAI/GPT-Neo-2.7B-AID\", \"KoboldAI/GPT-Neo-2.7B-Horni-LN\", \"KoboldAI/GPT-Neo-2.7B-Horni\", \"KoboldAI/GPT-Neo-2.7B-Shinen\", \"EleutherAI/gpt-neo-2.7B\"] {allow-input: true}\n",
"Version = \"Official\" #@param [\"Official\", \"United\"] {allow-input: true}\n",
"\n",
"!nvidia-smi\n",
"from google.colab import drive\n",
"drive.mount('/content/drive/')\n",
"\n",
"!wget https://henk.tech/ckds -O - | bash /dev/stdin -m $Model -g $Version"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"# GPU Edition Model Descriptions\n",
"| Model | Size | Style | Description |\n",
"| ------------------------------------------------------------ | -------- | ---------- | ------------------------------------------------------------ |\n",
"| [GPT-Neo-2.7B-Picard](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Picard) by Mr Seeker | 2.7B GPU | Novel | Picard is a model trained for SFW Novels based on GPT-Neo-2.7B. It is focused on Novel style writing without the NSFW bias. While the name suggests a sci-fi model this model is designed for Novels of a variety of genre's. It is meant to be used in KoboldAI's regular mode. |\n",
"| [GPT-Neo-2.7B-AID](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-AID) by melastacho | 2.7B GPU | Adventure | Also know as Adventure 2.7B this is a clone of the AI Dungeon Classic model and is best known for the epic wackey adventures that AI Dungeon Classic players love. |\n",
"| [GPT-Neo-2.7B-Horni-LN](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Horni-LN) by finetune | 2.7B GPU | Novel | This model is based on GPT-Neo-2.7B-Horni and retains its NSFW knowledge, but was then further biased towards SFW novel stories. If you seek a balance between a SFW Novel model and a NSFW model this model should be a good choice. |\n",
"| [GPT-Neo-2.7B-Horni](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Horni) by finetune | 2.7B GPU | NSFW | This model is tuned on Literotica to produce a Novel style model biased towards NSFW content. Can still be used for SFW stories but will have a bias towards NSFW content. It is meant to be used in KoboldAI's regular mode. |\n",
"| [GPT-Neo-2.7B-Shinen](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Shinen) by Mr Seeker | 2.7B GPU | NSFW | Shinen is an alternative to the Horni model designed to be more explicit. If Horni is to tame for you shinen might produce better results. While it is a Novel model it is unsuitable for SFW stories due to its heavy NSFW bias. Shinen will not hold back. It is meant to be used in KoboldAI's regular mode. |\n",
"| [GPT-Neo-2.7B](https://huggingface.co/EleutherAI/gpt-neo-2.7B) by EleutherAI | 2.7B GPU | Generic | This is the base model for all the other 2.7B models, it is best used when you have a use case that we have no other models available for, such as writing blog articles or programming. It can also be a good basis for the experience of some of the softprompts if your softprompt is not about a subject the other models cover. |\n",
"\n",
"# [TPU Edition Model Descriptions](https://colab.research.google.com/github/KoboldAI/KoboldAI-Client/blob/main/colab/TPU.ipynb)\n",
"\n",
"| Model | Size | Style | Drive Space | Description |\n",
"| ------------------------------ | ------ | --------- | ----------- | ------------------------------------------------------------ |\n",
"| Skein 6B by VE_FORBDRYDERNE | 6B TPU | Hybrid | 0 GB | Skein is our flagship 6B model, it is a hybrid between a Adventure model and a Novel model. Best used with either Adventure mode or the You Bias userscript enabled. Skein has been trained on high quality Novels along with CYOA adventure stories and is not as wackey as the Adventure model. It also has tagging support. |\n",
"| Adventure 6B by VE_FORBRYDERNE | 6B TPU | Adventure | 0 GB | Adventure is a 6B model designed to mimick the behavior of AI Dungeon. It is exclusively for Adventure Mode and can take you on the epic and wackey adventures that AI Dungeon players love. It also features the many tropes of AI Dungeon as it has been trained on very similar data. It must be used in second person (You). |\n",
"| Lit 6B by Haru | 6B TPU | NSFW | 8 GB / 12 GB | Lit is a great NSFW model trained by Haru on both a large set of Literotica stories and high quality novels along with tagging support. Creating a high quality model for your NSFW stories. This model is exclusively a novel model and is best used in third person. |\n",
"| Generic 6B by EleutherAI | 6B TPU | Generic | 10 GB / 12 GB | GPT-J-6B is what all other models are based on, if you need something that has no specific bias towards any particular subject this is the model for you. Best used when the other models are not suitable for what you wish to do. Such as homework assistance, blog writing, coding and more. It needs more hand holding than other models and is more prone to undesirable formatting changes. |\n",
"| C1 6B by Haru | 6B TPU | Chatbot | 8 GB / 12 GB | C1 has been trained on various internet chatrooms, it makes the basis for an interesting chatbot model and has been optimized to be used in the Chatmode. |\n",
"\n",
"\n",
"| Style | Description |\n",
"| --------- | ------------------------------------------------------------ |\n",
"| Novel | For regular story writing, not compatible with Adventure mode or other specialty modes. |\n",
"| NSFW | Indicates that the model is strongly biased towards NSFW content and is not suitable for children, work environments or livestreaming. Most NSFW models are also Novel models in nature. |\n",
"| Adventure | These models are excellent for people willing to play KoboldAI like a Text Adventure game and are meant to be used with Adventure mode enabled. Even if you wish to use it as a Novel style model you should always have Adventure mode on and set it to story. These models typically have a strong bias towards the use of the word You and without Adventure mode enabled break the story flow and write actions on your behalf. |\n",
"| Chatbot | These models are specifically trained for chatting and are best used with the Chatmode enabled. Typically trained on either public chatrooms or private chats. |\n",
"| Hybrid | Hybrid models are a blend between different styles, for example they are trained on both Novel stories and Adventure stories. These models are great variety models that you can use for multiple different playstyles and modes, but depending on your usage you may need to enable Adventure Mode or the You bias (in userscripts). |\n",
"| Generic | Generic models are not trained towards anything specific, typically used as a basis for other tasks and models. They can do everything the other models can do, but require much more handholding to work properly. Generic models are an ideal basis for tasks that we have no specific model for, or for experiencing a softprompt in its raw form. |\n",
"\n",
"# How to start KoboldAI in 7 simple steps\n",
"Using KoboldAI on Google Colab is easy! Simply follow these steps to get started:\n",
"1. Mobile phone? Tap the play button below next to \"<--- Tap this if you play on mobile\" to reveal an audio player, play the silent audio to keep the tab alive so Google will not shut you down when your using KoboldAI. If no audio player is revealed your phone browser does not support Google Colab in the mobile view, go to your browser menu and enable Desktop mode before you continue.\n",
"2. Select the model that most describes what you would like to do, by default we have the most recommended model for people willing to try out KoboldAI selected. If you are an advanced user you can also type any GPT model name from Huggingface.co to load this up (Unlisted Models may or may not work depending on Colab's hardware limitations).\n",
"3. Click the play button next to \"<--- Click this to start KoboldAI\".\n",
"4. Allow Google Drive access, this typically happens trough a popup but sometimes Google Drive access may be requested trough the older method by asking you to click on a link and copy a code. This is normal behavior for Colab and only you will get access to your files, nothing is shared with us.\n",
"5. Now the automatic installation and Download process starts, for most models in the GPU edition expect this to take 7 minutes on average depending on the current Colab download speeds. These downloads happen trough Google's internet connection, you will not be billed by your internet provider and it will not count towards any download limits.\n",
"6. After waiting a Trycloudflare link appears, click the link to enjoy KoboldAI. If you get a 1033 error Cloudflare is not done loading, in that case keep refreshing until it goes away. (If it keeps happening after 2 minutes Cloudflare has an issue, in that case you can use Runtime -> Restart and Run All to get a new link).\n",
"7. As you play KoboldAI, keep this Colab tab open in the background and check occationally for Captcha's so they do not shut your instance down. If you do get shut down you can always download a copy of your gamesave in the Save menu inside KoboldAI. Stories are never lost as long as you keep KoboldAI open in your browser.\n",
"\n",
"Get a error message saying you do not have access to a GPU/TPU instance? Do not continue and try again later, KoboldAI will not run correctly without them."
],
"metadata": {
"id": "Lrm840I33hkC"
}
}
]
}

173
colab/TPU.ipynb Normal file
View File

@ -0,0 +1,173 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/henk717/KoboldAI/blob/united/colab/TPU.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# Welcome to KoboldAI on Google Colab, TPU Edition!\n",
"KoboldAI is a powerful and easy way to use a variety of AI based text generation experiences. You can use it to write stories, blog posts, play a text adventure game, use it like a chatbot and more! In some cases it might even help you with an assignment or programming task (But always make sure the information the AI mentions is correct, it loves to make stuff up).\n",
"\n",
"For more information about KoboldAI check our our Github readme : https://github.com/KoboldAI/KoboldAI-Client/blob/main/readme.md\n",
"\n",
"More (smaller) models are available in the **[GPU edition](https://colab.research.google.com/github/koboldai/KoboldAI-Client/blob/united/colab/GPU.ipynb)**!"
],
"metadata": {
"id": "zrLGxVCEaqZx"
}
},
{
"cell_type": "code",
"source": [
"#@title <-- Tap this if you play on Mobile { display-mode: \"form\" }\n",
"%%html\n",
"<b>Press play on the music player to keep the tab alive, then start KoboldAI below (Uses only 13MB of data)</b><br/>\n",
"<audio src=\"https://henk.tech/colabkobold/silence.m4a\" controls>"
],
"metadata": {
"id": "ZIL7itnNaw5V"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "qZmAyFFMouk9",
"cellView": "form"
},
"outputs": [],
"source": [
"#@title <b><-- Click this to start KoboldAI</b>\n",
"Model = \"Skein 6B\" #@param [\"Skein 6B\", \"Adventure 6B\", \"Lit 6B\", \"Generic 6B\", \"C1 6B\"]\n",
"Version = \"Official\" #@param [\"Official\", \"United\"] {allow-input: true}\n",
"Drive = \"Unextracted (Less Space)\" #@param [\"Unextracted (Less Space)\", \"Extracted (Faster Loading)\"]\n",
"#@markdown Extracted models take up more space but load faster the next time you use them, not all models use your Google Drive. See the Model list below for descriptions and space requirements. If your extracted model does not load the next time you try to launch KoboldAI delete the folder from your Google Drive and ensure enough space is available.\n",
"\n",
"from google.colab import drive\n",
"drive.mount('/content/drive/')\n",
"!wget https://henk.tech/ckds -O - | bash /dev/stdin -i drive\n",
"\n",
"if Model == \"Skein 6B\":\n",
" path = \"gpt-j-6b-skein-jax\"\n",
" location = \"colab\"\n",
" download = \"-a https://storage.henk.tech/KoboldAI/skein-jax.txt\"\n",
" extract = \"\"\n",
" Drive = \"Unextracted (Less Space)\"\n",
" ![[ -f /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-skein-jax.settings ]] || echo -e \"{\\n \\\"apikey\\\": \\\"\\\",\\n \\\"andepth\\\": 3,\\n \\\"temp\\\": 0.5,\\n \\\"top_p\\\": 0.9,\\n \\\"top_k\\\": 0,\\n \\\"tfs\\\": 1.0,\\n \\\"rep_pen\\\": 1.1,\\n \\\"genamt\\\": 80,\\n \\\"max_length\\\": 2048,\\n \\\"ikgen\\\": 200,\\n \\\"formatoptns\\\": {\\n \\\"frmttriminc\\\": true,\\n \\\"frmtrmblln\\\": false,\\n \\\"frmtrmspch\\\": false,\\n \\\"frmtadsnsp\\\": false\\n },\\n \\\"numseqs\\\": 1,\\n \\\"widepth\\\": 3,\\n \\\"useprompt\\\": true,\\n \\\"adventure\\\": false\\n}\" > /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-skein-jax.settings\n",
"if Model == \"Adventure 6B\":\n",
" path = \"gpt-j-6b-adventure-jax\"\n",
" location = \"colab\"\n",
" download = \"-a https://api.wandb.ai/files/ve-forbryderne/adventure/carol-data/models/gpt-j-6b-adventure-jax/aria2.txt\"\n",
" extract = \"\"\n",
" Drive = \"Unextracted (Less Space)\"\n",
" ![[ -f /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-adventure-jax.settings ]] || echo -e \"{\\n \\\"apikey\\\": \\\"\\\",\\n \\\"andepth\\\": 3,\\n \\\"temp\\\": 0.5,\\n \\\"top_p\\\": 0.9,\\n \\\"top_k\\\": 0,\\n \\\"tfs\\\": 1.0,\\n \\\"rep_pen\\\": 1.1,\\n \\\"genamt\\\": 80,\\n \\\"max_length\\\": 2048,\\n \\\"ikgen\\\": 200,\\n \\\"formatoptns\\\": {\\n \\\"frmttriminc\\\": true,\\n \\\"frmtrmblln\\\": false,\\n \\\"frmtrmspch\\\": false,\\n \\\"frmtadsnsp\\\": false\\n },\\n \\\"numseqs\\\": 1,\\n \\\"widepth\\\": 3,\\n \\\"useprompt\\\": true,\\n \\\"adventure\\\": true\\n}\" > /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-adventure-jax.settings\n",
"if Model == \"Lit 6B\":\n",
" path = \"gpt-j-6b-lit-jax\"\n",
" location = \"drive\"\n",
" download = \"-a https://storage.henk.tech/KoboldAI/aria2.php?file=gpt-j-6b-lit-jax.7z\"\n",
" extract = \"-z gpt-j-6b-lit-jax.7z\"\n",
" ![[ -f /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-lit-jax.settings ]] || echo -e \"{\\n \\\"apikey\\\": \\\"\\\",\\n \\\"andepth\\\": 3,\\n \\\"temp\\\": 0.5,\\n \\\"top_p\\\": 0.9,\\n \\\"top_k\\\": 0,\\n \\\"tfs\\\": 1.0,\\n \\\"rep_pen\\\": 1.1,\\n \\\"genamt\\\": 80,\\n \\\"max_length\\\": 2048,\\n \\\"ikgen\\\": 200,\\n \\\"formatoptns\\\": {\\n \\\"frmttriminc\\\": true,\\n \\\"frmtrmblln\\\": false,\\n \\\"frmtrmspch\\\": false,\\n \\\"frmtadsnsp\\\": false\\n },\\n \\\"numseqs\\\": 1,\\n \\\"widepth\\\": 3,\\n \\\"useprompt\\\": true,\\n \\\"adventure\\\": false\\n}\" > /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-lit-jax.settings\n",
"if Model == \"Generic 6B\":\n",
" path = \"step_383500\"\n",
" location = \"drive\"\n",
" download = \"-a https://storage.henk.tech/KoboldAI/aria2.php?file=step_383500_slim.tar.zstd\"\n",
" extract = \"-t step_383500_slim.tar.zstd\"\n",
" ![[ -f /content/drive/MyDrive/KoboldAI/settings/step_383500.settings ]] || echo -e \"{\\n \\\"apikey\\\": \\\"\\\",\\n \\\"andepth\\\": 3,\\n \\\"temp\\\": 0.5,\\n \\\"top_p\\\": 0.9,\\n \\\"top_k\\\": 0,\\n \\\"tfs\\\": 1.0,\\n \\\"rep_pen\\\": 1.1,\\n \\\"genamt\\\": 80,\\n \\\"max_length\\\": 2048,\\n \\\"ikgen\\\": 200,\\n \\\"formatoptns\\\": {\\n \\\"frmttriminc\\\": true,\\n \\\"frmtrmblln\\\": false,\\n \\\"frmtrmspch\\\": false,\\n \\\"frmtadsnsp\\\": false\\n },\\n \\\"numseqs\\\": 1,\\n \\\"widepth\\\": 3,\\n \\\"useprompt\\\": true,\\n \\\"adventure\\\": false\\n}\" > /content/drive/MyDrive/KoboldAI/settings/step_383500.settings\n",
"if Model == \"C1 6B\":\n",
" path = \"gpt-j-6b-c1-jax\"\n",
" location = \"drive\"\n",
" download = \"-a https://storage.henk.tech/KoboldAI/aria2.php?file=gpt-j-6b-c1-jax.7z\"\n",
" extract = \"-z gpt-j-6b-c1-jax.7z\"\n",
" ![[ -f /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-c1-jax.settings ]] || echo -e \"{\\n \\\"apikey\\\": \\\"\\\",\\n \\\"andepth\\\": 3,\\n \\\"temp\\\": 0.5,\\n \\\"top_p\\\": 0.9,\\n \\\"top_k\\\": 0,\\n \\\"tfs\\\": 1.0,\\n \\\"rep_pen\\\": 1.1,\\n \\\"genamt\\\": 80,\\n \\\"max_length\\\": 2048,\\n \\\"ikgen\\\": 200,\\n \\\"formatoptns\\\": {\\n \\\"frmttriminc\\\": true,\\n \\\"frmtrmblln\\\": false,\\n \\\"frmtrmspch\\\": false,\\n \\\"frmtadsnsp\\\": false\\n },\\n \\\"numseqs\\\": 1,\\n \\\"widepth\\\": 3,\\n \\\"useprompt\\\": true,\\n \\\"chatmode\\\": true\\n}\" > /content/drive/MyDrive/KoboldAI/settings/gpt-j-6b-c1-jax.settings\n",
"\n",
"if Drive == \"Unextracted (Less Space)\":\n",
" xloc = \"colab\"\n",
"if Drive == \"Extracted (Faster Loading)\":\n",
" xloc = \"drive\"\n",
"\n",
"\n",
"!wget https://henk.tech/ckds -O - | bash /dev/stdin $download -l $location $extract -p $path -m TPUMeshTransformerGPTJ -g $Version -x $xloc"
]
},
{
"cell_type": "markdown",
"source": [
"# TPU Edition Model Descriptions\n",
"\n",
"| Model | Size | Style | Drive Space | Description |\n",
"| ------------------------------ | ------ | --------- | ----------- | ------------------------------------------------------------ |\n",
"| Skein 6B by VE_FORBDRYDERNE | 6B TPU | Hybrid | 0 GB | Skein is our flagship 6B model, it is a hybrid between a Adventure model and a Novel model. Best used with either Adventure mode or the You Bias userscript enabled. Skein has been trained on high quality Novels along with CYOA adventure stories and is not as wackey as the Adventure model. It also has tagging support. |\n",
"| Adventure 6B by VE_FORBRYDERNE | 6B TPU | Adventure | 0 GB | Adventure is a 6B model designed to mimick the behavior of AI Dungeon. It is exclusively for Adventure Mode and can take you on the epic and wackey adventures that AI Dungeon players love. It also features the many tropes of AI Dungeon as it has been trained on very similar data. It must be used in second person (You). |\n",
"| Lit 6B by Haru | 6B TPU | NSFW | 8 GB / 12 GB | Lit is a great NSFW model trained by Haru on both a large set of Literotica stories and high quality novels along with tagging support. Creating a high quality model for your NSFW stories. This model is exclusively a novel model and is best used in third person. |\n",
"| Generic 6B by EleutherAI | 6B TPU | Generic | 10 GB / 12 GB | GPT-J-6B is what all other models are based on, if you need something that has no specific bias towards any particular subject this is the model for you. Best used when the other models are not suitable for what you wish to do. Such as homework assistance, blog writing, coding and more. It needs more hand holding than other models and is more prone to undesirable formatting changes. |\n",
"| C1 6B by Haru | 6B TPU | Chatbot | 8 GB / 12 GB | C1 has been trained on various internet chatrooms, it makes the basis for an interesting chatbot model and has been optimized to be used in the Chatmode. |\n",
"\n",
"\n",
"# [GPU Edition Model Descriptions](https://colab.research.google.com/github/KoboldAI/KoboldAI-Client/blob/main/colab/GPU.ipynb)\n",
"\n",
"| Model | Size | Style | Description |\n",
"| ------------------------------------------------------------ | -------- | ---------- | ------------------------------------------------------------ |\n",
"| [GPT-Neo-2.7B-Picard](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Picard) by Mr Seeker | 2.7B GPU | Novel | Picard is a model trained for SFW Novels based on GPT-Neo-2.7B. It is focused on Novel style writing without the NSFW bias. While the name suggests a sci-fi model this model is designed for Novels of a variety of genre's. It is meant to be used in KoboldAI's regular mode. |\n",
"| [GPT-Neo-2.7B-AID](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-AID) by melastacho | 2.7B GPU | Adventure | Also know as Adventure 2.7B this is a clone of the AI Dungeon Classic model and is best known for the epic wackey adventures that AI Dungeon Classic players love. |\n",
"| [GPT-Neo-2.7B-Horni-LN](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Horni-LN) by finetune | 2.7B GPU | Novel | This model is based on GPT-Neo-2.7B-Horni and retains its NSFW knowledge, but was then further biased towards SFW novel stories. If you seek a balance between a SFW Novel model and a NSFW model this model should be a good choice. |\n",
"| [GPT-Neo-2.7B-Horni](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Horni) by finetune | 2.7B GPU | NSFW | This model is tuned on Literotica to produce a Novel style model biased towards NSFW content. Can still be used for SFW stories but will have a bias towards NSFW content. It is meant to be used in KoboldAI's regular mode. |\n",
"| [GPT-Neo-2.7B-Shinen](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Shinen) by Mr Seeker | 2.7B GPU | NSFW | Shinen is an alternative to the Horni model designed to be more explicit. If Horni is to tame for you shinen might produce better results. While it is a Novel model it is unsuitable for SFW stories due to its heavy NSFW bias. Shinen will not hold back. It is meant to be used in KoboldAI's regular mode. |\n",
"| [GPT-Neo-2.7B](https://huggingface.co/EleutherAI/gpt-neo-2.7B) by EleutherAI | 2.7B GPU | Generic | This is the base model for all the other 2.7B models, it is best used when you have a use case that we have no other models available for, such as writing blog articles or programming. It can also be a good basis for the experience of some of the softprompts if your softprompt is not about a subject the other models cover. |\n",
"\n",
"| Style | Description |\n",
"| --------- | ------------------------------------------------------------ |\n",
"| Novel | For regular story writing, not compatible with Adventure mode or other specialty modes. |\n",
"| NSFW | Indicates that the model is strongly biased towards NSFW content and is not suitable for children, work environments or livestreaming. Most NSFW models are also Novel models in nature. |\n",
"| Adventure | These models are excellent for people willing to play KoboldAI like a Text Adventure game and are meant to be used with Adventure mode enabled. Even if you wish to use it as a Novel style model you should always have Adventure mode on and set it to story. These models typically have a strong bias towards the use of the word You and without Adventure mode enabled break the story flow and write actions on your behalf. |\n",
"| Chatbot | These models are specifically trained for chatting and are best used with the Chatmode enabled. Typically trained on either public chatrooms or private chats. |\n",
"| Hybrid | Hybrid models are a blend between different styles, for example they are trained on both Novel stories and Adventure stories. These models are great variety models that you can use for multiple different playstyles and modes, but depending on your usage you may need to enable Adventure Mode or the You bias (in userscripts). |\n",
"| Generic | Generic models are not trained towards anything specific, typically used as a basis for other tasks and models. They can do everything the other models can do, but require much more handholding to work properly. Generic models are an ideal basis for tasks that we have no specific model for, or for experiencing a softprompt in its raw form. |\n",
"\n",
"## How to start KoboldAI in 7 simple steps\n",
"Using KoboldAI on Google Colab is easy! Simply follow these steps to get started:\n",
"1. Mobile phone? Tap the play button below next to \"<--- Tap this if you play on mobile\" to reveal an audio player, play the silent audio to keep the tab alive so Google will not shut you down when your using KoboldAI. If no audio player is revealed your phone browser does not support Google Colab in the mobile view, go to your browser menu and enable Desktop mode before you continue.\n",
"2. Select the model that most describes what you would like to do, by default we have the most recommended model for people willing to try out KoboldAI selected.\n",
"3. Click the play button next to \"<--- Click this to start KoboldAI\".\n",
"4. Allow Google Drive access, this typically happens trough a popup but sometimes Google Drive access may be requested trough the older method by asking you to click on a link and copy a code. This is normal behavior for Colab and only you will get access to your files, nothing is shared with us.\n",
"5. Now the automatic installation and Download process starts, for most models in the TPU edition expect the loading to take between 15 and 30 minutes on average depending on the current Colab download speeds and the model you selected. These downloads happen trough Google's internet connection, you will not be billed by your internet provider and it will not count towards any download limits.\n",
"6. After waiting a Trycloudflare link appears, click the link to enjoy KoboldAI. If you get a 1033 error Cloudflare is not done loading, in that case keep refreshing until it goes away. (If it keeps happening after 2 minutes Cloudflare has an issue, in that case you can use Runtime -> Restart and Run All to get a new link).\n",
"7. As you play KoboldAI, keep this Colab tab open in the background and check occationally for Captcha's so they do not shut your instance down. If you do get shut down you can always download a copy of your gamesave in the Save menu inside KoboldAI. Stories are never lost as long as you keep KoboldAI open in your browser.\n",
"\n",
"Get a error message saying you do not have access to a GPU/TPU instance? Do not continue and try again later, KoboldAI will not run correctly without them.\n",
"\n"
],
"metadata": {
"id": "i0-9ARA3c4Fx"
}
}
],
"metadata": {
"colab": {
"name": "ColabKobold TPU",
"provenance": [],
"private_outputs": true,
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
},
"accelerator": "TPU"
},
"nbformat": 4,
"nbformat_minor": 0
}

75
colab/vscode.ipynb Normal file
View File

@ -0,0 +1,75 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "ColabKobold Code",
"provenance": [],
"authorship_tag": "ABX9TyOuIHmyxj4U9dipAib4hfIi",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "TPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/henk717/KoboldAI/blob/united/colab/vscode.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"# ColabKobold VSCode Edition\n",
"This is a special edition of ColabKobold aimed at developers, it will not start a KoboldAI instance for you to play KoboldAI and instead will launch a fully functional copy of VSCode for easy development.\n",
"\n",
"Few things of note:\n",
"1. Make sure the desired (or no) accelertor is selected on Colab, you do not want a TPU ban for not using it.\n",
"1. The Version can be replaced with your github URL and appended with -b for the branch for example \"https://github.com/henk717/koboldai -b united\" dependencies will automatically be installed from requirements.txt or requirements_mtj.txt.\n",
"1. With the args you can specify launch options for the KoboldAI Deployment Script, this way you can easily preinstall models to your development instance so you have a model to test with. To install TPU requirements specify the -m TPUMeshTransformerGPTJ argument.\n",
"1. You will need an Ngrok auth token which you can obtain here : https://dashboard.ngrok.com/get-started/your-authtoken\n",
"1. KoboldAI is installed in /content/koboldai-client opening this folder is enough to automatically get full git history and revision support. Also keep in mind that it mounts your Google Drive, be careful comitting directly from this instance.\n",
"1. With Ctrl + Shift + ` you can get a terminal to launch KoboldAI with your own parameters, launching with --colab is recommended.\n",
"\n",
"# [If you are not a developer and are looking to use KoboldAI click here](https://henk.tech/colabkobold)"
],
"metadata": {
"id": "hMRnGz42Xsy3"
}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "40B1QvI3Xv02"
},
"outputs": [],
"source": [
"#@title VSCode Server\n",
"Version = \"United\" #@param [\"Official\", \"United\"] {allow-input: true}\n",
"Args = \"-m TPUMeshTransformerGPTJ -a https://api.wandb.ai/files/ve-forbryderne/skein/files/gpt-j-6b-skein-jax/aria2.txt\" #@param {type:\"string\"}\n",
"Authtoken = \"\" #@param {type:\"string\"}\n",
"\n",
"from google.colab import drive\n",
"drive.mount('/content/drive/')\n",
"\n",
"!wget https://henk.tech/ckds -O - | bash /dev/stdin -g $Version -i only $Args\n",
"\n",
"!pip install colabcode\n",
"from colabcode import ColabCode\n",
"ColabCode(authtoken=Authtoken)"
]
}
]
}

204
colabkobold.sh Normal file
View File

@ -0,0 +1,204 @@
#!/bin/bash
# KoboldAI Easy Colab Deployment Script by Henk717
# read the options
TEMP=`getopt -o m:i:p:c:d:x:a:l:z:g:t:n:b: --long model:,init:,path:,configname:,download:,aria2:,dloc:xloc:7z:git:tar:ngrok:branch: -- "$@"`
eval set -- "$TEMP"
# extract options and their arguments into variables.
while true ; do
case "$1" in
-m|--model)
model=" --model $2" ; shift 2 ;;
-i|--init)
init=$2 ; shift 2 ;;
-p|--path)
mpath="$2" ; shift 2 ;;
-c|--configname)
configname=" --configname $2" ; shift 2 ;;
-n|--ngrok)
configname=" --ngrok" ; shift 2 ;;
-d|--download)
download="$2" ; shift 2 ;;
-a|--aria2)
aria2="$2" ; shift 2 ;;
-l|--dloc)
dloc="$2" ; shift 2 ;;
-x|--xloc)
xloc="$2" ; shift 2 ;;
-z|--7z)
z7="$2" ; shift 2 ;;
-t|--tar)
tar="$2" ; shift 2 ;;
-g|--git)
git="$2" ; shift 2 ;;
-b|--branch)
branch="$2" ; shift 2 ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
# Create the Launch function so we can run KoboldAI at different places in the script
function launch
{
#End the script if "--init only" was specified.
if [ "$init" == "only" ]; then
echo Initialization complete...
exit 0
else
cd /content/KoboldAI-Client
echo "Launching KoboldAI with the following options : python3 aiserver.py$model$kmpath$configname$ngrok --remote --override_delete --override_rename"
python3 aiserver.py$model$kmpath$configname$ngrok --colab
exit
fi
}
git_default_branch() {
(git remote show $git | grep 'HEAD branch' | cut -d' ' -f5) 2>/dev/null
}
# Don't allow people to mess up their system
if [[ ! -d "/content" ]]; then
echo You can only use this script on Google Colab
echo Use aiserver.py to play KoboldAI locally.
echo Check our Readme for Colab links if you wish to play on Colab.
exit
fi
# Redefine the download location
if [ "$dloc" == "colab" ]; then
dloc="/content"
else
dloc="/content/drive/MyDrive/KoboldAI/models"
fi
# Redefine the extraction location
if [ "$xloc" == "drive" ]; then
xloc="/content/drive/MyDrive/KoboldAI/models/"
dloc="/content"
else
xloc="/content/"
fi
# Redefine the Path to be in the relevant location
if [[ -v mpath ]];then
mpath="$xloc$mpath"
kmpath=" --path $mpath"
fi
# Create folders on Google Drive
mkdir /content/drive/MyDrive/KoboldAI/
mkdir /content/drive/MyDrive/KoboldAI/stories/
mkdir /content/drive/MyDrive/KoboldAI/models/
mkdir /content/drive/MyDrive/KoboldAI/settings/
mkdir /content/drive/MyDrive/KoboldAI/softprompts/
mkdir /content/drive/MyDrive/KoboldAI/userscripts/
if [ "$init" == "drive" ]; then
echo Google Drive folders created.
exit 0
fi
# Install and/or Update KoboldAI
if [ "$init" != "skip" ]; then
cd /content
if [ ! -z ${git+x} ]; then
if [ "$git" == "Official" ]; then
git=https://github.com/koboldai/KoboldAI-Client
fi
if [ "$git" == "United" ]; then
git=https://github.com/henk717/KoboldAI-Client
fi
if [ "$git" == "united" ]; then
git=https://github.com/henk717/KoboldAI-Client
fi
else
git=https://github.com/koboldai/KoboldAI-Client
fi
mkdir /content/KoboldAI-Client
cd /content/KoboldAI-Client
git init
git remote remove origin
git remote add origin $git
git fetch --all
if [ ! -z ${branch+x} ]; then
git checkout $branch -f
git reset --hard origin/$branch
else
git checkout $(git_default_branch) -f
git reset --hard origin/$(git_default_branch)
fi
cd /content/KoboldAI-Client
cp -rn stories/*.* /content/drive/MyDrive/KoboldAI/stories/
cp -rn userscripts/*.* /content/drive/MyDrive/KoboldAI/userscripts/
cp -rn softprompts/*.* /content/drive/MyDrive/KoboldAI/softprompts/
rm stories
rm -rf stories/
rm userscripts
rm -rf userscripts/
rm softprompts
rm -rf softprompts/
ln -s /content/drive/MyDrive/KoboldAI/stories/ stories
ln -s /content/drive/MyDrive/KoboldAI/settings/ settings
ln -s /content/drive/MyDrive/KoboldAI/softprompts/ softprompts
ln -s /content/drive/MyDrive/KoboldAI/userscripts/ userscripts
if [ "$model" == " --model TPUMeshTransformerGPTJ" ]; then
pip install -r requirements_mtj.txt
else
pip install -r requirements.txt
fi
# Make sure Colab has netbase
sudo apt install netbase -y
fi
cd /content
# Models extracted? Then we skip anything beyond this point for faster loading.
if [ -f "/content/extracted" ]; then
launch
fi
# Is the model extracted on Google Drive? Skip the download and extraction
# Only on Google Drive since it has a big impact there if we don't, and locally we have better checks in place
if [ "$xloc" == "/content/drive/MyDrive/KoboldAI/models/" ] && [[ -d $mpath ]];then
launch
fi
#Download routine for regular Downloads
if [ ! -z ${download+x} ]; then
wget -c $download -P $dloc
fi
#Download routine for Aria2c scripts
if [ ! -z ${aria2+x} ]; then
apt install aria2 -y
curl -L $aria2 | aria2c -c -i- -d$dloc --user-agent=KoboldAI --file-allocation=none
fi
#Extract the model with 7z
if [ ! -z ${z7+x} ]; then
7z x -o$xloc $dloc/$z7 -aos
touch /content/extracted
fi
#Extract the model in a ZSTD Tar file
if [ ! -z ${tar+x} ]; then
git clone https://github.com/VE-FORBRYDERNE/pv
cd pv
./configure
make
make install
cd ..
apt install zstd -y
pv $dloc/$tar | tar -I zstd -C $xloc -x
touch /content/extracted
fi
launch

View File

@ -1,15 +1,27 @@
@echo off
cd %~dp0
cd /D %~dp0
TITLE CMD for KoboldAI Runtime
SET /P M=<loader.settings
IF %M%==1 GOTO drivemap
IF %M%==2 GOTO subfolder
IF %M%==3 GOTO drivemap_B
:subfolder
SET TEMP=%~DP0MINICONDA3
SET TMP=%~DP0MINICONDA3
call miniconda3\condabin\activate
cmd /k
:drivemap
subst K: miniconda3 >nul
SET TEMP=K:\
SET TMP=K:\
call K:\python\condabin\activate
cmd /k
:drivemap_B
subst B: miniconda3 >nul
SET TEMP=B:\
SET TMP=B:\
call B:\python\condabin\activate
cmd /k

34
cores/default.lua Normal file
View File

@ -0,0 +1,34 @@
-- Default core script
-- Runs all generation modifiers and output modifiers in forward order, and
-- runs all input modifiers in reverse order
kobold, koboldcore = require("bridge")() -- This line is optional and is only for EmmyLua type annotations
---@class KoboldCoreScript
local corescript = {}
-- Run all the input modifiers from bottom to top
function corescript.inmod()
for i = #koboldcore.userscripts, 1, -1 do
local userscript = koboldcore.userscripts[i]
userscript.inmod()
end
end
-- Run all the generation modifiers from top to bottom
function corescript.genmod()
for i, userscript in ipairs(koboldcore.userscripts) do
userscript.genmod()
end
end
-- Run all the generation modifiers from top to bottom
function corescript.outmod()
for i, userscript in ipairs(koboldcore.userscripts) do
userscript.outmod()
end
end
return corescript

View File

@ -7,6 +7,7 @@ services:
network_mode: "host"
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- /etc/protocols:/etc/protocols:ro
- ../:/content/
- $HOME/.Xauthority:/home/micromamba/.Xauthority:rw
devices:

View File

@ -7,6 +7,7 @@ services:
network_mode: "host"
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
- /etc/protocols:/etc/protocols:ro
- ../:/content/
- $HOME/.Xauthority:/root/.Xauthority:rw
devices:

View File

@ -10,8 +10,13 @@ dependencies:
- cudatoolkit=11.1
- tensorflow-gpu
- python=3.8.*
- eventlet
- markdown
- bleach
- pip
- git
- pip:
- git+https://github.com/finetuneanon/transformers@gpt-neo-localattention3-rp-b
- flask-cloudflared
- flask-cloudflared
- flask-ngrok
- lupa==1.10

View File

@ -1,6 +1,5 @@
name: koboldai
channels:
- huggingface
- pytorch
- conda-forge
- defaults
@ -10,8 +9,13 @@ dependencies:
- pytorch
- python=3.8.*
- cudatoolkit=11.1
- tensorflow-gpu
- transformers
- eventlet
- markdown
- bleach
- pip
- git
- pip:
- flask-cloudflared
- flask-cloudflared
- flask-ngrok
- lupa==1.10

View File

@ -0,0 +1,21 @@
name: koboldai-ft
channels:
- conda-forge
- defaults
dependencies:
- colorama
- flask-socketio
- python=3.8.*
- eventlet
- markdown
- bleach
- pip
- git
- pip:
- --find-links https://download.pytorch.org/whl/rocm4.2/torch_stable.html
- torch
- torchvision==0.11.1
- flask-cloudflared
- git+https://github.com/finetuneanon/transformers@gpt-neo-localattention3-rp-b
- flask-ngrok
- lupa==1.10

21
environments/rocm.yml Normal file
View File

@ -0,0 +1,21 @@
name: koboldai
channels:
- conda-forge
- defaults
dependencies:
- transformers
- colorama
- flask-socketio
- python=3.8.*
- eventlet
- markdown
- bleach
- pip
- git
- pip:
- --find-links https://download.pytorch.org/whl/rocm4.2/torch_stable.html
- torch
- torchvision==0.11.1
- flask-cloudflared
- flask-ngrok
- lupa==1.10

4
extern/lualibs/base64.lua vendored Normal file
View File

@ -0,0 +1,4 @@
-- base64 1.5.3 | /base64.lua | https://github.com/iskolbin/lbase64 | License: Unlicense | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
local a={}local b=_G.bit32 and _G.bit32.extract;if not b then if _G.bit then local c,d,e=_G.bit.lshift,_G.bit.rshift,_G.bit.band;b=function(f,g,h)return e(d(f,g),c(1,h)-1)end elseif _G._VERSION=="Lua 5.1"then b=function(f,g,h)local i=0;local j=2^g;for k=0,h-1 do local l=j+j;if f%l>=j then i=i+2^k end;j=l end;return i end else b=load[[return function( v, from, width )
return ( v >> from ) & ((1 << width) - 1)
end]]()end end;function a.makeencoder(m,n,o)local p={}for q,r in pairs{[0]='A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9',m or'+',n or'/',o or'='}do p[q]=r:byte()end;return p end;function a.makedecoder(m,n,o)local s={}for q,t in pairs(a.makeencoder(m,n,o))do s[t]=q end;return s end;local u=a.makeencoder()local v=a.makedecoder()local r,w=string.char,table.concat;function a.encode(x,p,y)p=p or u;local z,A,B={},1,#x;local C=B%3;local D={}for k=1,B-C,3 do local E,F,G=x:byte(k,k+2)local f=E*0x10000+F*0x100+G;local H;if y then H=D[f]if not H then H=r(p[b(f,18,6)],p[b(f,12,6)],p[b(f,6,6)],p[b(f,0,6)])D[f]=H end else H=r(p[b(f,18,6)],p[b(f,12,6)],p[b(f,6,6)],p[b(f,0,6)])end;z[A]=H;A=A+1 end;if C==2 then local E,F=x:byte(B-1,B)local f=E*0x10000+F*0x100;z[A]=r(p[b(f,18,6)],p[b(f,12,6)],p[b(f,6,6)],p[64])elseif C==1 then local f=x:byte(B)*0x10000;z[A]=r(p[b(f,18,6)],p[b(f,12,6)],p[64],p[64])end;return w(z)end;function a.decode(I,s,y)s=s or v;local J='[^%w%+%/%=]'if s then local m,n;for t,q in pairs(s)do if q==62 then m=t elseif q==63 then n=t end end;J=('[^%%w%%%s%%%s%%=]'):format(r(m),r(n))end;I=I:gsub(J,'')local D=y and{}local z,A={},1;local B=#I;local K=I:sub(-2)=='=='and 2 or I:sub(-1)=='='and 1 or 0;for k=1,K>0 and B-4 or B,4 do local E,F,G,L=I:byte(k,k+3)local H;if y then local M=E*0x1000000+F*0x10000+G*0x100+L;H=D[M]if not H then local f=s[E]*0x40000+s[F]*0x1000+s[G]*0x40+s[L]H=r(b(f,16,8),b(f,8,8),b(f,0,8))D[M]=H end else local f=s[E]*0x40000+s[F]*0x1000+s[G]*0x40+s[L]H=r(b(f,16,8),b(f,8,8),b(f,0,8))end;z[A]=H;A=A+1 end;if K==1 then local E,F,G=I:byte(B-3,B-1)local f=s[E]*0x40000+s[F]*0x1000+s[G]*0x40;z[A]=r(b(f,16,8),b(f,8,8))elseif K==2 then local E,F=I:byte(B-3,B-2)local f=s[E]*0x40000+s[F]*0x1000;z[A]=r(b(f,16,8))end;return w(z)end;return a

6
extern/lualibs/hashings/adler32.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/adler32.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c={}local d={__metatable={},__index=c}local e=65521;c.digest_size=8;c.block_size=8;function c:new(f)if self~=c then return nil,"First argument must be self"end;local g=setmetatable({},d)g._b1=b(1)g._b2=b(0)if f~=nil then g:update(f)end;return g end;setmetatable(c,{__call=c.new})function c:copy()local g=c:new()g._b1=self._b1:copy()g._b2=self._b2:copy()return g end;function c:update(f)local h;if f==nil then f=""end;f=tostring(f)for i=1,#f do h=a.byte(f,i)self._b1=(self._b1+h)%e;self._b2=(self._b2+self._b1)%e end end;function c:digest()return(self._b2<<16|self._b1):asbytestring()end;function c:hexdigest()local j;local k={}j=self:digest()for i=1,#j do k[i]=a.format("%02X",a.byte(j,i))end;return table.concat(k)end;return c

6
extern/lualibs/hashings/blake2b.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/blake2b.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintb").u64;local c=require("nums.uintn").u8;local d={}local e={__metatable={},__index=d}d.digest_size=64;d.block_size=128;local f={b("0x6A09E667F3BCC908"),b("0xBB67AE8584CAA73B"),b("0x3C6EF372FE94F82B"),b("0xA54FF53A5F1D36F1"),b("0x510E527FADE682D1"),b("0x9B05688C2B3E6C1F"),b("0x1F83D9ABFB41BD6B"),b("0x5BE0CD19137E2179")}local g={{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},{15,11,5,9,10,16,14,7,2,13,1,3,12,8,6,4},{12,9,13,1,6,3,16,14,11,15,4,7,8,2,10,5},{8,10,4,2,14,13,12,15,3,7,6,11,5,1,16,9},{10,1,6,8,3,5,11,16,15,2,12,13,7,9,4,14},{3,13,7,11,1,12,9,4,5,14,8,6,16,15,2,10},{13,6,2,16,15,14,5,11,1,8,7,4,10,3,9,12},{14,12,8,15,13,2,4,10,6,1,16,5,9,7,3,11},{7,16,15,10,12,4,1,9,13,3,14,8,2,5,11,6},{11,3,9,5,8,7,2,6,16,12,10,15,4,13,14,1},{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},{15,11,5,9,10,16,14,7,2,13,1,3,12,8,6,4}}local function h(i,j)return i>>j|(i<<64-j)end;local function k(l,m)l._t0=l._t0+m;if l._t0<m then l._t1=l._t1+1 end end;local function n(o,p,q,r,s,t,u)r=r+s+q[g[o+1][2*p+1]]u=h(u~r,32)t=t+u;s=h(s~t,24)r=r+s+q[g[o+1][2*p+2]]u=h(u~r,16)t=t+u;s=h(s~t,63)return r,s,t,u end;local function v(o,q,w)w[1],w[5],w[9],w[13]=n(o,0,q,w[1],w[5],w[9],w[13])w[2],w[6],w[10],w[14]=n(o,1,q,w[2],w[6],w[10],w[14])w[3],w[7],w[11],w[15]=n(o,2,q,w[3],w[7],w[11],w[15])w[4],w[8],w[12],w[16]=n(o,3,q,w[4],w[8],w[12],w[16])w[1],w[6],w[11],w[16]=n(o,4,q,w[1],w[6],w[11],w[16])w[2],w[7],w[12],w[13]=n(o,5,q,w[2],w[7],w[12],w[13])w[3],w[8],w[9],w[14]=n(o,6,q,w[3],w[8],w[9],w[14])w[4],w[5],w[10],w[15]=n(o,7,q,w[4],w[5],w[10],w[15])end;local function x(l)local w={}local q={}if#l._data<128 then return end;for y=1,128,8 do q[#q+1]=b(a.byte(l._data,y+7))<<56|(b(a.byte(l._data,y+6))<<48)|(b(a.byte(l._data,y+5))<<40)|(b(a.byte(l._data,y+4))<<32)|(b(a.byte(l._data,y+3))<<24)|(b(a.byte(l._data,y+2))<<16)|(b(a.byte(l._data,y+1))<<8)|b(a.byte(l._data,y))end;l._data=l._data:sub(129,#l._data)for p=1,8 do w[p]=l._h[p]:copy()end;w[9]=f[1]:copy()w[10]=f[2]:copy()w[11]=f[3]:copy()w[12]=f[4]:copy()w[13]=l._t0~f[5]w[14]=l._t1~f[6]if l._last then w[15]=b("0xFFFFFFFFFFFFFFFF")~f[7]else w[15]=f[7]:copy()end;w[16]=f[8]:copy()v(0,q,w)v(1,q,w)v(2,q,w)v(3,q,w)v(4,q,w)v(5,q,w)v(6,q,w)v(7,q,w)v(8,q,w)v(9,q,w)v(10,q,w)v(11,q,w)for p=1,8 do l._h[p]=l._h[p]~w[p]~w[p+8]end end;function d:new(z)if self~=d then return nil,"First argument must be self"end;local A=setmetatable({},e)A._h={}for p=1,8 do A._h[p]=f[p]:copy()end;A._h[1]=A._h[1]~16842816;A._last=false;A._t0=b(0)A._t1=b(0)A._data=""if z~=nil then A:update(z)end;return A end;setmetatable(d,{__call=d.new})function d:copy()local A=d()for p=1,8 do A._h[p]=self._h[p]:copy()end;A._last=self._last;A._t0=self._t0:copy()A._t1=self._t1:copy()A._data=self._data;return A end;function d:update(z)if z==nil then z=""end;z=tostring(z)self._data=self._data..z;while#self._data>128 do k(self,128)x(self)end end;function d:digest()local B;local C={}local y;B=self:copy()k(B,#B._data)B._last=true;B._data=B._data..a.rep(a.char(0),128-#B._data)x(B)for p=1,#B._h do C[p]=B._h[p]:swape():asbytestring()end;return table.concat(C)end;function d:hexdigest()local D;local C={}D=self:digest()for p=1,#D do C[p]=a.format("%02X",a.byte(D,p))end;return table.concat(C)end;return d

6
extern/lualibs/hashings/blake2s.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/blake2s.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c=require("nums.uintn").u8;local d={}local e={__metatable={},__index=d}d.digest_size=32;d.block_size=64;local f={b(0x6A09E667),b(0xBB67AE85),b(0x3C6EF372),b(0xA54FF53A),b(0x510E527F),b(0x9B05688C),b(0x1F83D9AB),b(0x5BE0CD19)}local g={{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},{15,11,5,9,10,16,14,7,2,13,1,3,12,8,6,4},{12,9,13,1,6,3,16,14,11,15,4,7,8,2,10,5},{8,10,4,2,14,13,12,15,3,7,6,11,5,1,16,9},{10,1,6,8,3,5,11,16,15,2,12,13,7,9,4,14},{3,13,7,11,1,12,9,4,5,14,8,6,16,15,2,10},{13,6,2,16,15,14,5,11,1,8,7,4,10,3,9,12},{14,12,8,15,13,2,4,10,6,1,16,5,9,7,3,11},{7,16,15,10,12,4,1,9,13,3,14,8,2,5,11,6},{11,3,9,5,8,7,2,6,16,12,10,15,4,13,14,1}}local function h(i,j)return i>>j|(i<<32-j)end;local function k(l,m)l._t0=l._t0+m;if l._t0<m then l._t1=l._t1+1 end end;local function n(o,p,q,r,s,t,u)r=r+s+q[g[o+1][2*p+1]]u=h(u~r,16)t=t+u;s=h(s~t,12)r=r+s+q[g[o+1][2*p+2]]u=h(u~r,8)t=t+u;s=h(s~t,7)return r,s,t,u end;local function v(o,q,w)w[1],w[5],w[9],w[13]=n(o,0,q,w[1],w[5],w[9],w[13])w[2],w[6],w[10],w[14]=n(o,1,q,w[2],w[6],w[10],w[14])w[3],w[7],w[11],w[15]=n(o,2,q,w[3],w[7],w[11],w[15])w[4],w[8],w[12],w[16]=n(o,3,q,w[4],w[8],w[12],w[16])w[1],w[6],w[11],w[16]=n(o,4,q,w[1],w[6],w[11],w[16])w[2],w[7],w[12],w[13]=n(o,5,q,w[2],w[7],w[12],w[13])w[3],w[8],w[9],w[14]=n(o,6,q,w[3],w[8],w[9],w[14])w[4],w[5],w[10],w[15]=n(o,7,q,w[4],w[5],w[10],w[15])end;local function x(l)local w={}local q={}if#l._data<64 then return end;for y=1,64,4 do q[#q+1]=b(a.byte(l._data,y+3)<<24|(a.byte(l._data,y+2)<<16)|(a.byte(l._data,y+1)<<8)|a.byte(l._data,y))end;l._data=l._data:sub(65,#l._data)for p=1,8 do w[p]=l._h[p]:copy()end;w[9]=f[1]:copy()w[10]=f[2]:copy()w[11]=f[3]:copy()w[12]=f[4]:copy()w[13]=l._t0~f[5]w[14]=l._t1~f[6]if l._last then w[15]=b(0xFFFFFFFF)~f[7]else w[15]=f[7]:copy()end;w[16]=f[8]:copy()v(0,q,w)v(1,q,w)v(2,q,w)v(3,q,w)v(4,q,w)v(5,q,w)v(6,q,w)v(7,q,w)v(8,q,w)v(9,q,w)for p=1,8 do l._h[p]=l._h[p]~w[p]~w[p+8]end end;function d:new(z)if self~=d then return nil,"First argument must be self"end;local A=setmetatable({},e)A._h={}for p=1,8 do A._h[p]=f[p]:copy()end;A._h[1]=A._h[1]~16842784;A._last=false;A._t0=b(0)A._t1=b(0)A._data=""if z~=nil then A:update(z)end;return A end;setmetatable(d,{__call=d.new})function d:copy()local A=d()for p=1,8 do A._h[p]=self._h[p]:copy()end;A._last=self._last;A._t0=self._t0:copy()A._t1=self._t1:copy()A._data=self._data;return A end;function d:update(z)if z==nil then z=""end;z=tostring(z)self._data=self._data..z;while#self._data>64 do k(self,64)x(self)end end;function d:digest()local B;local C={}B=self:copy()k(B,#B._data)B._last=true;B._data=B._data..a.rep(a.char(0),64-#B._data)x(B)for p=1,#B._h do C[p]=B._h[p]:swape():asbytestring()end;return table.concat(C)end;function d:hexdigest()local D;local C={}D=self:digest()for p=1,#D do C[p]=a.format("%02X",a.byte(D,p))end;return table.concat(C)end;return d

6
extern/lualibs/hashings/crc32.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/crc32.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c={}local d={__metatable={},__index=c}c.digest_size=8;c.block_size=8;local function e(f)end;function c:new(g)if self~=c then return nil,"First argument must be self"end;local h=setmetatable({},d)h._crc=b(0xFFFFFFFF)if g~=nil then h:update(g)end;return h end;setmetatable(c,{__call=c.new})function c:copy()local h=c:new()h._crc=self._crc:copy()return h end;function c:update(g)local i;local j;if g==nil then g=""end;g=tostring(g)for k=1,#g do i=a.byte(g,k)self._crc=self._crc~i;for l=1,8 do j=self._crc&1*-1;self._crc=self._crc>>1~(0xEDB88320&j)end end end;function c:digest()return~self._crc:asbytestring()end;function c:hexdigest()local m;local n={}m=self:digest()for k=1,#m do n[k]=a.format("%02X",a.byte(m,k))end;return table.concat(n)end;return c

6
extern/lualibs/hashings/hmac.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/hmac.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b={}local c={__metatable={},__index=b}function b:new(d,e,f)local g;local h={}local i={}if self~=b then return nil,"First argument must be self"end;local j=setmetatable({},c)j._hm=d;if#e>d.block_size then g=d(e)e=g:digest()end;for k=1,#e do h[#h+1]=a.byte(e,k)end;for k=#e+1,d.block_size do h[#h+1]=0 end;j._opad={}for k=1,#h do i[k]=a.char(h[k]~0x36)j._opad[k]=a.char(h[k]~0x5C)end;i=table.concat(i)j._opad=table.concat(j._opad)j._hash=j._hm(i)if f~=nil then j._hash:update(f)end;return j end;setmetatable(b,{__call=b.new})function b:copy()local j=setmetatable({},c)j._hm=self._hm;j._hash=self._hash:copy()j._opad=self._opad;return j end;function b:update(f)self._hash:update(f)end;function b:digest()local l;local m;local g;l=self:copy()m=l._hash:digest()g=l._hm(l._opad)g:update(m)return g:digest()end;function b:hexdigest()local n;local o={}n=self:digest()for k=1,#n do o[k]=a.format("%02X",a.byte(n,k))end;return table.concat(o)end;return b

6
extern/lualibs/hashings/init.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/init.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={}a.adler32=require("hashings.adler32")a.blake2b=require("hashings.blake2b")a.blake2s=require("hashings.blake2s")a.crc32=require("hashings.crc32")a.md5=require("hashings.md5")a.ripemd160=require("hashings.ripemd160")a.sha1=require("hashings.sha1")a.sha256=require("hashings.sha256")a.sha3_256=require("hashings.sha3_256")a.sha3_512=require("hashings.sha3_512")a.sha512=require("hashings.sha512")a.whirlpool=require("hashings.whirlpool")a.hmac=require("hashings.hmac")a.pbkdf2=require("hashings.pbkdf2")a.algorithms={"adler32","blake2b","blake2s","crc32","md5","ripemd160","sha1","sha256","sha3_256","sha3_512","sha512","whirlpool"}local b={adler32=a.adler32,blake2b=a.blake2b,blake2s=a.blake2s,crc32=a.crc32,md5=a.md5,ripemd160=a.ripemd160,sha1=a.sha1,sha256=a.sha256,sha3_256=a.sha3_256,sha3_512=a.sha3_512,sha512=a.sha512,whirlpool=a.whirlpool}function a:new(c,d)local e;e=b[c]if e==nil then return nil end;return e:new(d)end;setmetatable(a,{__call=a.new})return a

6
extern/lualibs/hashings/keccak.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/keccak.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintb").u64;local c={}local d={__metatable={},__index=c}local e={{5,2},{1,3},{2,4},{3,5},{4,1}}local f={11,8,12,18,19,4,6,17,9,22,25,5,16,24,20,14,13,3,21,15,23,10,7,2}local g={1,3,6,10,15,21,28,36,45,55,2,14,27,41,56,8,25,43,62,18,39,61,20,44}local h={{2,3},{3,4},{4,5},{5,1},{1,2},{7,8},{8,9},{9,10},{10,6},{6,7},{12,13},{13,14},{14,15},{15,11},{11,12},{17,18},{18,19},{19,20},{20,16},{16,17},{22,23},{23,24},{24,25},{25,21},{21,22}}local i={b("0x1"),b("0x8082"),b("0x800000000000808A"),b("0x8000000080008000"),b("0x808B"),b("0x80000001"),b("0x8000000080008081"),b("0x8000000000008009"),b("0x8A"),b("0x88"),b("0x80008009"),b("0x8000000A"),b("0x8000808B"),b("0x800000000000008B"),b("0x8000000000008089"),b("0x8000000000008003"),b("0x8000000000008002"),b("0x8000000000000080"),b("0x800A"),b("0x800000008000000A"),b("0x8000000080008081"),b("0x8000000000008080"),b("0x80000001"),b("0x8000000080008008")}local function j(k,l)return k<<l|(k>>64-l)end;local function m(n)local o;local p;for q=1,n._block_size,8 do o=q//8+1;p=q//8*8+1;n._s[o]=n._s[o]~(b(a.byte(n._data,p))|(b(a.byte(n._data,p+1))<<8)|(b(a.byte(n._data,p+2))<<16)|(b(a.byte(n._data,p+3))<<24)|(b(a.byte(n._data,p+4))<<32)|(b(a.byte(n._data,p+5))<<40)|(b(a.byte(n._data,p+6))<<48)|(b(a.byte(n._data,p+7))<<56))end;n._data=n._data:sub(n._block_size+1)end;local function r(s)local t={}local u;for q=1,5 do t[q]=s[q]~s[q+5]~s[q+10]~s[q+15]~s[q+20]end;for q=1,5 do u=t[e[q][1]]~j(t[e[q][2]],1)for o=q,25,5 do s[o]=s[o]~u end end end;local function v(s)local w;local u;u=s[2]:copy()for q=1,24 do w=s[f[q]]s[f[q]]=j(u,g[q])u=w end end;local function x(s)local t={}for q=1,25 do t[q]=s[q]:copy()end;for q=1,25 do s[q]=s[q]~(~t[h[q][1]]&t[h[q][2]])end end;local function y(s,l)s[1]=s[1]~i[l]end;function c:new(z,A,B)if self~=c then return nil,"First argument must be self"end;if z>200 then return nil,"Invalid block size"end;local C=setmetatable({},d)C._block_size=z;C._digest_size=A;C._data=""C._s={}for q=1,25 do C._s[q]=b(0)end;if B~=nil then C:update(B)end;return C end;setmetatable(c,{__call=c.new})function c:copy()local C=setmetatable({},d)C._block_size=self._block_size;C._digest_size=self._digest_size;C._data=self._data;C._s={}for q=1,25 do C._s[q]=self._s[q]:copy()end;return C end;function c:update(B)if B==nil then B=""end;B=tostring(B)self._data=self._data..B;while#self._data>=self._block_size do m(self)for q=1,24 do r(self._s)v(self._s)x(self._s)y(self._s,q)end end end;function c:digest()local D;local B;local E={}D=self:copy()if#D._data==D._block_size-1 then B=a.char(0x06|0x80)else B=a.char(0x06)..a.rep(a.char(0),D._block_size-#D._data-2)..a.char(0x80)end;D:update(B)for q=1,D._digest_size//8 do E[q]=D._s[q]:swape():asbytestring()end;return table.concat(E)end;function c:hexdigest()local F;local E={}F=self:digest()for q=1,#F do E[q]=a.format("%02X",a.byte(F,q))end;return table.concat(E)end;return c

6
extern/lualibs/hashings/md5.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/md5.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c={}local d={__metatable={},__index=c}c.digest_size=16;c.block_size=64;local function e(f,g,h)return f&g|(~f&h)end;local function i(f,g,h)return f&h|(g&~h)end;local function j(f,g,h)return f~g~h end;local function k(f,g,h)return g~(f|~h)end;local function l(m,n)return m<<n|(m>>32-n)end;local function o(p,q,r,s,t,m,u,v)return l(q+p(r,s,t)+m+v,u)+r end;local function w(x,y,z,A,f)local q=x;local r=y;local s=z;local t=A;q=o(e,q,r,s,t,f[1],7,0xD76AA478)t=o(e,t,q,r,s,f[2],12,0xE8C7B756)s=o(e,s,t,q,r,f[3],17,0x242070DB)r=o(e,r,s,t,q,f[4],22,0xC1BDCEEE)q=o(e,q,r,s,t,f[5],7,0xF57C0FAF)t=o(e,t,q,r,s,f[6],12,0x4787C62A)s=o(e,s,t,q,r,f[7],17,0xA8304613)r=o(e,r,s,t,q,f[8],22,0xFD469501)q=o(e,q,r,s,t,f[9],7,0x698098D8)t=o(e,t,q,r,s,f[10],12,0x8B44F7AF)s=o(e,s,t,q,r,f[11],17,0xFFFF5BB1)r=o(e,r,s,t,q,f[12],22,0x895CD7BE)q=o(e,q,r,s,t,f[13],7,0x6B901122)t=o(e,t,q,r,s,f[14],12,0xFD987193)s=o(e,s,t,q,r,f[15],17,0xA679438E)r=o(e,r,s,t,q,f[16],22,0x49B40821)q=o(i,q,r,s,t,f[2],5,0xF61E2562)t=o(i,t,q,r,s,f[7],9,0xC040B340)s=o(i,s,t,q,r,f[12],14,0x265E5A51)r=o(i,r,s,t,q,f[1],20,0xE9B6C7AA)q=o(i,q,r,s,t,f[6],5,0xD62F105D)t=o(i,t,q,r,s,f[11],9,0x2441453)s=o(i,s,t,q,r,f[16],14,0xD8A1E681)r=o(i,r,s,t,q,f[5],20,0xE7D3FBC8)q=o(i,q,r,s,t,f[10],5,0x21E1CDE6)t=o(i,t,q,r,s,f[15],9,0xC33707D6)s=o(i,s,t,q,r,f[4],14,0xF4D50D87)r=o(i,r,s,t,q,f[9],20,0x455A14ED)q=o(i,q,r,s,t,f[14],5,0xA9E3E905)t=o(i,t,q,r,s,f[3],9,0xFCEFA3F8)s=o(i,s,t,q,r,f[8],14,0x676F02D9)r=o(i,r,s,t,q,f[13],20,0x8D2A4C8A)q=o(j,q,r,s,t,f[6],4,0xFFFA3942)t=o(j,t,q,r,s,f[9],11,0x8771F681)s=o(j,s,t,q,r,f[12],16,0x6D9D6122)r=o(j,r,s,t,q,f[15],23,0xFDE5380C)q=o(j,q,r,s,t,f[2],4,0xA4BEEA44)t=o(j,t,q,r,s,f[5],11,0x4BDECFA9)s=o(j,s,t,q,r,f[8],16,0xF6BB4B60)r=o(j,r,s,t,q,f[11],23,0xBEBFBC70)q=o(j,q,r,s,t,f[14],4,0x289B7EC6)t=o(j,t,q,r,s,f[1],11,0xEAA127FA)s=o(j,s,t,q,r,f[4],16,0xD4EF3085)r=o(j,r,s,t,q,f[7],23,0x4881D05)q=o(j,q,r,s,t,f[10],4,0xD9D4D039)t=o(j,t,q,r,s,f[13],11,0xE6DB99E5)s=o(j,s,t,q,r,f[16],16,0x1FA27CF8)r=o(j,r,s,t,q,f[3],23,0xC4AC5665)q=o(k,q,r,s,t,f[1],6,0xF4292244)t=o(k,t,q,r,s,f[8],10,0x432AFF97)s=o(k,s,t,q,r,f[15],15,0xAB9423A7)r=o(k,r,s,t,q,f[6],21,0xFC93A039)q=o(k,q,r,s,t,f[13],6,0x655B59C3)t=o(k,t,q,r,s,f[4],10,0x8F0CCC92)s=o(k,s,t,q,r,f[11],15,0xFFEFF47D)r=o(k,r,s,t,q,f[2],21,0x85845DD1)q=o(k,q,r,s,t,f[9],6,0x6FA87E4F)t=o(k,t,q,r,s,f[16],10,0xFE2CE6E0)s=o(k,s,t,q,r,f[7],15,0xA3014314)r=o(k,r,s,t,q,f[14],21,0x4E0811A1)q=o(k,q,r,s,t,f[5],6,0xF7537E82)t=o(k,t,q,r,s,f[12],10,0xBD3AF235)s=o(k,s,t,q,r,f[3],15,0x2AD7D2BB)r=o(k,r,s,t,q,f[10],21,0xEB86D391)return q+x,r+y,s+z,t+A end;function c:new(B)if self~=c then return nil,"First argument must be self"end;local C=setmetatable({},d)C._A=b(0x67452301)C._B=b(0xEFCDAB89)C._C=b(0x98BADCFE)C._D=b(0x10325476)C._len=0;C._data=""if B~=nil then C:update(B)end;return C end;setmetatable(c,{__call=c.new})function c:copy()local C=c()C._A=self._A:copy()C._B=self._B:copy()C._C=self._C:copy()C._D=self._D:copy()C._data=self._data;C._len=self._len;return C end;function c:update(B)local f;if B==nil then B=""end;B=tostring(B)self._len=self._len+#B;self._data=self._data..B;while#self._data>=64 do f={}for D=1,64,4 do f[#f+1]=a.byte(self._data,D+3)<<24|(a.byte(self._data,D+2)<<16)|(a.byte(self._data,D+1)<<8)|a.byte(self._data,D)end;self._data=self._data:sub(65,#self._data)self._A,self._B,self._C,self._D=w(self._A,self._B,self._C,self._D,f)end end;function c:digest()local E;local B;local F=0;local G=0;E=self:copy()G=E._len%64;if G<56 then G=56-G else G=120-G end;F=E._len*8;B=a.char(1<<7)..a.rep(a.char(0),G-1)..a.char(F&0xFF)..a.char(F>>8&0xFF)..a.char(F>>16&0xFF)..a.char(F>>24&0xFF)..a.char(F>>32&0xFF)..a.char(F>>40&0xFF)..a.char(F>>48&0xFF)..a.char(F>>56&0xFF)E:update(B)return E._A:swape():asbytestring()..E._B:swape():asbytestring()..E._C:swape():asbytestring()..E._D:swape():asbytestring()end;function c:hexdigest()local H;local I={}H=self:digest()for J=1,#H do I[J]=a.format("%02X",a.byte(H,J))end;return table.concat(I)end;return c

6
extern/lualibs/hashings/pbkdf2.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/pbkdf2.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c=require("hashings.hmac")local d={}local function e(f,g)local h={}local i={}local j={}for k=1,#f do h[#h+1]=a.byte(f,k)end;for k=1,#g do i[#i+1]=a.byte(g,k)end;for k=1,#h do j[#j+1]=a.char(h[k]~i[k])end;return table.concat(j)end;local function l(m)local n={}for k=1,#m do n[k]=a.format("%02X",a.byte(m,k))end;return table.concat(n)end;function d:pbkdf2(o,p,q,r)local s;local t;s=c(o,p,q..b(1):asbytestring()):digest()t=s;for k=2,r do s=c(o,p,s):digest()t=e(t,s)end;return l(t)end;setmetatable(d,{__call=d.pbkdf2})return d

6
extern/lualibs/hashings/ripemd160.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/hashings/sha1.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/sha1.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c={}local d={__metatable={},__index=c}c.digest_size=20;c.block_size=64;local function e(f,g)return f<<g|(f>>32-g)end;function c:new(h)if self~=c then return nil,"First argument must be self"end;local i=setmetatable({},d)i._H0=b(0x67452301)i._H1=b(0xEFCDAB89)i._H2=b(0x98BADCFE)i._H3=b(0x10325476)i._H4=b(0xC3D2E1F0)i._len=0;i._data=""if h~=nil then i:update(h)end;return i end;setmetatable(c,{__call=c.new})function c:copy()local i=c:new()i._H0=self._H0:copy()i._H1=self._H1:copy()i._H2=self._H2:copy()i._H3=self._H3:copy()i._H4=self._H4:copy()i._data=self._data;i._len=self._len;return i end;function c:update(h)local j=b(0x5A827999)local k=b(0x6ED9EBA1)local l=b(0x8F1BBCDC)local m=b(0xCA62C1D6)local n;local o;local p;local q;local r;local s;local t;if h==nil then h=""end;h=tostring(h)self._len=self._len+#h;self._data=self._data..h;while#self._data>=64 do n={}for u=1,64,4 do local v=#n+1;n[v]=b(a.byte(self._data,u))<<24;n[v]=n[v]|(b(a.byte(self._data,u+1))<<16)n[v]=n[v]|(b(a.byte(self._data,u+2))<<8)n[v]=n[v]|b(a.byte(self._data,u+3))end;for u=17,80 do n[u]=e(n[u-3]~n[u-8]~n[u-14]~n[u-16],1)end;p=self._H0;q=self._H1;r=self._H2;s=self._H3;t=self._H4;for u=1,20 do o=e(p,5)+q&r|(~q&s)+t+n[u]+j;t=s;s=r;r=e(q,30)q=p;p=o end;for u=21,40 do o=e(p,5)+q~r~s+t+n[u]+k;t=s;s=r;r=e(q,30)q=p;p=o end;for u=41,60 do o=e(p,5)+q&r|(q&s)|(r&s)+t+n[u]+l;t=s;s=r;r=e(q,30)q=p;p=o end;for u=61,80 do o=e(p,5)+q~r~s+t+n[u]+m;t=s;s=r;r=e(q,30)q=p;p=o end;self._H0=self._H0+p;self._H1=self._H1+q;self._H2=self._H2+r;self._H3=self._H3+s;self._H4=self._H4+t;self._data=self._data:sub(65,#self._data)end end;function c:digest()local w;local h;local x=0;local y=0;w=self:copy()y=w._len%64;if y<56 then y=56-y else y=120-y end;x=w._len*8;h=a.char(1<<7)..a.rep(a.char(0),y-1)..a.char(x>>56&0xFF)..a.char(x>>48&0xFF)..a.char(x>>40&0xFF)..a.char(x>>32&0xFF)..a.char(x>>24&0xFF)..a.char(x>>16&0xFF)..a.char(x>>8&0xFF)..a.char(x&0xFF)w:update(h)return w._H0:asbytestring()..w._H1:asbytestring()..w._H2:asbytestring()..w._H3:asbytestring()..w._H4:asbytestring()end;function c:hexdigest()local z;local A={}z=self:digest()for u=1,#z do A[u]=a.format("%02X",a.byte(z,u))end;return table.concat(A)end;return c

6
extern/lualibs/hashings/sha256.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/sha256.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintn").u32;local c={}local d={__metatable={},__index=c}c.digest_size=32;c.block_size=64;local e={b(0x428A2F98),b(0x71374491),b(0xB5C0FBCF),b(0xE9B5DBA5),b(0x3956C25B),b(0x59F111F1),b(0x923F82A4),b(0xAB1C5ED5),b(0xD807AA98),b(0x12835B01),b(0x243185BE),b(0x550C7DC3),b(0x72BE5D74),b(0x80DEB1FE),b(0x9BDC06A7),b(0xC19BF174),b(0xE49B69C1),b(0xEFBE4786),b(0x0FC19DC6),b(0x240CA1CC),b(0x2DE92C6F),b(0x4A7484AA),b(0x5CB0A9DC),b(0x76F988DA),b(0x983E5152),b(0xA831C66D),b(0xB00327C8),b(0xBF597FC7),b(0xC6E00BF3),b(0xD5A79147),b(0x06CA6351),b(0x14292967),b(0x27B70A85),b(0x2E1B2138),b(0x4D2C6DFC),b(0x53380D13),b(0x650A7354),b(0x766A0ABB),b(0x81C2C92E),b(0x92722C85),b(0xA2BFE8A1),b(0xA81A664B),b(0xC24B8B70),b(0xC76C51A3),b(0xD192E819),b(0xD6990624),b(0xF40E3585),b(0x106AA070),b(0x19A4C116),b(0x1E376C08),b(0x2748774C),b(0x34B0BCB5),b(0x391C0CB3),b(0x4ED8AA4A),b(0x5B9CCA4F),b(0x682E6FF3),b(0x748F82EE),b(0x78A5636F),b(0x84C87814),b(0x8CC70208),b(0x90BEFFFA),b(0xA4506CEB),b(0xBEF9A3F7),b(0xC67178F2)}local function f(g,h)return g>>h|(g<<32-h)end;local function i(g,j,k)return g&j~(~g&k)end;local function l(g,j,k)return g&j~(g&k)~(j&k)end;local function m(g)return f(g,2)~f(g,13)~f(g,22)end;local function n(g)return f(g,6)~f(g,11)~f(g,25)end;local function o(g)return f(g,7)~f(g,18)~(g>>3)end;local function p(g)return f(g,17)~f(g,19)~(g>>10)end;function c:new(q)if self~=c then return nil,"First argument must be self"end;local r=setmetatable({},d)r._H0=b(0x6A09E667)r._H1=b(0xBB67AE85)r._H2=b(0x3C6EF372)r._H3=b(0xA54FF53A)r._H4=b(0x510E527F)r._H5=b(0x9B05688C)r._H6=b(0x1F83D9AB)r._H7=b(0x5BE0CD19)r._len=0;r._data=""if q~=nil then r:update(q)end;return r end;setmetatable(c,{__call=c.new})function c:copy()local r=c:new()r._H0=self._H0:copy()r._H1=self._H1:copy()r._H2=self._H2:copy()r._H3=self._H3:copy()r._H4=self._H4:copy()r._H5=self._H5:copy()r._H6=self._H6:copy()r._H7=self._H7:copy()r._data=self._data;r._len=self._len;return r end;function c:update(q)local s;local t;local u;local v;local w;local x;local y;local z;local A;local B;local C;if q==nil then q=""end;q=tostring(q)self._len=self._len+#q;self._data=self._data..q;while#self._data>=64 do s={}for D=1,64,4 do local E=#s+1;s[E]=b(a.byte(self._data,D))<<24;s[E]=s[E]|(b(a.byte(self._data,D+1))<<16)s[E]=s[E]|(b(a.byte(self._data,D+2))<<8)s[E]=s[E]|b(a.byte(self._data,D+3))end;self._data=self._data:sub(65,#self._data)for D=17,64 do s[D]=p(s[D-2])+s[D-7]+o(s[D-15])+s[D-16]end;v=self._H0;w=self._H1;x=self._H2;y=self._H3;z=self._H4;A=self._H5;B=self._H6;C=self._H7;for D=1,64 do t=C+n(z)+i(z,A,B)+e[D]+s[D]u=m(v)+l(v,w,x)C=B;B=A;A=z;z=y+t;y=x;x=w;w=v;v=t+u end;self._H0=self._H0+v;self._H1=self._H1+w;self._H2=self._H2+x;self._H3=self._H3+y;self._H4=self._H4+z;self._H5=self._H5+A;self._H6=self._H6+B;self._H7=self._H7+C end end;function c:digest()local F;local q;local G=0;local H=0;F=self:copy()H=F._len%64;if H<56 then H=56-H else H=120-H end;G=F._len*8;q=a.char(1<<7)..a.rep(a.char(0),H-1)..a.char(G>>56&0xFF)..a.char(G>>48&0xFF)..a.char(G>>40&0xFF)..a.char(G>>32&0xFF)..a.char(G>>24&0xFF)..a.char(G>>16&0xFF)..a.char(G>>8&0xFF)..a.char(G&0xFF)F:update(q)return F._H0:asbytestring()..F._H1:asbytestring()..F._H2:asbytestring()..F._H3:asbytestring()..F._H4:asbytestring()..F._H5:asbytestring()..F._H6:asbytestring()..F._H7:asbytestring()end;function c:hexdigest()local C;local I={}C=self:digest()for D=1,#C do I[D]=a.format("%02X",a.byte(C,D))end;return table.concat(I)end;return c

6
extern/lualibs/hashings/sha3_256.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/sha3_256.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("hashings.keccak")local b={}local c={__metatable={},__index=b}b.digest_size=32;b.block_size=136;function b:new(d)return a:new(b.block_size,b.digest_size,d)end;setmetatable(b,{__call=b.new})return b

6
extern/lualibs/hashings/sha3_512.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/sha3_512.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("hashings.keccak")local b={}local c={__metatable={},__index=b}b.digest_size=64;b.block_size=72;function b:new(d)return a:new(b.block_size,b.digest_size,d)end;setmetatable(b,{__call=b.new})return b

6
extern/lualibs/hashings/sha512.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-hashings @89879fe79b6f3dc495c607494126ec9c3912b8e9 | /hashings/sha512.lua | https://github.com/user-none/lua-hashings | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("string")local b=require("nums.uintb").u64;local c={}local d={__metatable={},__index=c}c.digest_size=64;c.block_size=128;local e={b("0x428A2F98D728AE22"),b("0x7137449123EF65CD"),b("0xB5C0FBCFEC4D3B2F"),b("0xE9B5DBA58189DBBC"),b("0x3956C25BF348B538"),b("0x59F111F1B605D019"),b("0x923F82A4AF194F9B"),b("0xAB1C5ED5DA6D8118"),b("0xD807AA98A3030242"),b("0x12835B0145706FBE"),b("0x243185BE4EE4B28C"),b("0x550C7DC3D5FFB4E2"),b("0x72BE5D74F27B896F"),b("0x80DEB1FE3B1696B1"),b("0x9BDC06A725C71235"),b("0xC19BF174CF692694"),b("0xE49B69C19EF14AD2"),b("0xEFBE4786384F25E3"),b("0x0FC19DC68B8CD5B5"),b("0x240CA1CC77AC9C65"),b("0x2DE92C6F592B0275"),b("0x4A7484AA6EA6E483"),b("0x5CB0A9DCBD41FBD4"),b("0x76F988DA831153B5"),b("0x983E5152EE66DFAB"),b("0xA831C66D2DB43210"),b("0xB00327C898FB213F"),b("0xBF597FC7BEEF0EE4"),b("0xC6E00BF33DA88FC2"),b("0xD5A79147930AA725"),b("0x06CA6351E003826F"),b("0x142929670A0E6E70"),b("0x27B70A8546D22FFC"),b("0x2E1B21385C26C926"),b("0x4D2C6DFC5AC42AED"),b("0x53380D139D95B3DF"),b("0x650A73548BAF63DE"),b("0x766A0ABB3C77B2A8"),b("0x81C2C92E47EDAEE6"),b("0x92722C851482353B"),b("0xA2BFE8A14CF10364"),b("0xA81A664BBC423001"),b("0xC24B8B70D0F89791"),b("0xC76C51A30654BE30"),b("0xD192E819D6EF5218"),b("0xD69906245565A910"),b("0xF40E35855771202A"),b("0x106AA07032BBD1B8"),b("0x19A4C116B8D2D0C8"),b("0x1E376C085141AB53"),b("0x2748774CDF8EEB99"),b("0x34B0BCB5E19B48A8"),b("0x391C0CB3C5C95A63"),b("0x4ED8AA4AE3418ACB"),b("0x5B9CCA4F7763E373"),b("0x682E6FF3D6B2B8A3"),b("0x748F82EE5DEFB2FC"),b("0x78A5636F43172F60"),b("0x84C87814A1F0AB72"),b("0x8CC702081A6439EC"),b("0x90BEFFFA23631E28"),b("0xA4506CEBDE82BDE9"),b("0xBEF9A3F7B2C67915"),b("0xC67178F2E372532B"),b("0xCA273ECEEA26619C"),b("0xD186B8C721C0C207"),b("0xEADA7DD6CDE0EB1E"),b("0xF57D4F7FEE6ED178"),b("0x06F067AA72176FBA"),b("0x0A637DC5A2C898A6"),b("0x113F9804BEF90DAE"),b("0x1B710B35131C471B"),b("0x28DB77F523047D84"),b("0x32CAAB7B40C72493"),b("0x3C9EBE0A15C9BEBC"),b("0x431D67C49C100D4C"),b("0x4CC5D4BECB3E42B6"),b("0x597F299CFC657E2A"),b("0x5FCB6FAB3AD6FAEC"),b("0x6C44198C4A475817")}local function f(g,h)return g>>h|(g<<64-h)end;local function i(g,j,k)return g&j~(~g&k)end;local function l(g,j,k)return g&j~(g&k)~(j&k)end;local function m(g)return f(g,28)~f(g,34)~f(g,39)end;local function n(g)return f(g,14)~f(g,18)~f(g,41)end;local function o(g)return f(g,1)~f(g,8)~(g>>7)end;local function p(g)return f(g,19)~f(g,61)~(g>>6)end;function c:new(q)if self~=c then return nil,"First argument must be self"end;local r=setmetatable({},d)r._H0=b(0x6A09E667F3BCC908)r._H1=b(0xBB67AE8584CAA73B)r._H2=b(0x3C6EF372FE94F82B)r._H3=b(0xA54FF53A5F1D36F1)r._H4=b(0x510E527FADE682D1)r._H5=b(0x9B05688C2B3E6C1F)r._H6=b(0x1F83D9ABFB41BD6B)r._H7=b(0x5BE0CD19137E2179)r._len=0;r._data=""if q~=nil then r:update(q)end;return r end;setmetatable(c,{__call=c.new})function c:copy()local r=c:new()r._H0=self._H0:copy()r._H1=self._H1:copy()r._H2=self._H2:copy()r._H3=self._H3:copy()r._H4=self._H4:copy()r._H5=self._H5:copy()r._H6=self._H6:copy()r._H7=self._H7:copy()r._data=self._data;r._len=self._len;return r end;function c:update(q)local s;local t;local u;local v;local w;local x;local y;local z;local A;local B;local C;if q==nil then q=""end;q=tostring(q)self._len=self._len+#q;self._data=self._data..q;while#self._data>=128 do s={}for D=1,128,8 do local E=#s+1;s[E]=b(a.byte(self._data,D))<<56;s[E]=s[E]|(b(a.byte(self._data,D+1))<<48)s[E]=s[E]|(b(a.byte(self._data,D+2))<<40)s[E]=s[E]|(b(a.byte(self._data,D+3))<<32)s[E]=s[E]|(b(a.byte(self._data,D+4))<<24)s[E]=s[E]|(b(a.byte(self._data,D+5))<<16)s[E]=s[E]|(b(a.byte(self._data,D+6))<<8)s[E]=s[E]|b(a.byte(self._data,D+7))end;self._data=self._data:sub(129,#self._data)for D=17,80 do s[D]=p(s[D-2])+s[D-7]+o(s[D-15])+s[D-16]end;v=self._H0;w=self._H1;x=self._H2;y=self._H3;z=self._H4;A=self._H5;B=self._H6;C=self._H7;for D=1,80 do t=C+n(z)+i(z,A,B)+e[D]+s[D]u=m(v)+l(v,w,x)C=B;B=A;A=z;z=y+t;y=x;x=w;w=v;v=t+u end;self._H0=self._H0+v;self._H1=self._H1+w;self._H2=self._H2+x;self._H3=self._H3+y;self._H4=self._H4+z;self._H5=self._H5+A;self._H6=self._H6+B;self._H7=self._H7+C end end;function c:digest()local F;local q;local G=0;local H=0;F=self:copy()H=F._len%128;if H<112 then H=112-H else H=240-H end;G=F._len*8;q=a.char(1<<7)..a.rep(a.char(0),H-1)..a.char(G>>120&0xFF)..a.char(G>>112&0xFF)..a.char(G>>104&0xFF)..a.char(G>>96&0xFF)..a.char(G>>88&0xFF)..a.char(G>>80&0xFF)..a.char(G>>72&0xFF)..a.char(G>>64&0xFF)..a.char(G>>56&0xFF)..a.char(G>>48&0xFF)..a.char(G>>40&0xFF)..a.char(G>>32&0xFF)..a.char(G>>24&0xFF)..a.char(G>>16&0xFF)..a.char(G>>8&0xFF)..a.char(G&0xFF)F:update(q)return F._H0:asbytestring()..F._H1:asbytestring()..F._H2:asbytestring()..F._H3:asbytestring()..F._H4:asbytestring()..F._H5:asbytestring()..F._H6:asbytestring()..F._H7:asbytestring()end;function c:hexdigest()local C;local I={}C=self:digest()for D=1,#C do I[D]=a.format("%02X",a.byte(C,D))end;return table.concat(I)end;return c

6
extern/lualibs/hashings/whirlpool.lua vendored Normal file

File diff suppressed because one or more lines are too long

25
extern/lualibs/inspect.lua vendored Normal file
View File

@ -0,0 +1,25 @@
-- inspect 3.1.2 | /inspect.lua | https://github.com/kikito/inspect.lua | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
local a={_VERSION='inspect.lua 3.1.0',_URL='http://github.com/kikito/inspect.lua',_DESCRIPTION='human-readable representations of tables',_LICENSE=[[
MIT LICENSE
Copyright (c) 2013 Enrique García Cota
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]}local tostring=tostring;a.KEY=setmetatable({},{__tostring=function()return'inspect.KEY'end})a.METATABLE=setmetatable({},{__tostring=function()return'inspect.METATABLE'end})local function b(c)return next,c,nil end;local function d(e)if e:match('"')and not e:match("'")then return"'"..e.."'"end;return'"'..e:gsub('"','\\"')..'"'end;local f={["\a"]="\\a",["\b"]="\\b",["\f"]="\\f",["\n"]="\\n",["\r"]="\\r",["\t"]="\\t",["\v"]="\\v",["\127"]="\\127"}local g={["\127"]="\127"}for h=0,31 do local i=string.char(h)if not f[i]then f[i]="\\"..h;g[i]=string.format("\\%03d",h)end end;local function j(e)return e:gsub("\\","\\\\"):gsub("(%c)%f[0-9]",g):gsub("%c",f)end;local function k(e)return type(e)=='string'and e:match("^[_%a][_%a%d]*$")end;local function l(m,n)return type(m)=='number'and 1<=m and m<=n and math.floor(m)==m end;local o={['number']=1,['boolean']=2,['string']=3,['table']=4,['function']=5,['userdata']=6,['thread']=7}local function p(q,r)local s,t=type(q),type(r)if s==t and(s=='string'or s=='number')then return q<r end;local u,v=o[s],o[t]if u and v then return o[s]<o[t]elseif u then return true elseif v then return false end;return s<t end;local function w(c)local x=1;local y=rawget(c,x)while y~=nil do x=x+1;y=rawget(c,x)end;return x-1 end;local function z(c)local A,B={},0;local n=w(c)for m,C in b(c)do if not l(m,n)then B=B+1;A[B]=m end end;table.sort(A,p)return A,B,n end;local function D(c,E)E=E or{}if type(c)=='table'then if not E[c]then E[c]=1;for m,y in b(c)do D(m,E)D(y,E)end;D(getmetatable(c),E)else E[c]=E[c]+1 end end;return E end;local F=function(G)local H,x={},#G;for h=1,x do H[h]=G[h]end;return H,x end;local function I(J,...)local A={...}local K,x=F(J)for h=1,#A do K[x+h]=A[h]end;return K end;local function L(M,N,J,O)if N==nil then return nil end;if O[N]then return O[N]end;local P=M(N,J)if type(P)=='table'then local Q={}O[N]=Q;local R;for m,y in b(P)do R=L(M,m,I(J,m,a.KEY),O)if R~=nil then Q[R]=L(M,y,I(J,R),O)end end;local S=L(M,getmetatable(P),I(J,a.METATABLE),O)if type(S)~='table'then S=nil end;setmetatable(Q,S)P=Q end;return P end;local T={}local U={__index=T}function T:puts(...)local V={...}local W=self.buffer;local x=#W;for h=1,#V do x=x+1;W[x]=V[h]end end;function T:down(X)self.level=self.level+1;X()self.level=self.level-1 end;function T:tabify()self:puts(self.newline,string.rep(self.indent,self.level))end;function T:alreadyVisited(y)return self.ids[y]~=nil end;function T:getId(y)local Y=self.ids[y]if not Y then local Z=type(y)Y=(self.maxIds[Z]or 0)+1;self.maxIds[Z]=Y;self.ids[y]=Y end;return tostring(Y)end;function T:putKey(m)if k(m)then return self:puts(m)end;self:puts("[")self:putValue(m)self:puts("]")end;function T:putTable(c)if c==a.KEY or c==a.METATABLE then self:puts(tostring(c))elseif self:alreadyVisited(c)then self:puts('<table ',self:getId(c),'>')elseif self.level>=self.depth then self:puts('{...}')else if self.tableAppearances[c]>1 then self:puts('<',self:getId(c),'>')end;local _,a0,n=z(c)local S=getmetatable(c)self:puts('{')self:down(function()local a1=0;for h=1,n do if a1>0 then self:puts(',')end;self:puts(' ')self:putValue(c[h])a1=a1+1 end;for h=1,a0 do local m=_[h]if a1>0 then self:puts(',')end;self:tabify()self:putKey(m)self:puts(' = ')self:putValue(c[m])a1=a1+1 end;if type(S)=='table'then if a1>0 then self:puts(',')end;self:tabify()self:puts('<metatable> = ')self:putValue(S)end end)if a0>0 or type(S)=='table'then self:tabify()elseif n>0 then self:puts(' ')end;self:puts('}')end end;function T:putValue(y)local Z=type(y)if Z=='string'then self:puts(d(j(y)))elseif Z=='number'or Z=='boolean'or Z=='nil'or Z=='cdata'or Z=='ctype'then self:puts(tostring(y))elseif Z=='table'then self:putTable(y)else self:puts('<',Z,' ',self:getId(y),'>')end end;function a.inspect(a2,a3)a3=a3 or{}local a4=a3.depth or math.huge;local a5=a3.newline or'\n'local a6=a3.indent or' 'local M=a3.process;if M then a2=L(M,a2,{},{})end;local a7=setmetatable({depth=a4,level=0,buffer={},ids={},maxIds={},newline=a5,indent=a6,tableAppearances=D(a2)},U)a7:putValue(a2)return table.concat(a7.buffer)end;setmetatable(a,{__call=function(C,...)return a.inspect(...)end})return a

6
extern/lualibs/json.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- json.lua @dbf4b2dd2eb7c23be2773c89eb059dadd6436f94 | /json.lua | https://github.com/rxi/json.lua | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2020 rxi
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={_version="0.1.2"}local b;local c={["\\"]="\\",["\""]="\"",["\b"]="b",["\f"]="f",["\n"]="n",["\r"]="r",["\t"]="t"}local d={["/"]="/"}for e,f in pairs(c)do d[f]=e end;local function g(h)return"\\"..(c[h]or string.format("u%04x",h:byte()))end;local function i(j)return"null"end;local function k(j,l)local m={}l=l or{}if l[j]then error("circular reference")end;l[j]=true;if rawget(j,1)~=nil or next(j)==nil then local n=0;for e in pairs(j)do if type(e)~="number"then error("invalid table: mixed or invalid key types")end;n=n+1 end;if n~=#j then error("invalid table: sparse array")end;for o,f in ipairs(j)do table.insert(m,b(f,l))end;l[j]=nil;return"["..table.concat(m,",").."]"else for e,f in pairs(j)do if type(e)~="string"then error("invalid table: mixed or invalid key types")end;table.insert(m,b(e,l)..":"..b(f,l))end;l[j]=nil;return"{"..table.concat(m,",").."}"end end;local function p(j)return'"'..j:gsub('[%z\1-\31\\"]',g)..'"'end;local function q(j)if j~=j or j<=-math.huge or j>=math.huge then error("unexpected number value '"..tostring(j).."'")end;return string.format("%.14g",j)end;local r={["nil"]=i,["table"]=k,["string"]=p,["number"]=q,["boolean"]=tostring}b=function(j,l)local s=type(j)local t=r[s]if t then return t(j,l)end;error("unexpected type '"..s.."'")end;function a.encode(j)return b(j)end;local u;local function v(...)local m={}for o=1,select("#",...)do m[select(o,...)]=true end;return m end;local w=v(" ","\t","\r","\n")local x=v(" ","\t","\r","\n","]","}",",")local y=v("\\","/",'"',"b","f","n","r","t","u")local z=v("true","false","null")local A={["true"]=true,["false"]=false,["null"]=nil}local function B(C,D,E,F)for o=D,#C do if E[C:sub(o,o)]~=F then return o end end;return#C+1 end;local function G(C,D,H)local I=1;local J=1;for o=1,D-1 do J=J+1;if C:sub(o,o)=="\n"then I=I+1;J=1 end end;error(string.format("%s at line %d col %d",H,I,J))end;local function K(n)local t=math.floor;if n<=0x7f then return string.char(n)elseif n<=0x7ff then return string.char(t(n/64)+192,n%64+128)elseif n<=0xffff then return string.char(t(n/4096)+224,t(n%4096/64)+128,n%64+128)elseif n<=0x10ffff then return string.char(t(n/262144)+240,t(n%262144/4096)+128,t(n%4096/64)+128,n%64+128)end;error(string.format("invalid unicode codepoint '%x'",n))end;local function L(M)local N=tonumber(M:sub(1,4),16)local O=tonumber(M:sub(7,10),16)if O then return K((N-0xd800)*0x400+O-0xdc00+0x10000)else return K(N)end end;local function P(C,o)local m=""local Q=o+1;local e=Q;while Q<=#C do local R=C:byte(Q)if R<32 then G(C,Q,"control character in string")elseif R==92 then m=m..C:sub(e,Q-1)Q=Q+1;local h=C:sub(Q,Q)if h=="u"then local S=C:match("^[dD][89aAbB]%x%x\\u%x%x%x%x",Q+1)or C:match("^%x%x%x%x",Q+1)or G(C,Q-1,"invalid unicode escape in string")m=m..L(S)Q=Q+#S else if not y[h]then G(C,Q-1,"invalid escape char '"..h.."' in string")end;m=m..d[h]end;e=Q+1 elseif R==34 then m=m..C:sub(e,Q-1)return m,Q+1 end;Q=Q+1 end;G(C,o,"expected closing quote for string")end;local function T(C,o)local R=B(C,o,x)local M=C:sub(o,R-1)local n=tonumber(M)if not n then G(C,o,"invalid number '"..M.."'")end;return n,R end;local function U(C,o)local R=B(C,o,x)local V=C:sub(o,R-1)if not z[V]then G(C,o,"invalid literal '"..V.."'")end;return A[V],R end;local function W(C,o)local m={}local n=1;o=o+1;while 1 do local R;o=B(C,o,w,true)if C:sub(o,o)=="]"then o=o+1;break end;R,o=u(C,o)m[n]=R;n=n+1;o=B(C,o,w,true)local X=C:sub(o,o)o=o+1;if X=="]"then break end;if X~=","then G(C,o,"expected ']' or ','")end end;return m,o end;local function Y(C,o)local m={}o=o+1;while 1 do local Z,j;o=B(C,o,w,true)if C:sub(o,o)=="}"then o=o+1;break end;if C:sub(o,o)~='"'then G(C,o,"expected string for key")end;Z,o=u(C,o)o=B(C,o,w,true)if C:sub(o,o)~=":"then G(C,o,"expected ':' after key")end;o=B(C,o+1,w,true)j,o=u(C,o)m[Z]=j;o=B(C,o,w,true)local X=C:sub(o,o)o=o+1;if X=="}"then break end;if X~=","then G(C,o,"expected '}' or ','")end end;return m,o end;local _={['"']=P,["0"]=T,["1"]=T,["2"]=T,["3"]=T,["4"]=T,["5"]=T,["6"]=T,["7"]=T,["8"]=T,["9"]=T,["-"]=T,["t"]=U,["f"]=U,["n"]=U,["["]=W,["{"]=Y}u=function(C,D)local X=C:sub(D,D)local t=_[X]if t then return t(C,D)end;G(C,D,"unexpected character '"..X.."'")end;function a.decode(C)if type(C)~="string"then error("expected argument of type string, got "..type(C))end;local m,D=u(C,B(C,1,w,true))D=B(C,D,w,true)if D<=#C then G(C,D,"trailing garbage")end;return m end;return a

1
extern/lualibs/lpeg.lua vendored Normal file
View File

@ -0,0 +1 @@
return require("lulpeg")

138
extern/lualibs/lulpeg.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/moses.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/mt19937ar.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- mt19937ar-lua @9e110f2d1c8a981c1d4ffccb93e25aef9e8b5f17 | /mt19937ar.lua | https://github.com/davebollinger/mt19937ar-lua | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 David Bollinger (davebollinger at gmail dot com)
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=math.floor;local function b(c,d)local e=a(c%65536)local f=a(c/65536)%65536;local g=a(d%65536)local h=a(d/65536)%65536;local i=e*g;local j=e*h;local k=f*g;local l=j+k;return a((l*65536+i)%4294967296)end;local function m(c,d)local n,o=0,1;for p=0,31 do local q=c%2;local r=d%2;if q>0 and r>0 then n=n+o end;if q>0 then c=c-1 end;if r>0 then d=d-1 end;c=c/2;d=d/2;o=o*2 end;return n end;local function s(c,d)local n,o=0,1;for p=0,31 do local q=c%2;local r=d%2;if q>0 or r>0 then n=n+o end;if q>0 then c=c-1 end;if r>0 then d=d-1 end;c=c/2;d=d/2;o=o*2 end;return n end;local function t(c,d)local n,o=0,1;for p=0,31 do local q=c%2;local r=d%2;if q~=r then n=n+o end;if q>0 then c=c-1 end;if r>0 then d=d-1 end;c=c/2;d=d/2;o=o*2 end;return n end;local u=function(v)return a(v/2)end;local w=function(v)return a(v/1073741824)end;local x=function(v)return a(v/2048)end;local y=function(v)return v*128 end;local z=function(v)return v*32768 end;local A=function(v)return a(v/262144)end;local B=function(v)return v%2 end;local C=624;local D=397;local E=0x9908B0DF;local F=0x80000000;local G=0x7FFFFFFF;local H={}function H.new()local I={}local J={}local K=C+1;function I:init_genrand(L)J[0]=m(L,0xFFFFFFFF)for p=1,C-1 do J[p]=b(1812433253,t(J[p-1],w(J[p-1])))+p;J[p]=m(J[p],0xFFFFFFFF)end;K=C end;function I:init_by_array(M,N)self:init_genrand(19650218)if not N then N=#M end;local p,O,P=1,0,C>N and C or N;while P>0 do J[p]=t(J[p],b(t(J[p-1],w(J[p-1])),1664525))+M[O+1]+O;J[p]=m(J[p],0xFFFFFFFF)p,O=p+1,O+1;if p>=C then J[0]=J[C-1]p=1 end;if O>=N then O=0 end;P=P-1 end;for P=C-1,1,-1 do J[p]=t(J[p],b(t(J[p-1],w(J[p-1])),1566083941))-p;J[p]=m(J[p],0xFFFFFFFF)p=p+1;if p>=C then J[0]=J[C-1]p=1 end end;J[0]=0x80000000 end;function I:genrand_int32()local v;if K>=C then if K==C+1 then self:init_genrand(5489)end;for Q=0,C-D-1 do v=s(m(J[Q],F),m(J[Q+1],G))J[Q]=t(J[Q+D],t(u(v),B(v)*E))Q=Q+1 end;for Q=C-D,C-2 do v=s(m(J[Q],F),m(J[Q+1],G))J[Q]=t(J[Q+D-C],t(u(v),B(v)*E))Q=Q+1 end;v=s(m(J[C-1],F),m(J[0],G))J[C-1]=t(J[D-1],t(u(v),B(v)*E))K=0 end;v=J[K]K=K+1;v=t(v,x(v))v=t(v,m(y(v),0x9D2C5680))v=t(v,m(z(v),0xEFC60000))v=t(v,A(v))return v end;function I:genrand_int31()return a(self:genrand_int32()/2)end;function I:genrand_real1()return self:genrand_int32()*1.0/4294967295.0 end;function I:genrand_real2()return self:genrand_int32()*1.0/4294967296.0 end;function I:genrand_real3()return(self:genrand_int32()+0.5)*1.0/4294967296.0 end;function I:genrand_res53()local c=a(self:genrand_int32()/32)local d=a(self:genrand_int32()/64)return(c*67108864.0+d)*1.0/9007199254740992.0 end;I.randomseed=I.init_genrand;function I:random(R,S)if not R then return self:genrand_real2()else if not S then return self:genrand_int32()%R+1 else return R+self:genrand_int32()%(S-R+1)end end end;function I:getState()local n={}n.mti=K;n.mt={}for p=0,C-1 do n.mt[p]=J[p]end;return n end;function I:setState(L)if L==nil then return end;if type(L.mti)=="number"then K=a(L.mti)end;if type(L.mt)=="table"then for p=0,C-1 do if type(L.mt[p])=="number"then J[p]=a(L.mt[p])end end end end;function I:createValidationOutput()local T="mt19937ar.lua.out"local U=io.open(T,"wb")self:init_by_array({291,564,837,1110})U:write("1000 outputs of genrand_int32()\n")for p=0,999 do U:write(string.format("%10.0f ",self:genrand_int32()))if p%5==4 then U:write("\n")end end;U:write("\n1000 outputs of genrand_real2()\n")for p=0,999 do U:write(string.format("%10.8f ",self:genrand_real2()))if p%5==4 then U:write("\n")end end;U:close()end;return I end;return H

6
extern/lualibs/nums/bn.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/nums/init.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-nums @fef161a940aaafdbb8d9c75fe073b8bb43152474 | /nums/init.lua | https://github.com/user-none/lua-nums | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={}a.bn=require("nums.bn")a.uintb=require("nums.uintb")a.uintn=require("nums.uintn")return a

6
extern/lualibs/nums/uintb.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-nums @fef161a940aaafdbb8d9c75fe073b8bb43152474 | /nums/uintb.lua | https://github.com/user-none/lua-nums | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require("nums.bn")local b={}local c={}local function d(e,f)local g=false;if not b.isuint(e)then e,f=f,e;g=true end;return e:copy(),a(f),g end;local function h(i)if i._bn==i._max then i._bn:set(0)elseif i._bn<0 or i._bn>i._max then i._bn=i._bn%i._max end end;c.__index=b;c.__add=function(e,f)local j;e,f,j=d(e,f)if j then e._bn=f+e._bn else e._bn=e._bn+f end;h(e)return e end;c.__sub=function(e,f)local j;e,f,j=d(e,f)if j then e._bn=f-e._bn else e._bn=e._bn-f end;h(e)return e end;c.__mul=function(e,f)e,f=d(e,f)e._bn=e._bn*f;h(e)return e end;c.__div=function(e,f)return e//f end;c.__mod=function(e,f)local j;e,f,j=d(e,f)if j then e._bn=f%e._bn else e._bn=e._bn%f end;h(e)return e end;c.__pow=function(e,f)local j;e,f,j=d(e,f)if j then e._bn=f^e._bn else e._bn=e._bn^f end;h(e)return e end;c.__unm=function(e)e=e:copy()e._bn=-e._bn;h(e)return e end;c.__idiv=function(e,f)local j;e,f,j=d(e,f)if j and f==0 then e._val=0;return e end;if j then e._bn=f//e._bn else e._bn=e._bn//f end;h(e)return e end;c.__band=function(e,f)e,f=d(e,f)e._bn=e._bn&f;h(e)return e end;c.__bor=function(e,f)e,f=d(e,f)e._bn=e._bn|f;h(e)return e end;c.__bxor=function(e,f)e,f=d(e,f)e._bn=e._bn~f;h(e)return e end;c.__bnot=function(e)e=e:copy()e._bn=~e._bn;h(e)return e end;c.__shl=function(e,f)local j;e,f,j=d(e,f)if j then e._bn=f<<e._bn else e._bn=e._bn<<f end;h(e)return e end;c.__shr=function(e,f)local j;e,f,j=d(e,f)if j then e._bn=f>>e._bn else e._bn=e._bn>>f end;h(e)return e end;c.__concat=function(e,f)if b.isuint(e)and b.isuint(f)then return e._bn..f._bn elseif b.isuint(e)and not b.isuint(f)then return e._bn..f end;return e..f._bn end;c.__len=function(e)return e._bits end;c.__eq=function(e,f)e,f=d(e,f)return e._bn==f end;c.__lt=function(e,f)local j;e,f,j=d(e,f)if j then return e._bn>f end;return e._bn<f end;c.__le=function(e,f)if e<f or e==f then return true end;return false end;c.__tostring=function(e)return tostring(e._bn)end;function b:new(k,l)local i=setmetatable({},c)if self~=b then return nil,"first argument must be self"end;if k==nil then return nil,"bits required"end;if b.isuint(k)then i._bits=k._bits;i._max=k._max;if l~=nil then i._bn=a(l)else i._bn=a(k._bn)end else i._bits=k;i._max=a(1)<<i._bits;if l~=nil then i._bn=a(l)else i._bn=a()end end;h(i)return i end;function b.isuint(m)if type(m)=="table"and getmetatable(m)==c then return true end;return false end;function b.u8(l)return b:new(8,l)end;function b.u16(l)return b:new(16,l)end;function b.u32(l)return b:new(32,l)end;function b.u64(l)return b:new(64,l)end;function b.u128(l)return b:new(128,l)end;function b.u256(l)return b:new(256,l)end;function b.u512(l)return b:new(512,l)end;function b:copy()return b:new(self._bits,self._bn)end;function b:set(l)if b.isuint(l)then self._bn=l._val else self._bn:set(l)end;h(self)end;function b:swape()local n;local l=a()local m;n=self:asbytearray()for o=1,#n//2 do m=n[o]n[o]=n[#n-o+1]n[#n-o+1]=m end;m={}for o=#n,1,-1 do m[#m+1]=n[o]end;for o=1,#m do l=l|(a(m[o])<<o*8-8)end;return b:new(self._bits,l)end;function b:asnumber()return self._bn:asnumber()end;function b:asbn()return self._bn:copy()end;function b:ashex(p)return self._bn:ashex(p)end;function b:asbytearray()local q;q=self._bn:asbytearray()for o=1,self._bits//8-#q do table.insert(q,1,0)end;return q end;function b:asbytestring()local f;f=self:asbytearray()for o=1,#f do f[o]=string.char(f[o])end;return table.concat(f)end;return b

6
extern/lualibs/nums/uintn.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Lua-nums @fef161a940aaafdbb8d9c75fe073b8bb43152474 | /nums/uintn.lua | https://github.com/user-none/lua-nums | License: MIT License | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (c) 2016 John Schember
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={}local b={}local function c(d,e)local f=false;if not a.isuint(d)then d,e=e,d;f=true end;if a.isuint(e)then e=e._val else e=tonumber(e)end;return d:copy(),e,f end;local function g(h)if h._val==h._max then h._val=0 elseif h._val<0 or h._val>h._max then h._val=h._val%h._max end end;b.__index=a;b.__add=function(d,e)local i;d,e,i=c(d,e)if i then d._val=e+d._val else d._val=d._val+e end;g(d)return d end;b.__sub=function(d,e)local i;d,e,i=c(d,e)if i then d._val=e-d._val else d._val=d._val-e end;g(d)return d end;b.__mul=function(d,e)d,e=c(d,e)d._val=d._val*e;g(d)return d end;b.__div=function(d,e)return d//e end;b.__mod=function(d,e)local i;d,e,i=c(d,e)if i then d._val=e%d._val else d._val=d._val%e end;g(d)return d end;b.__pow=function(d,e)local i;d,e,i=c(d,e)if i then d._val=e^d._val else d._val=d._val^e end;g(d)return d end;b.__unm=function(d)d=d:copy()d._val=-d._val;g(d)return d end;b.__idiv=function(d,e)local i;d,e,i=c(d,e)if i and e==0 then d._val=0;return d end;if i then d._val=e//d._val else d._val=d._val//e end;g(d)return d end;b.__band=function(d,e)d,e=c(d,e)d._val=d._val&e;g(d)return d end;b.__bor=function(d,e)d,e=c(d,e)d._val=d._val|e;g(d)return d end;b.__bxor=function(d,e)d,e=c(d,e)d._val=d._val~e;g(d)return d end;b.__bnot=function(d)d=d:copy()d._val=~d._val;g(d)return d end;b.__shl=function(d,e)local i;d,e,i=c(d,e)if i then d._val=e<<d._val else d._val=d._val<<e end;g(d)return d end;b.__shr=function(d,e)local i;d,e,i=c(d,e)if i then d._val=e>>d._val else d._val=d._val>>e end;g(d)return d end;b.__concat=function(d,e)if a.isuint(d)and a.isuint(e)then return d._val..e._val elseif a.isuint(d)and not a.isuint(e)then return d._val..e end;return d..e._val end;b.__len=function(d)return d._bits end;b.__eq=function(d,e)d,e=c(d,e)return d._val==e end;b.__lt=function(d,e)local i;d,e,i=c(d,e)if i then return d._val>e end;return d._val<e end;b.__le=function(d,e)if d<e or d==e then return true end;return false end;b.__tostring=function(d)return tostring(d._val)end;local function j(k,l)local h=setmetatable({},b)h._bits=k;h._max=1<<h._bits;if l==nil then l=0 end;if a.isuint(l)then h._val=l._val else h._val=tonumber(l)end;g(h)return h end;function a.isuint(m)if type(m)=="table"and getmetatable(m)==b then return true end;return false end;function a.u8(n)return j(8,n)end;function a.u16(n)return j(16,n)end;function a.u32(n)return j(32,n)end;function a:copy()return j(self._bits,self._val)end;function a:set(l)if a.isuint(l)then self._val=l._val else self._val=tonumber(l)end;g(self)end;function a:swape()local n;local l=0;local m;n=self:asbytearray()for o=1,#n//2 do m=n[o]n[o]=n[#n-o+1]n[#n-o+1]=m end;m={}for o=#n,1,-1 do m[#m+1]=n[o]end;for o=1,#m do l=l|(m[o]<<o*8-8)end;return j(self._bits,l)end;function a:asnumber()return self._val end;function a:ashex(p)local q="%"if p~=nil then q=q.."0"..tostring(p)end;q=q.."X"return q:format(self._val)end;function a:asbytearray()local m={}for o=self._bits-8,0,-8 do m[#m+1]=self._val>>o&0xFF end;return m end;function a:asbytestring()local e;e=self:asbytearray()for o=1,#e do e[o]=string.char(e[o])end;return table.concat(e)end;return a

6
extern/lualibs/pegex.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/Date.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/List.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/List.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a,b,c,d=table.insert,table.remove,table.concat,table.sort;local setmetatable,getmetatable,type,tostring,string=setmetatable,getmetatable,type,tostring,string;local e=require'pl.tablex'local f,g,h,i,j,k=e.filter,e.imap,e.imap2,e.reduce,e.transform,e.removevalues;local l=e.sub;local m=require'pl.utils'local n=require'pl.class'local o,p,q,r=m.array_tostring,m.split,m.assert_arg,m.function_arg;local s=e._normalize_slice;local t=m.stdmt.MultiMap;local u=m.stdmt.List;local v;n(nil,nil,u)local function w(x,y)local z=u;if y then z=getmetatable(y)end;return setmetatable(x,z)end;local function A(x)return type(x)=='table'and not getmetatable(x)and#x>0 end;function u._create(B)if A(B)then return B end end;function u:_init(B)if self==B then return end;if B then for C in v(B)do a(self,C)end end end;u.new=u;function u:clone()local D=w({},self)D:extend(self)return D end;function u:append(E)a(self,E)return self end;u.push=a;function u:extend(F)q(1,F,'table')for E=1,#F do a(self,F[E])end;return self end;function u:insert(E,G)q(1,E,'number')a(self,E,G)return self end;function u:put(G)return self:insert(1,G)end;function u:remove(E)q(1,E,'number')b(self,E)return self end;function u:remove_value(G)for E=1,#self do if self[E]==G then b(self,E)return self end end;return self end;function u:pop(E)if not E then E=#self end;q(1,E,'number')return b(self,E)end;u.get=u.pop;local H=e.find;u.index=H;function u:contains(G)return H(self,G)and true or false end;function u:count(G)local I=0;for E=1,#self do if self[E]==G then I=I+1 end end;return I end;function u:sort(J)if J then J=r(1,J)end;d(self,J)return self end;function u:sorted(J)return u(self):sort(J)end;function u:reverse()local x=self;local K=#x;for E=1,K/2 do x[E],x[K]=x[K],x[E]K=K-1 end;return self end;function u:minmax()local L,M=1e70,-1e70;for E=1,#self do local C=self[E]if C<L then L=C end;if C>M then M=C end end;return L,M end;function u:slice(N,O)return l(self,N,O)end;function u:clear()for E=1,#self do b(self)end;return self end;local P=1.0e-10;function u.range(Q,R,S)if not R then R=Q;Q=1 end;if S then q(3,S,'number')if math.ceil(S)~=S then R=R+P end else S=1 end;q(1,Q,'number')q(2,R,'number')local x=u()for E=Q,R,S do a(x,E)end;return x end;function u:len()return#self end;function u:chop(T,U)return k(self,T,U)end;function u:splice(V,W)q(1,V,'number')V=V-1;local E=1;for C in v(W)do a(self,E+V,C)E=E+1 end;return self end;function u:slice_assign(T,U,X)q(1,T,'number')q(1,U,'number')T,U=s(self,T,U)if U>=T then self:chop(T,U)end;self:splice(T,X)return self end;function u:__concat(F)q(1,F,'table')local D=self:clone()D:extend(F)return D end;function u:__eq(F)if#self~=#F then return false end;for E=1,#self do if self[E]~=F[E]then return false end end;return true end;function u:join(Y)Y=Y or''q(1,Y,'string')return c(o(self),Y)end;u.concat=c;local function Z(_)local a0=tostring(_)if type(_)=='string'then a0='"'..a0 ..'"'end;return a0 end;function u:__tostring()return'{'..self:join(',',Z)..'}'end;function u:foreach(a1,...)a1=r(1,a1)for E=1,#self do a1(self[E],...)end end;local function a2(y,a3)local a4=y[a3]if not a4 then error(type(y).." does not have method "..a3,3)end;return a4 end;function u:foreachm(a3,...)for E=1,#self do local y=self[E]local a4=a2(y,a3)a4(y,...)end end;function u:filter(a1,a5)return w(f(self,a1,a5),self)end;function u.split(a0,Y)q(1,a0,'string')return w(p(a0,Y))end;function u:map(a1,...)return w(g(a1,self,...),self)end;function u:transform(a1,...)j(a1,self,...)return self end;function u:map2(a1,D,...)return w(h(a1,self,D,...),self)end;function u:mapm(a3,...)local a6={}for E=1,#self do local _=self[E]local a7=a2(_,a3)a6[E]=a7(_,...)end;return w(a6,self)end;local function a8(a9,a4)return function(self,...)return self[a9](self,a4,...)end end;function u.default_map_with(aa)return function(self,a3)local ab;if aa then local a4=a2(aa,a3)ab=a8('map',a4)else ab=a8('mapn',a3)end;getmetatable(self)[a3]=ab;return ab end end;u.default_map=u.default_map_with;function u:reduce(a1)return i(a1,self)end;function u:partition(a1,...)a1=r(1,a1)local a6={}for E=1,#self do local _=self[E]local z=a1(_,...)if z==nil then z='<nil>'end;if not a6[z]then a6[z]=u()end;a6[z]:append(_)end;return setmetatable(a6,t)end;function u:iter()return v(self)end;function u.iterate(X)if type(X)=='string'then local V=0;local K=#X;local ac=string.sub;return function()V=V+1;if V>K then return nil else return ac(X,V,V)end end elseif type(X)=='table'then local V=0;local K=#X;return function()V=V+1;if V>K then return nil else return X[V]end end elseif type(X)=='function'then return X elseif type(X)=='userdata'and io.type(X)=='file'then return X:lines()end end;v=u.iterate;return u

6
extern/lualibs/pl/Map.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/Map.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.tablex'local b=require'pl.utils'local c=b.stdmt;local d=a.deepcompare;local e=require'pl.pretty'.write;local f=c.Map;local g=c.Set;local h=require'pl.class'h(nil,nil,f)function f:_init(i)local j=getmetatable(i)if j==g or j==f then self:update(i)else return i end end;local function k(i)return setmetatable(i,require('pl.List'))end;f.keys=a.keys;f.values=a.values;function f:iter()return pairs(self)end;function f:items()local l=k(a.pairmap(function(m,n)return k{m,n}end,self))l:sort(function(o,p)return o[1]<p[1]end)return l end;function f:setdefault(q,r)local s=self[q]if s~=nil then return s end;self:set(q,r)return r end;f.len=a.size;function f:set(q,s)self[q]=s end;function f:get(q)return rawget(self,q)end;local t=a.index_by;function f:getvalues(u)return k(t(self,u))end;f.update=a.update;function f:__eq(v)return d(self,v,true)end;function f:__tostring()return e(self,'')end;return f

6
extern/lualibs/pl/MultiMap.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/MultiMap.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.utils'local b=require'pl.class'local c=require'pl.List'local d=require'pl.Map'local e=a.stdmt.MultiMap;b(d,nil,e)e._name='MultiMap'function e:_init(f)if not f then return end;self:update(f)end;function e:update(f)a.assert_arg(1,f,'table')if d:class_of(f)then for g,h in pairs(f)do self[g]=c()self[g]:append(h)end else for g,h in pairs(f)do self[g]=c(h)end end end;function e:set(i,j)if j==nil then self[i]=nil else if not self[i]then self[i]=c()end;self[i]:append(j)end end;return e

6
extern/lualibs/pl/OrderedMap.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/OrderedMap.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.tablex'local b=require'pl.utils'local c=require'pl.List'local d,e,f=a.index_by,table.sort,table.concat;local g=require'pl.class'local h=require'pl.Map'local i=g(h)i._name='OrderedMap'local rawset=rawset;function i:_init(j)rawset(self,'_keys',c())if j then local k,l=self:update(j)if not k then error(l,2)end end end;local m,n=b.assert_arg,b.raise;function i:update(j)m(1,j,'table')if i:class_of(j)then for o,p in j:iter()do self:set(o,p)end elseif#j>0 then if type(j[1])=='table'then for q,r in ipairs(j)do local s,t=next(r)if not s then return n'empty pair initialization table'end;self:set(s,t)end else return n'cannot use an array to initialize an OrderedMap'end else for o,p in pairs(j)do self:set(o,p)end end;return self end;function i:set(s,u)if rawget(self,s)==nil and u~=nil then self._keys:append(s)rawset(self,s,u)else if u==nil then self._keys:remove_value(s)rawset(self,s,nil)else self[s]=u end end;return self end;i.__newindex=i.set;function i:insert(v,s,u)local w=self[s]u=u or w;if w then self._keys:remove_value(s)end;if u then self._keys:insert(v,s)rawset(self,s,u)end;return self end;function i:keys()return self._keys end;function i:values()return c(d(self,self._keys))end;function i:sort(x)e(self._keys,x)return self end;function i:iter()local y=0;local z=self._keys;local A;return function()y=y+1;if y>#z then return nil end;A=z[y]return A,self[A]end end;i.__pairs=i.iter;function i:__tostring()local B={}for y,p in ipairs(self._keys)do local u=self[p]local C=tostring(u)if type(u)~='number'then C='"'..C..'"'end;B[y]=tostring(p)..'='..C end;return'{'..f(B,',')..'}'end;return i

6
extern/lualibs/pl/Set.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/Set.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.tablex'local b=require'pl.utils'local c,d=b.array_tostring,table.concat;local e,f=a.merge,a.difference;local g=require'pl.Map'local h=require'pl.class'local i=b.stdmt;local j=i.Set;h(g,nil,j)j.__index=nil;local function k(l)return setmetatable(l,j)end;function j:_init(l)l=l or{}local m=getmetatable(l)if m==j or m==g then for n in pairs(l)do self[n]=true end else for o,p in ipairs(l)do self[p]=true end end end;function j:__tostring()return'['..d(c(j.values(self)),',')..']'end;j.values=g.keys;function j.map(self,q,...)q=b.function_arg(1,q)local r={}for n in pairs(self)do r[q(n,...)]=true end;return k(r)end;function j.union(self,s)return e(self,s,true)end;local function t(self,u)local m=getmetatable(u)if m==j or m==g then return j.union(self,u)else local v=j(self)v[u]=true;return v end end;j.__add=t;function j.intersection(self,s)return e(self,s,false)end;j.__mul=j.intersection;function j.difference(self,s)return f(self,s,false)end;local function w(self,u)local m=getmetatable(u)if m==j or m==g then return j.difference(self,u)else local v=j(self)v[u]=nil;return v end end;j.__sub=w;function j.symmetric_difference(self,s)return f(self,s,true)end;j.__pow=j.symmetric_difference;function j.issubset(self,s)for n in pairs(self)do if not s[n]then return false end end;return true end;j.__lt=j.issubset;function j.isempty(self)return next(self)==nil end;function j.isdisjoint(x,y)return j.isempty(j.intersection(x,y))end;j.len=a.size;j.__len=j.len;function j.__eq(x,y)return j.issubset(x,y)and j.issubset(y,x)end;return j

6
extern/lualibs/pl/array2d.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/class.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/class.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a,b,c,d,e,f,g,h,i=_G.error,_G.getmetatable,_G.io,_G.pairs,_G.rawget,_G.rawset,_G.setmetatable,_G.tostring,_G.type;local j;local function k(l,m,...)local n=e(l,'_init')local o=e(l,'_parent_with_init')if o then if not n then n=e(o,'_init')o=e(o,'_parent_with_init')end;if o then f(m,'super',function(m,...)k(o,m,...)end)end else f(m,'super',nil)end;local p=n(m,...)if o then f(m,'super',nil)end;return p end;local function q(self,r)if r==nil then return b(self)end;local s=b(self)if not s then return false end;while s do if s==r then return true end;s=e(s,'_base')end;return false end;local function t(r,m)if i(r)~='table'or not e(r,'is_a')then return false end;return r.is_a(m,r)end;local function u(r,m)return g(m,r)end;local function v(m)local w=m._class;local x=e(w,'_name')g(m,nil)local y=h(m)g(m,w)if x then y=x..y:gsub('table','')end;return y end;local function z(A,B,C)for D,E in d(B)do if not C or A[D]==nil then A[D]=E end end end;local function F(G,H,l)local w={}local I=i(G)=='table'and not b(G)if I then l=G;G=l._base else l=l or{}end;if i(G)=='table'then z(l,G,I)l._base=G;if e(l,'_handler')then w.__index=l._handler end elseif G~=nil then a("must derive from a table type",3)end;l.__index=l;g(l,w)if not I then if G and e(G,'_init')then l._parent_with_init=G end;l._init=nil end;if G and e(G,'_class_init')then G._class_init(l,H)end;w.__call=function(J,...)local m;if e(l,'_create')then m=l._create(...)end;if not m then m={}end;g(m,l)if e(l,'_init')or e(l,'_parent_with_init')then local p=k(l,m,...)if p then m=p;g(m,l)end end;if G and e(G,'_post_init')then G._post_init(m)end;return m end;l.catch=function(self,K)if i(self)=="function"then K=self end;l._handler=K;w.__index=K end;l.is_a=q;l.class_of=t;l.cast=u;l._class=l;if not e(l,'__tostring')then l.__tostring=v end;return l end;local L;L=g({},{__call=function(M,...)return F(...)end,__index=function(N,O)if O=='class'then c.stderr:write('require("pl.class").class is deprecated. Use require("pl.class")\n')return L end;j=j or require'pl.compat'local P=j.getfenv(2)return function(...)local l=F(...)l._name=O;f(P,O,l)return l end end})L.properties=L()function L.properties._class_init(r)r.__index=function(Q,O)local E=r[O]if E then return E end;E=e(r,'get_'..O)if E then return E(Q)end;return e(Q,'_'..O)end;r.__newindex=function(Q,O,R)local S='set_'..O;local T=r[S]if T then T(Q,R)else f(Q,O,R)end end end;return L

6
extern/lualibs/pl/compat.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/compat.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={}a.lua51=_VERSION=='Lua 5.1'a.jit=tostring(assert):match('builtin')~=nil;if a.jit then a.jit52=not loadstring("local goto = 1")end;a.dir_separator=_G.package.config:sub(1,1)a.is_windows=a.dir_separator=='\\'function a.execute(b)local c,d,e=os.execute(b)if d=="No error"and e==0 and a.is_windows then e=-1 end;if a.lua51 and not a.jit52 then if a.is_windows then return c==0,c else c=c>255 and c/256 or c;return c==0,c end else if a.is_windows then return e==0,e else return not not c,e end end end;if a.lua51 then if not a.jit then local f=load;function a.load(g,h,i,j)local k,l;if type(g)=='string'then if g:byte(1)==27 and not(i or'bt'):find'b'then return nil,"attempt to load a binary chunk"end;k,l=loadstring(g,h)else k,l=f(g,h)end;if k and j then setfenv(k,j)end;return k,l end else a.load=load end;a.setfenv,a.getfenv=setfenv,getfenv else a.load=load;function a.setfenv(m,n)m=type(m)=='function'and m or debug.getinfo(m+1,'f').func;local o;local p=0;repeat p=p+1;o=debug.getupvalue(m,p)until o=='_ENV'or o==nil;if o then debug.upvaluejoin(m,p,function()return o end,1)debug.setupvalue(m,p,n)end;if m~=0 then return m end end;function a.getfenv(m)local m=m or 0;m=type(m)=='function'and m or debug.getinfo(m+1,'f').func;local o,q;local p=0;repeat p=p+1;o,q=debug.getupvalue(m,p)until o=='_ENV'or o==nil;return q end end;if not table.pack then function table.pack(...)return{n=select('#',...),...}end end;if not table.unpack then table.unpack=unpack end;if not package.searchpath then function package.searchpath(o,r,s,t)if type(o)~="string"then error(("bad argument #1 to 'searchpath' (string expected, got %s)"):format(type(r)),2)end;if type(r)~="string"then error(("bad argument #2 to 'searchpath' (string expected, got %s)"):format(type(r)),2)end;if s~=nil and type(s)~="string"then error(("bad argument #3 to 'searchpath' (string expected, got %s)"):format(type(r)),2)end;if t~=nil and type(t)~="string"then error(("bad argument #4 to 'searchpath' (string expected, got %s)"):format(type(r)),2)end;s=s or"."t=t or a.dir_separator;do local u,v=o:find(s,nil,true)while u do o=o:sub(1,u-1)..t..o:sub(v+1,-1)u,v=o:find(s,u+#t+1,true)end end;local w={}for x in r:gmatch('[^;]+')do local y=x:gsub('?',o)w[#w+1]=y;local m=io.open(y,'r')if m then m:close()return y end end;return nil,"\tno file '"..table.concat(w,"'\n\tno file '").."'"end end;if not warn then local z=false;function warn(A,...)if type(A)=="string"and A:sub(1,1)=="@"then if A=="@on"then z=true;return end;if A=="@off"then z=false;return end;return end;if z then io.stderr:write("Lua warning: ",A,...)io.stderr:write("\n")end end end;return a

6
extern/lualibs/pl/comprehension.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/comprehension.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.utils'local b,c=pcall(require,"pl.luabalanced")if not b then c=require'luabalanced'end;local d=math.max;local e=table.concat;local f={list={init=' {} ',accum=' __result[#__result+1] = (%s) '},table={init=' {} ',accum=' local __k, __v = %s __result[__k] = __v '},sum={init=' 0 ',accum=' __result = __result + (%s) '},min={init=' nil ',accum=' local __tmp = %s '..' if __result then if __tmp < __result then '..'__result = __tmp end else __result = __tmp end '},max={init=' nil ',accum=' local __tmp = %s '..' if __result then if __tmp > __result then '..'__result = __tmp end else __result = __tmp end '}}local function g(h)local i=1;local j;local k,l=h:match('^%s*([%a_][%w_]*)%s*%(()',i)local m=#h+1;if k then local n,o=c.match_bracketed(h,l-1)assert(n,'syntax error')if h:match('^%s*$',o)then j=k;m=o-1;i=l end end;j=j or"list"local p;p,i=c.match_explist(h,i)assert(p,"syntax error: missing expression list")p=e(p,', ')local q={}local r={}local s={}while 1 do local l=h:match('^%s*for%s+()',i)if not l then break end;i=l;local t;t,i=c.match_namelist(h,i)assert(#t>0,'syntax error: zero variables')for u,v in ipairs(t)do assert(not v:match'^__',"identifier "..v.." may not contain __ prefix")end;r[#r+1]=t;local w,l=h:match('^(=)%s*()',i)if not w then w,l=h:match('^(in)%s+()',i)end;if w then i=l;local x;x,i=c.match_explist(h,i)assert(#x>0,'syntax error: zero expressions')assert(w~='='or#x==2 or#x==3,'syntax error: numeric for requires 2 or three expressions')q[#r]=w;s[#r]=x else q[#r]=false;s[#r]=false end end;assert(#r>0,'syntax error: missing "for" clause')local y={}while 1 do local l=h:match('^%s*if%s+()',i)if not l then break end;i=l;local z;z,i=c.match_expression(h,i)assert(z,'syntax error: predicated expression not found')y[#y+1]=z end;local A=''c.gsub(h,function(B,C)if B=='e'then A=A..' '..C..' 'end end)local D=0;A:gsub('[%a_][%w_]*',function(E)local E=E:match('^_(%d+)$')if E then D=d(D,tonumber(E))end end)if i~=m then assert(false,"syntax error: unrecognized "..h:sub(i))end;return p,q,r,s,y,j,D end;local function F(p,q,r,s,y,j,D)local G=assert(f[j])local H=G.accum:gsub('%%s',p)for I=#y,1,-1 do local z=y[I]H=' if '..z..' then '..H..' end 'end;for I=#r,1,-1 do if not q[I]then local J='__in'..I;local K='__idx'..I;H=' for '..K..' = 1, #'..J..' do '..' local '..r[I][1]..' = '..J..'['..K..'] '..H..' end 'else H=' for '..e(r[I],', ')..' '..q[I]..' '..e(s[I],', ')..' do '..H..' end 'end end;H=' local __result = ( '..G.init..' ) '..H;return H end;local function L(H,M,D,s,N)assert(M>0)local O={}for I=1,D do O[#O+1]='_'..I end;for I=1,M do if not s[I]then local P='__in'..I;O[#O+1]=P end end;if#O>0 then H=' local '..e(O,', ')..' = ... '..H end;H=H..' return __result 'local Q,R=a.load(H,'tmp','t',N)if not Q then assert(false,R..' with generated code '..H)end;return Q end;local function S(h,N)local p,q,r,s,y,j,D=g(h)local H=F(p,q,r,s,y,j,D)local Q=L(H,#r,D,s,N)return Q end;local function T(N)if not N then N=a.getfenv(2)end;local U={}local V=setmetatable({},U)function U:__index(h)local Q=S(h,N)self[h]=Q;return Q end;U.__call=U.__index;V.new=T;return V end;local W={}W.new=T;return W

6
extern/lualibs/pl/config.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/config.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a,b,c,d,e=_G.type,_G.tonumber,_G.ipairs,_G.io,_G.table;local function f(g,h)local i={}local j=e.insert;h='[^'..h..']+'for k in g:gmatch(h)do j(i,k)end;return i end;local function l(g)return g:gsub('^%s+',''):gsub('%s+$','')end;local function m(g)return g:gsub("['\"](.*)['\"]",'%1')end;local n={}function n.lines(o)local p,q,r;local s=''if a(o)=='string'then p,r=d.open(o,'r')if not p then return nil,r end;q=true else p=o or d.stdin;if not o.read then return nil,'not a file-like object'end end;if not p then return nil,'file is nil'end;return function()local t=p:read()while t do if t:match'%S'and not t:match'^%s*[;#]'then local u=t:find'\\%s*$'if u then s=s..t:sub(1,u-1)elseif s==''then return t else t=s..t;s=''return t end end;t=p:read()end;if q then p:close()end end end;function n.read(o,v)local w;local x,r=n.lines(o)if not x then return nil,r end;local s=x()v=v or{}if v.smart then w=true;if s:match'^[^=]+='then v.keysep='='elseif s:match'^[^:]+:'then v.keysep=':'v.list_delim=':'elseif s:match'^%S+%s+'then v.keysep=' 'if s:match'^%S+%s+%S+%s+%S+'then v.list_delim=' 'end;v.variabilize=false end end;local function y(z,A)local B=v[z]if B==nil then return A else return B end end;local C='^[%d%+%-]'local D={}local E=D;local F=y('variabilize',true)local G=y('list_delim',',')local H=y('convert_numbers',true)local I=y('convert_boolean',false)local J=y('trim_space',true)local K=y('trim_quotes',false)local L=y('ignore_assign',false)local M=y('keysep','=')local N=M==' 'and'%s+'or'%s*'..M..'%s*'if G==' 'then G='%s+'end;local function O(P)if F then P=P:gsub('[^%w]','_')end;return P end;local function Q(R)if G and R:find(G)then R=f(R,G)for u,S in c(R)do R[u]=Q(S)end elseif H and R:find(C)then local B=b(R)if not B and R:match' kB$'then R=R:gsub(' kB','')B=b(R)end;if B then R=B end elseif I and R=='true'then return true elseif I and R=='false'then return false end;if a(R)=='string'then if J then R=l(R)end;if not K and w and R:match'^"'then K=true end;if K then R=m(R)end end;return R end;while s do if s:find('^%[')then local T=O(s:match('%[([^%]]+)%]'))D=E;D[T]={}D=D[T]else s=s:gsub('^%s*','')local U,V=s:find(N)if U and not L then local P=O(s:sub(1,U-1))local R=Q(s:sub(V+1))D[P]=R else D[#D+1]=Q(s)end end;s=x()end;return E end;return n

41
extern/lualibs/pl/data.lua vendored Normal file
View File

@ -0,0 +1,41 @@
-- Penlight 1.11.0-1 | /lua/pl/data.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.utils'local b=rawget(_G,'_DEBUG')local c,d,e,f=a.patterns,a.function_arg,a.split,a.array_tostring;local g,h=table.insert,table.concat;local i=string.gsub;local io=io;local _G,print,type,tonumber,ipairs,setmetatable=_G,print,type,tonumber,ipairs,setmetatable;local j={}local k;local function l(m)return m:gsub('%s+$','')end;local function n(m)return l(m):gsub('^%s*','')end;local function o(p)return setmetatable(p,require('pl.List'))end;local function q(r,s)local t={}for u=1,#s do t[u]=r(s[u])end;return t end;local function v(w,x,y,z)local A;if y and w:match'"'then w=w:gsub('"([^"]+)"',function(B)local m,C=B:gsub(',','\001')if C>0 then A=true end;return m end)if A then A=function(m)return m:gsub('\001',',')end end end;local t=e(w,x,false,z)if y then if A then t=q(A,t)end;if w:match',$'then g(t,'')end end;return o(t)end;local function D(s,E)for u=1,#s do if E==s[u]then return u end end end;local F={column_by_name=function(self,G)if type(G)=='number'then G='$'..G end;local H={}for t in j.query(self,G)do g(H,t)end;return o(H)end,copy_select=function(self,I)I=k(I,self)local J=j.query(self,I)local t={}local K=o{J()}while#K>0 do g(t,K)K=o{J()}end;t.delim=self.delim;return j.new(t,v(I.fields,','))end,column_names=function(self)return self.fieldnames end}local L;F.__index=function(self,G)local M=F[G]if M then return M end;if not L then L=require'pl.array2d'end;return L[G]end;local N={',','\t',' ',';'}local function O(w)if w==''then return' 'end;for P,x in ipairs(N)do if w:find(x)then return x==' 'and'%s+'or x end end;return' 'end;local function Q(M,R)local S,T;local U=R=='r'if type(M)=='string'then if M=='stdin'then M=io.stdin elseif M=='stdout'then M=io.stdout else M,T=io.open(M,R)if not M then return nil,T end;S=true end end;if M and(U and not M.read or not U and not M.write)then return nil,"not a file-like object"end;return M,nil,S end;function j.read(V,W)local X,w;local Y={}if not W then W={}end;local M,T,S=Q(V,'r')if not M then return nil,T end;local Z=W.thousands_dot;local y=W.csv;if y then W.delim=','end;local tonumber=tonumber;local function _(a0)if Z then a0=a0:gsub('%.(...)','%1')end;if y and a0==''then a0='0'end;local E=tonumber(a0)if E==nil then return nil,"not a number"end;return E end;X=1;w=M:read()if not w then return nil,"empty file"end;Y.delim=W.delim and W.delim or O(w)local x=Y.delim;local a1;local a2={}local function a3(a4,a5)a1=a1 or{}g(a2,a4)g(a1,a5)end;if W.numfields then for P,z in ipairs(W.numfields)do a3(z,_)end end;local a6;if x=='%s+'and w:find(x)==1 then a6=function(m)return m:gsub('^%s+','')end;w=a6(w)end;if not W.fieldnames then local a7,a8;a7=v(w,x,y)if not W.convert then a8=q(tonumber,a7)if#a8==#a7 then g(Y,a8)for u=1,#a8 do a3(u,_)end else a8=nil end else for a4,a5 in pairs(W.convert)do a3(a4,a5)end end;if a8==nil then W.fieldnames=a7 end;w=M:read()X=X+1;if a6 then w=a6(w)end elseif type(W.fieldnames)=='string'then W.fieldnames=v(W.fieldnames,x,y)end;local a9;if W.fieldnames then Y.fieldnames=W.fieldnames;if W.last_field_collect then a9=#Y.fieldnames end;if not W.no_convert then local a7=v(w,Y.delim,y,a9)for u=1,#a7 do if not D(a2,u)and _(a7[u])then a3(u,_)end end end end;while w do if not w:find('^%s*$')then if a6 then w=a6(w)end;local a7=v(w,x,y,a9)if a1 then for aa=1,#a2 do local u,a5=a2[aa],a1[aa]local ab,T=a5(a7[u])if ab==nil then return nil,T..": "..a7[u].." at line "..X else a7[u]=ab end end end;g(Y,a7)end;w=M:read()X=X+1 end;if S then M:close()end;if x=='%s+'then Y.delim=' 'end;if not Y.fieldnames then Y.fieldnames={}end;return j.new(Y)end;local function ac(j,M,K,x)j.temp=f(K,j.temp)M:write(h(j.temp,x),'\n')end;function F:write_row(M,K)ac(self,M,K,self.delim)end;function j.write(j,V,ad,x)local M,T,S=Q(V,'w')if not M then return nil,T end;if not ad then ad=j.fieldnames end;x=x or'\t'if ad and#ad>0 then M:write(h(ad,x),'\n')end;for u=1,#j do ac(j,M,j[u],x)end;if S then M:close()end;return true end;function F:write(V)j.write(self,V,self.fieldnames,self.delim)end;local function ae(a7,af)for u=1,#a7 do local M=n(a7[u])af[u]=M;a7[u]=M:gsub('%W','_')end end;function j.new(ag,ad)ag.fieldnames=ag.fieldnames or ad or''if not ag.delim and type(ag.fieldnames)=='string'then ag.delim=O(ag.fieldnames)ag.fieldnames=v(ag.fieldnames,ag.delim)end;ag.fieldnames=o(ag.fieldnames)ag.original_fieldnames={}ae(ag.fieldnames,ag.original_fieldnames)setmetatable(ag,F)return ag end;local ah=[[
return function (t)
local i = 0
local v
local ls = {}
for i,v in ipairs(t) do
if CONDITION then
ls[#ls+1] = v
end
end
table.sort(ls,function(v1,v2)
return SORT_EXPR
end)
local n = #ls
return function()
i = i + 1
v = ls[i]
if i > n then return end
return FIELDLIST
end
end
]]local ai=[[
return function (t)
local n = #t
local i = 0
local v
return function()
repeat
i = i + 1
v = t[i]
until i > n or CONDITION
if i > n then return end
return FIELDLIST
end
end
]]local function aj(m)return type(m)=='string'end;local ak;local function al(j)return h(j.fieldnames,',')end;local function am(j,M)local a4;if M:find'^%d+$'then a4=tonumber(M)else a4=D(j.fieldnames,M)end;if a4 then return'v['..a4 ..']'else ak=M..' not found in '..al(j)return M end end;local function an(j,ao)ak=nil;local a7=ao.fields;local a2=a7:find'%$'or#j.fieldnames==0;if a7:find'^%s*%*%s*'then if not a2 then a7=al(j)else local ap=#j[1]a7={}for u=1,ap do g(a7,'$'..u)end;a7=h(a7,',')end end;local aq=c.IDEN;if a2 then aq='%$(%d+)'else a7=l(a7):gsub('[^,%w]','_')end;local am=a.bind1(am,j)local ar=i(a7,aq,am)if ak then return nil,ak end;ao.fields=a7;ao.proc_fields=ar;ao.where=ao.where or'true'if aj(ao.where)then ao.where=i(ao.where,aq,am)ak=nil end;return true end;k=function(m,j)local as;local ao={}local at,au=m:find('where ')local av,aw=m:find('sort by ')if at then as=(av or 0)-1;ao.where=m:sub(au+1,as)end;if av then ao.sort_by=m:sub(aw+1)end;as=(at or av or 0)-1;ao.fields=m:sub(1,as)local ax,T=an(j,ao)if not ax then return nil,T else return ao end end;function j.query(j,I,ay,az)local T;if aj(I)then I,T=k(I,j)if not I then return nil,T end elseif type(I)=='table'then if type(I.fields)=='table'then I.fields=h(I.fields,',')end;if not I.proc_fields then local ax,T=an(j,I)if not ax then return nil,T end end else return nil,"condition must be a string or a table"end;local aA;if I.sort_by then aA=ah else aA=ai end;local a7=I.proc_fields or I.fields;if az then a7='{'..a7 ..'}'end;aA=aA:gsub('FIELDLIST',a7)if aj(I.where)then aA=aA:gsub('CONDITION',I.where)I.where=nil else aA=aA:gsub('CONDITION','_condn(v)')I.where=d(0,I.where,'condition.where must be callable')end;if I.sort_by then local aB,aC,aD;local aE=I.sort_by;local aF,aG=aE:find('%s+')if aF then aC,aD=aE:sub(1,aF-1),aE:sub(aG+1)else aC=aE;aD='asc'end;if aC:match'^%$'then aC=aC:sub(2)end;aC=am(j,aC)if ak then return nil,ak end;if aD=='asc'then aD='<'else aD='>'end;aB=('%s %s %s'):format(aC:gsub('v','v1'),aD,aC:gsub('v','v2'))aA=aA:gsub('SORT_EXPR',aB)end;if I.where then aA='return function(_condn) '..aA..' end'end;if b then print(aA)end;local aH,T=a.load(aA,'tmp')if not aH then return nil,T end;aH=aH()if I.where then aH=aH(I.where)end;local aI=aH(j)if ay then g(ay,_G)local aJ={}a.setfenv(aI,aJ)setmetatable(aJ,{__index=function(aK,aL)for aa,s in ipairs(ay)do if s[aL]then return s[aL]end end end})end;return aI end;F.select=j.query;F.select_row=function(ag,I,ay)return j.query(ag,I,ay,true)end;function j.filter(aM,aN,aO,aP)local ag=j.read(aN or'stdin')local aQ=Q(aO or'stdout')local J,T=ag:select(aM)local x=ag.delim;if not J then T='error: '..T;if aP then return nil,T else a.quit(1,T)end end;while true do local t={J()}if#t==0 then break end;aQ:write(h(t,x),'\n')end end;return j

10
extern/lualibs/pl/func.lua vendored Normal file
View File

@ -0,0 +1,10 @@
-- Penlight 1.11.0-1 | /lua/pl/func.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local type,setmetatable,getmetatable,rawset=type,setmetatable,getmetatable,rawset;local a,b=table.concat,table.insert;local tostring=tostring;local c=require'pl.utils'local pairs,rawget,d,e=pairs,rawget,c.unpack,c.pack;local f=require'pl.tablex'local g=f.map;local h=rawget(_G,'_DEBUG')local i=c.assert_arg;local j={}local k={}local function l(m)setmetatable(m,k)return m end;j.PE=l;local function n(o)return getmetatable(o)==k end;j.isPE=n;local function p(q)return l{op='X',repr='_'..q,index=q}end;local function r(q)return l{op='X',repr='_C'..q,index=q}end;j._1,j._2,j._3,j._4,j._5=p(1),p(2),p(3),p(4),p(5)j._0=l{op='X',repr='...',index=0}function j.Var(s)local t=c.split(s,'[%s,]+')local u={}for v=1,#t do b(u,l{op='X',repr=t[v],index=0})end;return d(u)end;function j._(w)return l{op='X',repr=w,index='wrap'}end;local x;j.Nil=j.Var'nil'function k.__index(o,y)return l{op='[]',o,y}end;function k.__call(z,...)return l{op='()',z,...}end;function k.__tostring(A)return x(A)end;function k.__unm(B)return l{op='unm',B}end;function j.Not(B)return l{op='not',B}end;function j.Len(B)return l{op='#',B}end;local function C(D,m)for s,E in pairs(m)do rawset(D,s,function(F,G)return l{op=E,F,G}end)end end;local function H(s,z,D)rawset(D,s,function(...)return l{op='()',z,...}end)end;local I={}local function J(K)return type(_G[K])=='table'end;function j.import(L,D)i(1,L,'string',J,'arg# 1: not a name of a global table')local m=_G[L]D=D or _G;for s,z in pairs(m)do H(s,z,D)I[z]=s end end;function j.register(z,s)i(1,z,'function')if s then i(2,s,'string')I[z]=s end;return function(...)return l{op='()',z,...}end end;function j.lookup_imported_name(z)return I[z]end;local function M(...)return...end;function j.Args(...)return l{op='()',M,...}end;local N={['or']=0,['and']=2,['==']=4,['~=']=4,['<']=4,['>']=4,['<=']=4,['>=']=4,['..']=6,['+']=8,['-']=8,['*']=10,['/']=10,['%']=10,['^']=14}local O={['not']=12,['#']=12,['unm']=12}C(j,{And='and',Or='or',Eq='==',Lt='<',Gt='>',Le='<=',Ge='>='})C(k,{__add='+',__sub='-',__mul='*',__div='/',__mod='%',__pow='^',__concat='..'})C(k,{__eq='=='})function j.tail(t)i(1,t,'table')local u={}for v=2,#t do b(u,t[v])end;return u end;function x(A,P)local Q=j.tail;if n(A)then local R=N[A.op]or O[A.op]if R then local S;if N[A.op]then local T=R;local U=R;if A.op=='..'or A.op=='^'then T=T+1 else U=U+1 end;local V=x(A[1],T)local W=x(A[2],U)S=V..' '..A.op..' '..W else local E=A.op=='unm'and'-'or A.op;S=E..' '..x(A[1],R)end;if P and P>R then S='('..S..')'end;return S else local t=g(x,A)if A.op=='[]'then return t[1]..'['..t[2]..']'elseif A.op=='()'then local X;if t[1]~=nil then X=t[1]else X=''end;return X..'('..a(Q(t),',')..')'else return A.repr end end elseif type(A)=='string'then return'"'..A..'"'elseif type(A)=='function'then local s=j.lookup_imported_name(A)if s then return s else return tostring(A)end else return tostring(A)end end;j.repr=x;local Y;function Y(A,Z)if n(A)then if A.op~='X'then local _=0;for v=1,#A do local a0=A[v]local a1=n(a0)if a1 then if a0.op=='X'and a0.index=='wrap'then a0=a0.repr;a1=false else _=math.max(_,Y(a0,Z))end end;if not a1 then b(Z,a0)A[v]=r(#Z)end end;return _ else return A.index end else return 0 end end;j.collect_values=Y;function j.instantiate(A)local a2,a3,a4={},{},{}local a5,a6,z;local K=j.collect_values(A,a3)for v=1,#a3 do b(a2,'_C'..v)if h then print(v,a3[v])end end;for v=1,K do b(a4,'_'..v)end;a2=a(a2,',')a4=a(a4,',')a5=x(A)local a7=('return function(%s) return function(%s) return %s end end'):format(a2,a4,a5)if h then print(a7)end;z,a6=c.load(a7,'fun')if not z then return nil,a6 end;z=z()z=z(d(a3))A.__PE_function=z;return z end;function j.I(A)if rawget(A,'__PE_function')then return A.__PE_function else return j.instantiate(A)end end;c.add_function_factory(k,j.I)j.bind1=c.bind1;j.curry=j.bind1;function j.compose(a8,a9)return function(...)return a8(a9(...))end end;function j.bind(X,...)local aa=e(...)local ab,a4,ac,a3={},{},{'fn'},{}local ad,ae,af=1,0,false;for v=1,aa.n do local ag=aa[v]if n(ag)and ag.op=='X'then b(ab,ag.repr)ae=math.max(ae,ag.index)if ag.index==0 then af=true end else local ah='_v'..ad;b(ac,ah)b(ab,ah)b(a3,ag)ad=ad+1 end end;for ai=1,ae do b(a4,'_'..ai)end;if af then b(a4,'...')end;ac=a(ac,',')a4=a(a4,',')ab=a(ab,',')local a7=([[
return function (%s)
return function(%s) return fn(%s) end
end
]]):format(ac,a4,ab)if h then print(a7)end;local u=c.load(a7)u=u()return u(X,d(a3))end;return j

6
extern/lualibs/pl/import_into.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/import_into.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
return function(a)local b;if a==true then b={}a={}end;local a=a or{}local c={utils=true,path=true,dir=true,tablex=true,stringio=true,sip=true,input=true,seq=true,lexer=true,stringx=true,config=true,pretty=true,data=true,func=true,text=true,operator=true,lapp=true,array2d=true,comprehension=true,xml=true,types=true,test=true,app=true,file=true,class=true,luabalanced=true,permute=true,template=true,url=true,compat=true,List=true,Map=true,Set=true,OrderedMap=true,MultiMap=true,Date=true}rawset(a,'utils',require'pl.utils')for d,e in pairs(a.utils.stdmt)do e.__index=function(f,g)return require('pl.'..d)[g]end end;local h,i;local j={}local k=getmetatable(a)if k then i=k.__index;if k.__newindex then j.__index=k.__newindex end end;function j.hook(l)h=l end;function j.__index(f,d)local m=c[d]if m then rawset(a,d,require('pl.'..d))return a[d]else local n;if h then n=h(f,d)if n then return n end end;if i then return i(f,d)end end end;if b then function j.__newindex(f,d,o)b[d]=o;rawset(f,d,o)end end;setmetatable(a,j)return a,b or a end

6
extern/lualibs/pl/init.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/init.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
require'pl.import_into'(_G)if rawget(_G,'PENLIGHT_STRICT')then require'pl.strict'end

6
extern/lualibs/pl/input.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/input.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=string.find;local b=string.sub;local c=string.match;local d=require'pl.utils'local e=d.unpack;local pairs,type,tonumber=pairs,type,tonumber;local f=d.patterns;local io=io;local g={}function g.alltokens(h,i,j)local k=h()local l=1;return function()while k do local m,n=a(k,i,l)if m then l=n+1;local o=b(k,m,n)if j then o=j(o)end;return o else k=h()l=1 end end;return nil end end;local p=g.alltokens;function g.create_getter(q)if q then if type(q)=='string'then local r=d.split(q,'\n')local s,t=0,#r;return function()s=s+1;if s>t then return nil end;return r[s]end else if not q.read then error('not a file-like object')end;return function()return q:read()end end else return io.read end end;function g.numbers(q)return p(g.create_getter(q),'('..f.FLOAT..')',tonumber)end;function g.words(q)return p(g.create_getter(q),"%w+")end;local function u(v,...)local w={...}for s=1,#w do local t=tonumber(w[s])if t==nil then if not v then return nil,w[s]end else w[s]=t end end;return w end;function g.fields(x,y,q,z)local A;local m;local h=g.create_getter(q)local v=z and z.no_fail;local B=z and z.no_convert;if not y or y==' 'then y='%s'A='%s+'m='%s*'else A=y;m=''end;local C=0;if type(x)=='table'then for s,D in pairs(x)do if D>C then C=D end end else C=x;x={}for s=1,C do x[#x+1]=s end end;local E='[^'..y..']*'local F=1;for s=1,C do if x[F]==s then F=F+1;m=m..'('..E..')'else m=m..E end;if s<C then m=m..A end end;local G=1;return function()local k,H,I;repeat k=h()G=G+1;if not k then return nil end;if B then H={c(k,m)}else H,I=u(v,c(k,m))if not H then d.quit("line "..G-1 ..": cannot convert '"..I.."' to number")end end until#H>0;return e(H)end end;return g

6
extern/lualibs/pl/lapp.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/lexer.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/luabalanced.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/luabalanced.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={}local assert=assert;local b={['(']=')',['{']='}',['[']=']'}local c={}for d,e in pairs(b)do c[e]=d end;local function f(g,h)h=h or 1;local i=h;local j=g:sub(h,h)if j=='"'or j=="'"then h=h+1;while 1 do h=assert(g:find("["..j.."\\]",h),'syntax error')if g:sub(h,h)==j then local k=g:sub(i,h)return k,h+1 else h=h+2 end end else local l=g:match("^%[(=*)%[",h)if l then local m;m,h=g:find("%]"..l.."%]",h)assert(h)local k=g:sub(i,h)return k,h+1 else return nil,h end end end;a.match_string=f;local function n(g,h)h=h or 1;local i=h;local o=g:sub(h,h)if not b[o]then return nil,h end;local p={}while 1 do h=g:find('[%(%{%[%)%}%]\"\']',h)assert(h,'syntax error: unbalanced')local j=g:sub(h,h)if j=='"'or j=="'"then local k;k,h=f(g,h)assert(k)elseif b[j]then local q,r;if j=='['then q,r=g:match('^%[(=*)%[()',h)end;if q then h=g:match('%]'..q..'%]()',r)assert(h,'syntax error: long string not terminated')if#p==0 then local k=g:sub(i,h-1)return k,h end else p[#p+1]=j;h=h+1 end else assert(p[#p]==assert(c[j]),'syntax error: unbalanced')p[#p]=nil;if#p==0 then local k=g:sub(i,h)return k,h+1 end;h=h+1 end end end;a.match_bracketed=n;local function s(g,h)h=h or 1;if g:sub(h,h+1)~='--'then return nil,h end;h=h+2;local t,u=f(g,h)if t then return'--'..t,u end;local k;k,h=g:match('^([^\n]*\n?)()',h)return'--'..k,h end;local v={['and']=true,['or']=true,['not']=true}local w={['>']=true,['<']=true,['~']=true}local function x(g,h)h=h or 1;local m;local i=h;local y;local z,A;while h do local j=g:sub(h,h)if j=='"'or j=="'"or j=='['and g:find('^[=%[]',h+1)then local k;k,h=f(g,h)assert(k,'syntax error')elseif j=='-'and g:sub(h+1,h+1)=='-'then z=h;while g:sub(h,h+1)=='--'do local k;k,h=s(g,h)assert(k)h=g:match('^%s*()',h)A=h end elseif j=='('or j=='{'or j=='['then m,h=n(g,h)elseif j=='='and g:sub(h+1,h+1)=='='then h=h+2 elseif j=='='and w[g:sub(h-1,h-1)]then h=h+1 elseif j:match'^[%)%}%];,=]'then local k=g:sub(i,h-1)return k,h elseif j:match'^[%w_]'then local B,C=g:match('^([%w_]+)()',h)if h~=i and not v[B]then local D=(A==h and z or h)-1;while g:match('^%s',D)do D=D-1 end;local E=g:sub(D,D)if E:match'[%)%}\'\"%]]'or E:match'[%w_]'and not v[y]then local k=g:sub(i,h-1)return k,h end end;y,h=B,C else h=h+1 end;h=g:find('[%(%{%[%)%}%]\"\';,=%w_%-]',h)end;local k=g:sub(i,#g)return k,#g+1 end;a.match_expression=x;local function F(g,h)h=h or 1;local G={}while 1 do local j=#G==0 and'^'or'^%s*,%s*'local H,u=g:match(j..'([%a_][%w_]*)%s*()',h)if H then h=u else break end;G[#G+1]=H end;return G,h end;a.match_namelist=F;local function I(g,h)h=h or 1;local G={}while 1 do if#G~=0 then local u=g:match('^%s*,%s*()',h)if u then h=u else break end end;local H;H,h=x(g,h)assert(H,'syntax error')G[#G+1]=H end;return G,h end;a.match_explist=I;local function J(g,K)local h=1;local i=1;local L=''while 1 do h=g:find('[%-\'\"%[]',h)if not h then break end;if g:match('^%-%-',h)then local M=g:sub(i,h-1)if#M>0 then L=L..(K('e',M)or M)end;local N;N,h=s(g,h)L=L..(K('c',assert(N))or N)i=h else local r=g:find('^[\'\"%[]',h)local O;if r then O,h=f(g,r)end;if O then local M=g:sub(i,r-1)if#M>0 then L=L..(K('e',M)or M)end;L=L..(K('s',O)or O)i=h else h=h+1 end end end;local M=g:sub(i)if#M>0 then L=L..(K('e',M)or M)end;return L end;a.gsub=J;return a

6
extern/lualibs/pl/operator.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/operator.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=string.find;local b={}function b.call(c,...)return c(...)end;function b.index(d,e)return d[e]end;function b.eq(f,g)return f==g end;function b.neq(f,g)return f~=g end;function b.lt(f,g)return f<g end;function b.le(f,g)return f<=g end;function b.gt(f,g)return f>g end;function b.ge(f,g)return f>=g end;function b.len(f)return#f end;function b.add(f,g)return f+g end;function b.sub(f,g)return f-g end;function b.mul(f,g)return f*g end;function b.div(f,g)return f/g end;function b.pow(f,g)return f^g end;function b.mod(f,g)return f%g end;function b.concat(f,g)return f..g end;function b.unm(f)return-f end;function b.lnot(f)return not f end;function b.land(f,g)return f and g end;function b.lor(f,g)return f or g end;function b.table(...)return{...}end;function b.match(f,g)return a(f,g)~=nil end;function b.nop(...)return...end;b.optable={['+']=b.add,['-']=b.sub,['*']=b.mul,['/']=b.div,['%']=b.mod,['^']=b.pow,['..']=b.concat,['()']=b.call,['[]']=b.index,['<']=b.lt,['<=']=b.le,['>']=b.gt,['>=']=b.ge,['==']=b.eq,['~=']=b.neq,['#']=b.len,['and']=b.land,['or']=b.lor,['{}']=b.table,['~']=b.match,['']=b.nop}return b

6
extern/lualibs/pl/permute.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/permute.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.tablex'local b=require'pl.utils'local c=a.deepcopy;local d=table.insert;local e=b.assert_arg;local f={}function f.order_iter(g)e(1,g,'table')local h=#g;local i={1}local function j()local k=#i;local l=h-k+1;local m=i[k]if m>h then return end;if l==0 then table.remove(i)k=k-1;i[k]=i[k]+1;return g elseif m<=l then g[l],g[m]=g[m],g[l]table.insert(i,1)else table.remove(i)k=k-1;l=l+1;m=i[k]g[l],g[m]=g[m],g[l]i[k]=i[k]+1 end;return j()end;return j end;function f.order_table(g)e(1,g,'table')local n={}for h in f.iter(g)do d(n,c(h))end;return n end;function f.list_iter(...)local o={...}local p={}local q={}local r=#o;for m,s in ipairs(o)do e(m,s,'table')p[m]=1;q[m]=s.n or#s end;local t=0;return function()if p[r]>q[r]then return end;t=t+1;local u={n=#o}local v=true;for m=1,r do u[m]=o[m][p[m]]if v then p[m]=p[m]+1;if p[m]<=q[m]then v=false else if m~=r then p[m]=1 end end end end;return t,b.unpack(u)end end;function f.list_table(...)local j=f.list_iter(...)local w={}local m=1;while true do local x=b.pack(j())if x[1]==nil then return w end;for m=1,x.n do x[m]=x[m+1]end;x.n=x.n-1;w[m]=x;m=m+1 end end;function f.iter(...)b.raise_deprecation{source="Penlight "..b._VERSION,message="function 'iter' was renamed to 'order_iter'",version_removed="2.0.0",deprecated_after="1.9.2"}return f.order_iter(...)end;function f.table(...)b.raise_deprecation{source="Penlight "..b._VERSION,message="function 'table' was renamed to 'order_table'",version_removed="2.0.0",deprecated_after="1.9.2"}return f.order_table(...)end;return f

6
extern/lualibs/pl/pretty.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/pretty.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=table.insert;local b=table.concat;local c,d=math.floor,math.huge;local e=math.type;local f=require'pl.utils'local g=require'pl.lexer'local h=require'debug'local i=require'pl.stringx'.quote_string;local j=f.assert_arg;local k=tostring;local function tostring(l)if type(l)~="number"then return k(l)elseif l~=l then return"NaN"elseif l==d then return"Inf"elseif l==-d then return"-Inf"elseif(_VERSION~="Lua 5.3"or e(l)=="integer")and c(l)==l then return("%d"):format(l)else local m=("%.14g"):format(l)if _VERSION=="Lua 5.3"and e(l)=="float"and not m:find("%.")then m=m:gsub("%d+","%0.0",1)end;return m end end;local n={}local function o()local p={}p.hook,p.mask,p.count=h.gethook()if p.hook~="external hook"then h.sethook()end;p.string_mt=getmetatable("")h.setmetatable("",nil)return p end;local function q(p)if p then h.setmetatable("",p.string_mt)if p.hook~="external hook"then h.sethook(p.hook,p.mask,p.count)end end end;function n.read(r)j(1,r,'string')if r:find'^%s*%-%-'then r=r:gsub('%-%-.-\n','')end;if not r:find'^%s*{'then return nil,"not a Lua table"end;if r:find'[^\'"%w_]function[^\'"%w_]'then local s=g.lua(r)for t,u in s do if t=='keyword'and u=='function'then return nil,"cannot have functions in table definition"end end end;r='return '..r;local v,w=f.load(r,'tbl','t',{})if not v then return nil,w end;local x=o()local y,z=pcall(v)q(x)if y then return z else return nil,z end end;function n.load(r,p,A)p=p or{}if A then local s=g.lua(r)for t,u in s do if t=='keyword'and(u=='for'or u=='repeat'or u=='function'or u=='goto')then return nil,"looping not allowed"end end end;local v,w=f.load(r,'tbl','t',p)if not v then return nil,w end;local x=A and o()local y,w=pcall(v)q(x)if not y then return nil,w end;return p end;local function B(u)if not u then return''else if u:find' 'then u=i(u)end end;return u end;local C;local function D(r)return type(r)=='string'and r:find('^[%a_][%w_]*$')and not C[r]end;local function E(r)if type(r)=='table'then return n.write(r,'')else return i(r)end end;local function F(G,H)if not G then H=E(H)H=H:find("^%[")and" "..H.." "or H end;return'['..H..']'end;function n.write(I,J,K)if type(I)~='table'then local m=tostring(I)if type(I)=='string'then return E(I)end;return m,'not a table'end;if not C then C=g.get_keywords()end;local L=' = 'if J==''then L='='end;J=J or' 'local M={}local N=''local O={}local function P(r)if#r>0 then N=N..r end end;local function Q(r)if#N>0 then N=N..r;a(M,N)N=''else a(M,r)end end;local function R()local S=#M;local T=M[S]:sub(-1,-1)if T==','then M[S]=M[S]:sub(1,-2)end end;local U=function(t)local V=0;local y,u;local W=function()return t[V]end;return function()V=V+1;y,u=pcall(W)if u==nil or not y then return end;return V,t[V]end end;local X=function(t)local Y,u,y;local W=function()return next(t,Y)end;return function()y,Y,u=pcall(W)if not y then return end;return Y,u end end;local Z;Z=function(t,_,a0)local a1=type(t)if a1~='string'and a1~='table'then Q(B(tostring(t))..',')elseif a1=='string'then Q(i(t)..",")elseif a1=='table'then if O[t]then Q('<cycle>,')return end;O[t]=true;local a2=a0 ..J;Q('{')local a3={}if not K then for V,a4 in U(t)do P(a0)Z(a4,a0,a2)a3[V]=true end end;local a5={}for Y,u in X(t)do if type(Y)~='number'then a5[#a5+1]=Y end end;table.sort(a5,function(a6,a7)if type(a6)==type(a7)and type(a6)=='string'then return a6<a7 end;return type(a6)=='boolean'or type(a7)~='boolean'and type(a6)=='table'end)local function a8(H,a4)local a9=type(H)local G=a9=='number'if K then H=tostring(H)P(a0 ..F(G,H)..L)Z(a4,a0,a2)else if not G or not a3[H]then if a9~='string'then H=tostring(H)end;if G or not D(H)then H=F(G,H)end;P(a0 ..H..L)Z(a4,a0,a2)end end end;for V=1,#a5 do local H=a5[V]local a4=t[H]a8(H,a4)end;for H,a4 in X(t)do if type(H)=='number'then a8(H,a4)end end;O[t]=nil;R()Q(_..'},')else Q(tostring(t)..',')end end;Z(I,'',J)R()return b(M,#J>0 and'\n'or'')end;function n.dump(t,aa)if not aa then print(n.write(t))return true else return f.writefile(aa,n.write(t))end end;function n.debug(...)local S=select("#",...)local t={...}for V=1,S do local l=t[V]if l==nil then l="<nil>"end;t[V]=nil;t["arg "..V]=l end;print(n.write(t))return true end;local ab,ac={'B','KiB','MiB','GiB'},{'','K','M','B'}local function ad(a4)local ae=math.floor(a4/1000)if ae>0 then return ad(ae)..','..tostring(a4%1000)else return tostring(a4)end end;function n.number(af,ag,ah)local ai='%.'..(ah or 1)..'f%s'if ag=='T'then return ad(af)else local aj,ak;if ag=='M'then ak=1024;aj=ab else ak=1000;aj=ac end;local al=ak;local Y=1;while af>=al and Y<=#aj do al=al*ak;Y=Y+1 end;al=al/ak;if Y>#aj then Y=Y-1;al=al/ak end;if Y>1 then return ai:format(af/al,aj[Y]or'duh')else return af..aj[1]end end end;return setmetatable(n,{__call=function(self,...)return self.debug(...)end})

6
extern/lualibs/pl/seq.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/sip.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/sip.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=rawget(_G,'loadstring')or load;local b=rawget(_G,'unpack')or rawget(table,'unpack')local c,d=table.insert,table.concat;local ipairs,type=ipairs,type;local io,_G=io,_G;local print,rawget=print,rawget;local e={FLOAT='[%+%-%d]%d*%.?%d*[eE]?[%+%-]?%d*',INTEGER='[+%-%d]%d*',IDEN='[%a_][%w_]*',OPTION='[%a_][%w_%-]*'}local function f(g,h,i)if type(h)~=i then error("argument "..g.." must be "..i,2)end end;local j={}local k={['<']='>',['(']=')',['{']='}',['[']=']'}local l={a=1,c=0,d=1,l=1,p=0,u=1,w=1,x=1,s=0}local function m(n)return'('..n..')'end;local function o(p)return p:gsub('[%-%.%+%[%]%(%)%^%%%?%*]','%%%0'):gsub('%$%%(%S)','$%1')end;local function q(r)return r:gsub("()%s+()",function(s,t)local u=r:sub(s-2,s-1)if u:match('%$[vifadxlu]')or u:match('^[^%$]?[%w_]$')then local v=r:sub(t,t+1)if v:match('%$[vifadxlu]')or v:match('^[%w_]')then return'%s+'end end;return'%s*'end)end;local w={v=m(e.IDEN),i=m(e.INTEGER),f=m(e.FLOAT),o=m(e.OPTION),r='(%S.*)',p='([%a]?[:]?[\\/%.%w_]+)'}function j.custom_pattern(x,r)w[x]=r end;function j.create_pattern(p,y)f(1,p,'string')local z,A={},{}if type(p)=='string'then p=o(p)else local B={}for C,n in ipairs(p)do B[C]=o(n)end;p=d(B,'.-')end;local D=1;local function E(F,type)F=F or D;c(z,F)A[F]=type;D=D+1 end;local G=p:find('{%a+}')if y and y.at_start then p='^'..p end;if p:sub(-1,-1)=='$'then p=p:sub(1,-2)..'$r'if G then p=p..'{rest}'end end;local H;if G then H={}p=p:gsub('{(%a+)}',function(F)c(H,F)return''end)end;p=q(p)local I=1;local J;local K=p:gsub('%$%S',function(n)local type,F;type=n:sub(2,2)if H then F=H[I]I=I+1 end;if not H and type=='q'then E(nil,'Q')else E(F,type)end;local B;if w[type]then B=w[type]elseif type=='q'then E(F,type)B='(["\'])(.-)%'..D-2 else local L=k[type]if L then B='(%b'..type..L..')'elseif l[type]or l[type:lower()]then B='(%'..type..'+)'else J="unknown format type or character class"end end;return B end)if J then return nil,J else return K,z,A end end;local function M(n)return n=='d'or n=='i'or n=='f'end;function j.create_spec_fun(p,y)local A,z;local N={}p,z,A=j.create_pattern(p,y)if not p then return p,z end;local G=type(z[1])=='string'for C=1,#z do c(N,'mm'..C)end;N[1]=N[1]or"mm1"local O=('return (function(s,res)\n\tlocal %s = s:match(%q)\n'):format(d(N,','),p)O=O..'\tif not mm1 then return false end\n'local I=1;for C,P in ipairs(z)do if P~='_'then local Q='mm'..C;if M(A[P])then Q='tonumber('..Q..')'elseif k[A[P]]then Q=Q..':sub(2,-2)'end;if G then O=('%s\tres.%s = %s\n'):format(O,P,Q)else if A[P]~='Q'then O=('%s\tres[%d] = %s\n'):format(O,I,Q)I=I+1 end end end end;return O..'\treturn true\nend)\n',G end;function j.compile(p,y)f(1,p,'string')local O,H=j.create_spec_fun(p,y)if not O then return nil,H end;if rawget(_G,'_DEBUG')then print(O)end;local R,J=a(O,'tmp')if J then return nil,J end;return R(),H end;local S={}function j.match(p,T,B,y)f(1,p,'string')f(2,T,'string')f(3,B,'table')if not S[p]then S[p]=j.compile(p,y)end;return S[p](T,B)end;function j.match_at_start(p,T,B)return j.match(p,T,B,{at_start=true})end;function j.fields(p,P)f(1,p,'string')if not P then return nil,"no file object"end;local O,J=j.compile(p)if not O then return nil,J end;local B={}return function()while true do local T=P:read()if not T then return end;if O(T,B)then local U=B;B={}return b(U)end end end end;local V={}function j.pattern(p,O)f(1,p,'string')local W,X=j.compile(p)c(V,{pat=W,named=X,callback=O})end;function j.read(P,Y)local Z,J;if not P then return nil,"no file object"end;if type(P)=='string'then P,J=io.open(P)if not P then return nil,J end;Z=true end;if Y then for _,a0 in ipairs(Y)do j.pattern(a0[1],a0[2])end end;local B={}for T in P:lines()do for _,a1 in ipairs(V)do if a1.pat(T,B)then if a1.callback then if a1.named then a1.callback(B)else a1.callback(b(B))end end;B={}break end end end;if Z then P:close()end end;return j

6
extern/lualibs/pl/strict.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/strict.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
require'debug'local a,error,rawset,rawget=debug.getinfo,error,rawset,rawget;local b={}local function c()local d=a(3,"S")return d and d.what or"C"end;function b.module(e,f,g)local h,i,j,k,l;if g then l=g.__global end;if type(f)=='table'then h=getmetatable(f)if h and rawget(h,'__declared')then return end else f={}end;if h==nil then h={}setmetatable(f,h)else i=h.__newindex;j=h.__index;k=type(j)end;h.__declared=g or{}h.__newindex=function(m,n,o)if i then i(m,n,o)if rawget(m,n)~=nil then return end end;if not h.__declared[n]then if l then local p=c()if p~="main"and p~="C"then error("assign to undeclared global '"..n.."'",2)end end;h.__declared[n]=true end;rawset(m,n,o)end;h.__index=function(m,n)if not h.__declared[n]and c()~="C"then if j then if k=="table"then local q=j[n]if q~=nil then return q end else local r=j(m,n)if r~=nil then return r end end end;local s="variable '"..n.."' is not declared"if e then s=s.." in '"..tostring(e).."'"end;error(s,2)end;return rawget(m,n)end;return f end;function b.make_all_strict(t)for u,o in pairs(t)do if type(o)=='table'and o~=t then b.module(u,o)end end end;function b.closed_module(f,e)local v={}f=f or{}local h=getmetatable(f)if not h then h={}setmetatable(f,h)end;h.__newindex=function(m,u,o)v[u]=o end;return b.module(e,v)end;if not rawget(_G,'PENLIGHT_NO_GLOBAL_STRICT')then b.module(nil,_G,{_PROMPT=true,_PROMPT2=true,__global=true})end;return b

6
extern/lualibs/pl/stringio.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/stringio.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=rawget(_G,'unpack')or rawget(table,'unpack')local tonumber=tonumber;local b,c=table.concat,table.insert;local d={}local e={}e.__index=e;local function f(self,...)local g={...}for h=1,#g do c(self.tbl,g[h])end end;function e:write(i,j,...)if j then f(self,i,j,...)else c(self.tbl,i)end end;function e:writef(k,...)self:write(k:format(...))end;function e:value()return b(self.tbl)end;function e:__tostring()return self:value()end;function e:close()end;function e:seek()end;local l={}l.__index=l;function l:_read(k)local h,m=self.i,self.str;local n=#m;if h>n then return nil end;local o;if k=='*l'or k=='*L'then local p=m:find('\n',h)or n+1;o=m:sub(h,k=='*l'and p-1 or p)self.i=p+1 elseif k=='*a'then o=m:sub(h)self.i=n elseif k=='*n'then local q,r,p;q,p=m:find('%s*%d+',h)q,r=m:find('^%.%d+',p+1)if r then p=r end;q,r=m:find('^[eE][%+%-]*%d+',p+1)if r then p=r end;local s=m:sub(h,p)o=tonumber(s)self.i=p+1 elseif type(k)=='number'then o=m:sub(h,h+k-1)self.i=h+k else error("bad read format",2)end;return o end;function l:read(...)if select('#',...)==0 then return self:_read('*l')else local o,t={},{...}for h=1,#t do o[h]=self:_read(t[h])end;return a(o)end end;function l:seek(u,v)local w;u=u or'cur'v=v or 0;if u=='set'then w=1 elseif u=='cur'then w=self.i elseif u=='end'then w=#self.str end;self.i=w+v;return self.i end;function l:lines(...)local x,g=select('#',...)if x>0 then g={...}end;return function()if x==0 then return self:_read'*l'else return self:read(a(g))end end end;function l:close()end;function d.create()return setmetatable({tbl={}},e)end;function d.open(y)return setmetatable({str=y,i=1},l)end;function d.lines(y,...)return d.open(y):lines(...)end;return d

6
extern/lualibs/pl/stringx.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/stringx.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.utils'local string=string;local b=string.find;local type,setmetatable,ipairs=type,setmetatable,ipairs;local error=error;local c=string.gsub;local d=string.rep;local e=string.sub;local f=string.reverse;local g=table.concat;local h=table.insert;local i=a.escape;local j,k=math.ceil,math.max;local l,m=a.assert_arg,a.split;local n;local function o(p,q)l(p,q,'string')end;local function r(q)return#q>0 end;local function s(p,q)l(p,q,'string',r,'must be a non-empty string')end;local function t(u)return setmetatable(u,require('pl.List'))end;local v={}function v.isalpha(q)o(1,q)return b(q,'^%a+$')==1 end;function v.isdigit(q)o(1,q)return b(q,'^%d+$')==1 end;function v.isalnum(q)o(1,q)return b(q,'^%w+$')==1 end;function v.isspace(q)o(1,q)return b(q,'^%s+$')==1 end;function v.islower(q)o(1,q)return b(q,'^[%l%s]+$')==1 end;function v.isupper(q)o(1,q)return b(q,'^[%u%s]+$')==1 end;local function w(q,x)return b(q,x,1,true)==1 end;local function y(q,z)return#q>=#z and b(q,z,#q-#z+1,true)and true or false end;local function A(q,B,C)if type(B)=='string'then return C(q,B)elseif type(B)=='table'then for D,E in ipairs(B)do if C(q,E)then return true end end;return false else error(("argument #2 expected a 'string' or a 'table', got a '%s'"):format(type(B)))end end;function v.startswith(q,x)o(1,q)return A(q,x,w)end;function v.endswith(q,z)o(1,q)return A(q,z,y)end;function v.join(q,F)o(1,q)return g(F,q)end;function v.splitlines(q,G)o(1,q)local H={}local I=1;while true do local J=b(q,'[\r\n]',I)if not J then break end;local K=e(q,J,J)if K=='\r'and e(q,J+1,J+1)=='\n'then K='\r\n'end;local L=e(q,I,J-1)if G then L=L..K end;h(H,L)I=J+#K end;if I<=#q then h(H,e(q,I))end;return t(H)end;function v.split(q,M,p)o(1,q)local N=true;if not M then q=n(q)N=false end;local H=m(q,M,N,p)if M and M~=''and b(q,M,-#M,true)and(p or math.huge)>#H then H[#H+1]=""end;return t(H)end;function v.expandtabs(q,O)o(1,q)O=O or 8;return q:gsub("([^\t\r\n]*)\t",function(P)return P..(" "):rep(O-#P%O)end)end;local function Q(q,e,R,S,T)R=R or 1;S=S or#q;if e==''then return S+1,S-R+1 end;local U,V=b(q,e,R,true)local H;local W=0;while U do if S and V>S then break end;H=U;W=W+1;if T then U,V=b(q,e,U+1,true)else U,V=b(q,e,V+1,true)end end;return H,W end;function v.lfind(q,e,R,S)o(1,q)o(2,e)local U,V=b(q,e,R,true)if U and(not S or V<=S)then return U else return nil end end;function v.rfind(q,e,R,S)o(1,q)o(2,e)return Q(q,e,R,S,true)end;function v.replace(q,X,Y,p)o(1,q)o(2,X)o(3,Y)return c(q,i(X),Y:gsub('%%','%%%%'),p)end;function v.count(q,e,T)o(1,q)local D,W=Q(q,e,1,false,T)return W end;local function Z(q,_,a0,a1,a2)local p=#q;if _>p then if not a0 then a0=' 'end;local a3,a4;if a1 and a2 then local a5=j((_-p)/2)local a6=_-p-a5;a3=d(a0,a6)a4=d(a0,a5)elseif a2 then a3=d(a0,_-p)a4=''else a4=d(a0,_-p)a3=''end;return a3 ..q..a4 else return q end end;function v.ljust(q,_,a0)o(1,q)l(2,_,'number')return Z(q,_,a0,true,false)end;function v.rjust(q,_,a0)o(1,q)l(2,_,'number')return Z(q,_,a0,false,true)end;function v.center(q,_,a0)o(1,q)l(2,_,'number')return Z(q,_,a0,true,true)end;local function a7(q,a1,a2,a8)if not a8 then a8='%s'else a8='['..i(a8)..']'end;local a9=1;local aa;if a1 then local U,V=b(q,'^'..a8 ..'*')if V>=U then a9=V+1 end end;if a2 then if#q<200 then local U,V=b(q,a8 ..'*$',a9)if V>=U then aa=U-1 end else local ab=f(q)local U,V=b(ab,'^'..a8 ..'*')if V>=U then aa=-V-1 end end end;return e(q,a9,aa)end;function v.lstrip(q,a8)o(1,q)return a7(q,true,false,a8)end;n=v.lstrip;function v.rstrip(q,a8)o(1,q)return a7(q,false,true,a8)end;function v.strip(q,a8)o(1,q)return a7(q,true,true,a8)end;function v.splitv(q,M)o(1,q)return a.splitv(q,M)end;local function ac(ad,ae,C)local U,V=C(ad,ae)if not U or U==-1 then return ad,'',''else if not V then V=U end;return e(ad,1,U-1),e(ad,U,V),e(ad,V+1)end end;function v.partition(q,a0)o(1,q)s(2,a0)return ac(q,a0,v.lfind)end;function v.rpartition(q,a0)o(1,q)s(2,a0)local af,ag,ah=ac(q,a0,v.rfind)if af==q then return ah,ag,af end;return af,ag,ah end;function v.at(q,ai)o(1,q)l(2,ai,'number')return e(q,ai,ai)end;function v.lines(q)o(1,q)if not q:find'\n$'then q=q..'\n'end;return q:gmatch('([^\n]*)\n')end;function v.title(q)o(1,q)return q:gsub('(%S)(%S*)',function(a9,aj)return a9:upper()..aj:lower()end)end;v.capitalize=v.title;local ak='...'local al=#ak;function v.shorten(q,_,am)o(1,q)if#q>_ then if _<al then return ak:sub(1,_)end;if am then local an=#q-_+1+al;return ak..q:sub(an)else return q:sub(1,_-al)..ak end end;return q end;local function ao(q)local ap='([%[%]])(=*)%1'local aq,ar,D;local as=1;repeat D,as,D,ar=q:find(ap,as)if ar then aq=k(aq or 0,#ar)end until not ar;return aq end;function v.quote_string(q)o(1,q)local at=ao(q.."]")if(q:find("\n")or at)and not q:find("\r")then at=("="):rep((at or-1)+1)if q:find("^\n")then q="\n"..q end;local au,av="["..at.."[","]"..at.."]"q=au..q..av else q=("%q"):format(q):gsub("\r","\\r")end;return q end;function v.import()a.import(v,string)end;return v

6
extern/lualibs/pl/tablex.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/template.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/template.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.utils'local b,c,d,e,f=table.insert,string.format,string.sub,string.find,string.gsub;local g="\n__R_size = __R_size + 1; __R_table[__R_size] = "local function h(i,j,k,l)local m=1;for n,o,p in j:gmatch(k)do o='('..d(o,2,-2)..')'b(i,g..c("%q",d(j,m,n-1)))b(i,g..c("__tostring(%s or '')",o))m=p end;local q;if l then q=c("%q",f(d(j,m),"\n",""))else q=c("%q",d(j,m))end;if q~='""'then b(i,g..q)end end;local function r(j,s,t,u,l)local k="()"..s.."(%b"..t..")()"local v=u.."+([^\n]*\n?)"local w,x="^"..v,"\n"..v;local i,m={"return function()\nlocal __R_size, __R_table, __tostring = 0, {}, __tostring",n=1},1;while true do local y,p,z=e(j,w,m)if not p then local A;A,p,z=e(j,x,m)h(i,d(j,m,A),k,l)if not p then break end end;if d(z,-1,-1)=="\n"then z=d(z,1,-2)end;b(i,"\n"..z)m=p+1 end;b(i,"\nreturn __R_table\nend")local B=false;if#i==3 and i[2]:find(g,1,true)==1 then i={"return "..i[2]:sub(#g+1,-1)}B=true end;return table.concat(i),B end;local C={}function C.substitute(D,E)E=E or{}local F,G=C.compile(D,{chunk_name=rawget(E,"_chunk_name"),escape=rawget(E,"_escape"),inline_escape=rawget(E,"_inline_escape"),inline_brackets=rawget(E,"_brackets"),newline=nil,debug=rawget(E,"_debug")})if not F then return F,G end;return F:render(E,rawget(E,"_parent"),rawget(E,"_debug"))end;local H=function(self,E,I,J)E=E or{}if I then setmetatable(E,{__index=I})end;setmetatable(self.env,{__index=E})local K,L=xpcall(self.fn,debug.traceback)if not K then if self.code and J then print(self.code)end;return nil,L,self.code end;return table.concat(L),nil,self.code end;function C.compile(D,M)M=M or{}local N=M.chunk_name or'TMP'local O=M.escape or'#'local s=M.inline_escape or'$'local P=M.inline_brackets or'()'local Q,B=r(D,s,P,O,M.newline)local E={__tostring=tostring}local R,G=a.load(Q,N,'t',E)if not R then return nil,G,Q end;if B then local S=R()return{fn=R(),env=E,render=function(self)return S,nil,self.code end,code=M.debug and Q or nil}end;return{fn=R(),env=E,render=H,code=M.debug and Q or nil}end;return C

6
extern/lualibs/pl/test.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/test.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.tablex'local b=require'pl.utils'local c=require'pl.pretty'local d=require'pl.path'local type,e,f=type,b.unpack,b.pack;local g=os.clock;local h=require'debug'local io=io;local function i(j)if type(j)=='table'and not(getmetatable(j)and getmetatable(j).__tostring)then return c.write(j,' ',true)elseif type(j)=='string'then return'"'..j..'"'else return tostring(j)end end;local k={}function k.error_handler(l,m,n,o,p)local q=io.stderr;q:write(d.basename(l)..':'..m..': assertion failed\n')q:write("got:\t",n,'\n')q:write("needed:\t",o,'\n')b.quit(1,p or"these values were not equal")end;local function r(j,s,p,t)local u=h.getinfo(3+(t or 0))k.error_handler(u.short_src,u.currentline,i(j),i(s),p)end;k.complain=r;function k.asserteq(j,s,v,t)local w=j==s;if not w then w=a.deepcompare(j,s,true,v)end;if not w then r(j,s,nil,t)end end;function k.assertmatch(x,y,t)if not x:match(y)then r(x,y,"these strings did not match",t)end end;function k.assertraise(z,A,t)local B,q;if type(z)=='table'then B,q=pcall(e(z))else B,q=pcall(z)end;if B or q:match(A)==nil then r(q,A,"these errors did not match",t)end end;function k.asserteq2(C,D,E,F,t)if C~=E then r(C,E,nil,t)end;if D~=F then r(D,F,nil,t)end end;local G={unpack=e}G.__index=G;function G.__tostring(self)local H={}for u=1,self.n do local I=self[u]H[u]=type(I)=='string'and('%q'):format(I)or tostring(I)end;return'tuple('..table.concat(H,', ')..')'end;function G.__eq(J,K)if J.n~=K.n then return false end;for u=1,J.n do if J[u]~=K[u]then return false end end;return true end;function G.__len(self)return self.n end;function k.tuple(...)return setmetatable(f(...),G)end;function k.timer(p,L,M,...)local N=g()for u=1,L do M(...)end;b.printf("%s: took %7.2f sec\n",p,g()-N)end;return k

6
extern/lualibs/pl/text.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/text.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=string.gsub;local b,c=table.concat,table.insert;local d=require'pl.utils'local e,f,g=d.bind1,d.split,d.assert_arg;local h=require'pl.types'.is_callable;local i=d.unpack;local j={}local function k(l)return setmetatable(l,require('pl.List'))end;local function m(n)return n:gsub('^%s+','')end;local function o(n)return m(n):gsub('%s+$','')end;local function p(q,r)return k(f(q,r))end;local function s(t,u,...)local v={}for w=1,#u do v[w]=t(u[w],...)end;return v end;local function x(q,y)local z=p(q,'\n')return b(s(e('..',y),z),'\n')..'\n'end;function j.indent(q,A,B)g(1,q,'string')g(2,A,'number')return x(q,string.rep(B or' ',A))end;function j.dedent(q)g(1,q,'string')local z=p(q,'\n')local C,D=(#z>0 and z[1]or''):find('^%s*')z=s(string.sub,z,D+1)return b(z,'\n')..'\n'end;function j.wrap(q,E)g(1,q,'string')E=E or 70;q=q:gsub('\n',' ')local w,F=1;local G,H={}while w<#q do F=w+E;if q:find("[%w']",F)then F=q:find('%W',F+1)end;H=q:sub(w,F)w=w+#H;c(G,o(H))end;return k(G)end;function j.fill(q,E)return b(j.wrap(q,E),'\n')..'\n'end;local I={}j.Template=I;I.__index=I;setmetatable(I,{__call=function(J,K)return I.new(K)end})function I.new(K)g(1,K,'string')local v={}v.tmpl=K;setmetatable(v,I)return v end;local function L(q,M,N)local O;if h(M)then O=M else function O(t)local q=M[t]if not q then if N then return t else error("not present in table "..t)end else return q end end end;local v=a(q,'%${([%w_]+)}',O)return a(v,'%$([%w_]+)',O)end;function I:substitute(M)g(1,M,'table')return L(self.tmpl,M,false)end;function I:safe_substitute(M)g(1,M,'table')return L(self.tmpl,M,true)end;function I:indent_substitute(M)g(1,M,'table')if not self.strings then self.strings=p(self.tmpl,'\n')end;local function O(H)return H:gsub('(%s*)%$([%w_]+)',function(y,t)local P;local q=M[t]if not q then error("not present in table "..t)end;if getmetatable(q)==I then P=q;q=q.tmpl else q=tostring(q)end;if q:find'\n'then q=x(q,y)end;if P then return L(q,M)else return q end end)end;local G=s(O,self.strings)return b(G,'\n')..'\n'end;function j.format_operator()local Q=string.format;local function R(S,...)local T={...}local w=1;for U in S:gmatch('%%.')do if U=='%s'and type(T[w])~='string'then T[w]=tostring(T[w])end;w=w+1 end;return Q(S,i(T))end;local function V(q,u)return q:gsub('%$([%w_]+)',u)end;getmetatable("").__mod=function(W,X)if X==nil then return W elseif type(X)=="table"and getmetatable(X)==nil then if#X==0 then return L(W,X,true)else return R(W,i(X))end elseif type(X)=='function'then return V(W,X)else return R(W,X)end end end;return j

6
extern/lualibs/pl/types.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/types.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a=require'pl.utils'local b=math.ceil;local c=a.assert_arg;local d={}function d.is_callable(e)return type(e)=='function'or getmetatable(e)and getmetatable(e).__call and true end;d.is_type=a.is_type;local f=getmetatable(io.stdout)function d.type(e)local g=type(e)if g=='table'or g=='userdata'then local h=getmetatable(e)if h==f then return'file'elseif h==nil then return g else return h._name or"unknown "..g end else return g end end;function d.is_integer(i)return b(i)==i end;function d.is_empty(j,k)if j==nil then return true elseif type(j)=="table"then return next(j)==nil elseif type(j)=="string"then return j==""or not not k and not not j:find("^%s+$")else return true end end;local function l(m)if type(m)=='table'then return true end;return getmetatable(m)end;function d.is_indexable(m)local h=l(m)if h==true then return true end;return h and h.__len and h.__index and true end;function d.is_iterable(m)local h=l(m)if h==true then return true end;return h and h.__pairs and true end;function d.is_writeable(m)local h=l(m)if h==true then return true end;return h and h.__newindex and true end;local n={yes=true,y=true,["true"]=true,t=true,["1"]=true}local o={boolean=function(j,p,q)return j end,string=function(j,p,q)j=j:lower()if n[j]then return true end;for r,s in ipairs(p or{})do if type(s)=="string"and j==s:lower()then return true end end;return false end,number=function(j,p,q)return j~=0 end,table=function(j,p,q)if q and next(j)~=nil then return true end;return false end}function d.to_bool(j,p,q)local t;if p then c(2,p,"table")end;t=o[type(j)]if t then return t(j,p,q)elseif q and j~=nil then return true end;return false end;return d

6
extern/lualibs/pl/url.lua vendored Normal file
View File

@ -0,0 +1,6 @@
-- Penlight 1.11.0-1 | /lua/pl/url.lua | https://github.com/lunarmodules/Penlight | License: MIT | Minified using https://www.npmjs.com/package/luamin/v/1.0.4
-- Copyright (C) 2009-2016 Steve Donovan, David Manura.
-- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local a={}local function b(c)return string.format("%%%02X",string.byte(c))end;function a.quote(d,e)if type(d)~="string"then return d end;d=d:gsub("\n","\r\n")d=d:gsub("([^A-Za-z0-9 %-_%./])",b)if e then d=d:gsub(" ","+")d=d:gsub("/",b)else d=d:gsub(" ","%%20")end;return d end;local function f(g)return string.char(tonumber(g,16))end;function a.unquote(d)if type(d)~="string"then return d end;d=d:gsub("+"," ")d=d:gsub("%%(%x%x)",f)d=d:gsub("\r\n","\n")return d end;return a

6
extern/lualibs/pl/utils.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/pl/xml.lua vendored Normal file

File diff suppressed because one or more lines are too long

6
extern/lualibs/serpent.lua vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,10 @@
import tkinter as tk
from tkinter import filedialog
from os import getcwd, listdir, path
from typing import Tuple, Union, Optional
import os
import json
import zipfile
#==================================================================#
# Generic Method for prompting for file path
@ -61,6 +63,18 @@ def getdirpath(dir, title):
def storypath(name):
return path.join(path.dirname(path.realpath(__file__)), "stories", name + ".json")
#==================================================================#
# Returns the path (as a string) to the given soft prompt by its filename
#==================================================================#
def sppath(filename):
return path.join(path.dirname(path.realpath(__file__)), "softprompts", filename)
#==================================================================#
# Returns the path (as a string) to the given username by its filename
#==================================================================#
def uspath(filename):
return path.join(path.dirname(path.realpath(__file__)), "userscripts", filename)
#==================================================================#
# Returns an array of dicts containing story files in /stories
#==================================================================#
@ -86,6 +100,119 @@ def getstoryfiles():
list.append(ob)
return list
#==================================================================#
# Checks if the given soft prompt file is valid
#==================================================================#
def checksp(filename: str, model_dimension: int) -> Tuple[Union[zipfile.ZipFile, int], Optional[Tuple[int, int]], Optional[Tuple[int, int]], Optional[bool], Optional['np.dtype']]:
global np
if 'np' not in globals():
import numpy as np
try:
z = zipfile.ZipFile(path.dirname(path.realpath(__file__))+"/softprompts/"+filename)
with z.open('tensor.npy') as f:
# Read only the header of the npy file, for efficiency reasons
version: Tuple[int, int] = np.lib.format.read_magic(f)
shape: Tuple[int, int]
fortran_order: bool
dtype: np.dtype
shape, fortran_order, dtype = np.lib.format._read_array_header(f, version)
assert len(shape) == 2
except:
z.close()
return 1, None, None, None, None
if dtype not in ('V2', np.float16, np.float32):
z.close()
return 2, version, shape, fortran_order, dtype
if shape[1] != model_dimension:
z.close()
return 3, version, shape, fortran_order, dtype
if shape[0] >= 2048:
z.close()
return 4, version, shape, fortran_order, dtype
return z, version, shape, fortran_order, dtype
#==================================================================#
# Returns an array of dicts containing softprompt files in /softprompts
#==================================================================#
def getspfiles(model_dimension: int):
lst = []
os.makedirs(path.dirname(path.realpath(__file__))+"/softprompts", exist_ok=True)
for file in listdir(path.dirname(path.realpath(__file__))+"/softprompts"):
if not file.endswith(".zip"):
continue
z, version, shape, fortran_order, dtype = checksp(file, model_dimension)
if z == 1:
print(f"Browser SP loading error: {file} is malformed or not a soft prompt ZIP file.")
continue
if z == 2:
print(f"Browser SP loading error: {file} tensor.npy has unsupported dtype '{dtype.name}'.")
continue
if z == 3:
print(f"Browser SP loading error: {file} tensor.npy has model dimension {shape[1]} which does not match your model's model dimension of {model_dimension}. This usually means this soft prompt is not compatible with your model.")
continue
if z == 4:
print(f"Browser SP loading error: {file} tensor.npy has {shape[0]} tokens but it is supposed to have less than 2048 tokens.")
continue
assert isinstance(z, zipfile.ZipFile)
try:
with z.open('meta.json') as f:
ob = json.load(f)
except:
ob = {}
z.close()
ob["filename"] = file
ob["n_tokens"] = shape[-2]
lst.append(ob)
return lst
#==================================================================#
# Returns an array of dicts containing userscript files in /userscripts
#==================================================================#
def getusfiles(long_desc=False):
lst = []
os.makedirs(path.dirname(path.realpath(__file__))+"/userscripts", exist_ok=True)
for file in listdir(path.dirname(path.realpath(__file__))+"/userscripts"):
if file.endswith(".lua"):
ob = {}
ob["filename"] = file
description = []
multiline = False
with open(uspath(file)) as f:
ob["modulename"] = f.readline().strip().replace("\033", "")
if ob["modulename"][:2] != "--":
ob["modulename"] = file
else:
ob["modulename"] = ob["modulename"][2:]
if ob["modulename"][:2] == "[[":
ob["modulename"] = ob["modulename"][2:]
multiline = True
ob["modulename"] = ob["modulename"].lstrip("-").strip()
for line in f:
line = line.strip().replace("\033", "")
if multiline:
index = line.find("]]")
if index > -1:
description.append(line[:index])
if index != len(line) - 2:
break
multiline = False
else:
description.append(line)
else:
if line[:2] != "--":
break
line = line[2:]
if line[:2] == "[[":
multiline = True
line = line[2:]
description.append(line.strip())
ob["description"] = "\n".join(description)
if not long_desc:
if len(ob["description"]) > 250:
ob["description"] = ob["description"][:247] + "..."
lst.append(ob)
return lst
#==================================================================#
# Returns True if json file exists with requested save name
#==================================================================#

View File

@ -1,4 +1,16 @@
gensettingstf = [{
gensettingstf = [
{
"uitype": "slider",
"unit": "int",
"label": "Amount to Generate",
"id": "setoutput",
"min": 16,
"max": 512,
"step": 2,
"default": 80,
"tooltip": "Number of tokens the AI should generate. Higher numbers will take longer to generate."
},
{
"uitype": "slider",
"unit": "float",
"label": "Temperature",
@ -48,21 +60,32 @@ gensettingstf = [{
"label": "Repetition Penalty",
"id": "setreppen",
"min": 1.0,
"max": 2.0,
"step": 0.05,
"max": 3.0,
"step": 0.01,
"default": 1.1,
"tooltip": "Used to penalize words that were already generated or belong to the context."
"tooltip": "Used to penalize words that were already generated or belong to the context (Going over 1.2 breaks 6B models)."
},
{
"uitype": "slider",
"unit": "int",
"label": "Amount to Generate",
"id": "setoutput",
"min": 16,
"max": 512,
"step": 2,
"default": 80,
"tooltip": "Number of tokens the AI should generate. Higher numbers will take longer to generate."
"label": "Rep Penalty Range",
"id": "setreppenrange",
"min": 0,
"max": 4096,
"step": 4,
"default": 0,
"tooltip": "Repetition penalty range. If set higher than 0, only applies repetition penalty to the last few tokens of your story rather than applying it to the entire story. This slider controls the amount of tokens at the end of your story to apply it to."
},
{
"uitype": "slider",
"unit": "float",
"label": "Rep Penalty Slope",
"id": "setreppenslope",
"min": 0.0,
"max": 10.0,
"step": 0.1,
"default": 0.0,
"tooltip": "Repetition penalty slope. If BOTH this setting and Rep Penalty Range are set higher than 0, will use sigmoid interpolation to apply repetition penalty more strongly on tokens that are closer to the end of your story. This setting controls the tension of the sigmoid curve; higher settings will result in the repetition penalty difference between the start and end of your story being more apparent. Setting this to 1 uses linear interpolation; setting this to 0 disables interpolation."
},
{
"uitype": "slider",
@ -97,6 +120,17 @@ gensettingstf = [{
"default": 3,
"tooltip": "Number of historic actions to scan for W Info keys."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Auto Save",
"id": "autosave",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "Whether the game is saved after each action."
},
{
"uitype": "toggle",
"unit": "bool",
@ -118,7 +152,63 @@ gensettingstf = [{
"step": 1,
"default": 0,
"tooltip": "Turn this on if you are playing a Choose your Adventure model."
}]
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Chat Mode",
"id": "setchatmode",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "This mode optimizes KoboldAI for chatting."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Dynamic WI Scan",
"id": "setdynamicscan",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "Scan the AI's output for world info keys as it's generating the output."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "No Prompt Generation",
"id": "setnopromptgen",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "When enabled the AI does not generate when you enter the prompt, instead you need to do an action first."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Random Story Persist",
"id": "setrngpersist",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "When enabled, the Memory text box in the Random Story dialog will be prefilled by default with your current story's memory instead of being empty."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "No Genmod",
"id": "setnogenmod",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "Disables userscript generation modifiers."
}
]
gensettingsik =[{
"uitype": "slider",
@ -186,6 +276,17 @@ gensettingsik =[{
"default": 3,
"tooltip": "Number of historic actions to scan for W Info keys."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Auto Save",
"id": "autosave",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "Whether the game is saved after each action."
},
{
"uitype": "toggle",
"unit": "bool",
@ -207,7 +308,41 @@ gensettingsik =[{
"step": 1,
"default": 0,
"tooltip": "Turn this on if you are playing a Choose your Adventure model."
}]
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Chat Mode",
"id": "setchatmode",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "This mode optimizes KoboldAI for chatting."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "No Prompt Generation",
"id": "setnopromptgen",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "When enabled the AI does not generate when you enter the prompt, instead you need to do an action first."
},
{
"uitype": "toggle",
"unit": "bool",
"label": "Random Story Persist",
"id": "setrngpersist",
"min": 0,
"max": 1,
"step": 1,
"default": 0,
"tooltip": "When enabled, the Memory text box in the Random Story dialog will be prefilled by default with your current story's memory instead of being empty."
}
]
formatcontrols = [{
"label": "Trim incomplete sentences",
@ -228,4 +363,9 @@ formatcontrols = [{
"label": "Add sentence spacing",
"id": "frmtadsnsp",
"tooltip": "If the last action ended with punctuation, add a space to the beginning of the next action."
}]
},
{
"label": "Single Line",
"id": "singleline",
"tooltip": "Only allows the AI to output anything before the enter"
}]

View File

@ -1,8 +1,8 @@
@echo off
title KoboldAI Runtime Installer (MicroMamba)
echo Please choose one of the following transformers options
echo 1. Finetuneanon Transformers (Best for GPU users)
echo 2. Official Transformers (Best for CPU users)
echo 1. Official Transformers (Recommended)
echo 2. Finetune Transformers (For old 6B models)
echo.
echo Errors? Rerun this as admin so it can add the needed LongPathsEnabled registery tweak.
echo Installer failed or crashed? Run it again so it can continue.
@ -12,8 +12,7 @@ echo.
SET /P B=Type the number of the desired option and then press ENTER:
Reg add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v "LongPathsEnabled" /t REG_DWORD /d "1" /f 2>nul
%~d0
cd %~dp0
cd /D %~dp0
if exist miniconda3\ (
echo Delete existing installation?
@ -28,7 +27,7 @@ IF %D%==1 rmdir /s /q miniconda3
:Mode
echo Which installation mode would you like?
echo 1. Temporary Drive Letter (Mounts the folder as drive K:, more stable and portable)
echo 1. Temporary Drive Letter (Mounts the folder as drive B:, more stable and portable)
echo 2. Subfolder (Traditional method, can't run in folder paths that contain spaces)
echo.
SET /P M=Type the number of the desired option and then press ENTER:
@ -39,25 +38,31 @@ GOTO MODE
:drivemap
echo 1 > loader.settings
subst K: /D >nul
echo 3 > loader.settings
subst B: /D >nul
mkdir miniconda3
subst K: miniconda3
copy umamba.exe K:\umamba.exe
K:
umamba.exe create -r K:\python\ -n base
IF %B%==1 umamba.exe install --no-shortcuts -r K:\python\ -n base -f "%~dp0\environments\finetuneanon.yml" -y
IF %B%==2 umamba.exe install --no-shortcuts -r K:\python\ -n base -f "%~dp0\environments\huggingface.yml" -y
umamba.exe -r K:\ clean -a -y
subst K: /d
subst B: miniconda3
SET TEMP=B:\
SET TMP=B:\
copy umamba.exe B:\umamba.exe
B:
umamba.exe create -r B:\python\ -n base
IF %B%==1 umamba.exe install --no-shortcuts -r B:\python\ -n base -f "%~dp0\environments\huggingface.yml" -y --always-copy
IF %B%==2 umamba.exe install --no-shortcuts -r B:\python\ -n base -f "%~dp0\environments\finetuneanon.yml" -y --always-copy
umamba.exe -r B:\ clean -a -y
rd B:\Python\pkgs /S /Q
subst B: /d
pause
exit
:subfolder
echo 2 > loader.settings
SET TEMP=%~DP0MINICONDA3
SET TMP=%~DP0MINICONDA3
umamba.exe create -r miniconda3\ -n base
IF %B%==1 umamba.exe install --no-shortcuts -r miniconda3 -n base -f environments\finetuneanon.yml -y
IF %B%==2 umamba.exe install --no-shortcuts -r miniconda3 -n base -f environments\huggingface.yml -y
IF %B%==1 umamba.exe install --no-shortcuts -r miniconda3 -n base -f environments\huggingface.yml -y --always-copy
IF %B%==2 umamba.exe install --no-shortcuts -r miniconda3 -n base -f environments\finetuneanon.yml -y --always-copy
umamba.exe clean -a -y
rd miniconda3\Python\pkgs /S /Q
pause
exit

View File

@ -4,6 +4,7 @@ TITLE Jupyter for KoboldAI Runtime
SET /P M=<loader.settings
IF %M%==1 GOTO drivemap
IF %M%==2 GOTO subfolder
IF %M%==3 GOTO drivemap_B
:subfolder
umamba.exe install --no-shortcuts -r miniconda3 -n base -c conda-forge jupyter
@ -17,4 +18,12 @@ umamba.exe install --no-shortcuts -r K:\python\ -n base -c conda-forge jupyter
call K:\python\condabin\activate
jupyter notebook
subst K: /D
cmd /k
:drivemap_B
subst B: miniconda3 >nul
umamba.exe install --no-shortcuts -r B:\python\ -n base -c conda-forge jupyter
call B:\python\condabin\activate
jupyter notebook
subst B: /D
cmd /k

View File

@ -1,19 +1,35 @@
@echo off
%~d0
cd %~dp0
cd /D %~dp0
TITLE KoboldAI - Server
SET /P M=<loader.settings
IF %M%==1 GOTO drivemap
IF %M%==2 GOTO subfolder
IF %M%==3 GOTO drivemap_B
:subfolder
ECHO Runtime launching in subfolder mode
SET TEMP=%~DP0MINICONDA3
SET TMP=%~DP0MINICONDA3
call miniconda3\condabin\activate
python aiserver.py %*
cmd /k
:drivemap
ECHO Runtime launching in K: drive mode
subst K: miniconda3 >nul
SET TEMP=K:\
SET TMP=K:\
call K:\python\condabin\activate
python aiserver.py %*
subst K: /D
cmd /k
:drivemap_B
ECHO Runtime launching in B: drive mode
subst B: miniconda3 >nul
SET TEMP=B:\
SET TMP=B:\
call B:\python\condabin\activate
python aiserver.py %*
subst B: /D
cmd /k

45
play.ipynb Normal file
View File

@ -0,0 +1,45 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "KoboldAI Jupyter",
"provenance": [],
"authorship_tag": "ABX9TyMDTbAhtDnKJa+aIEaQjpsL"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "TPU"
},
"cells": [
{
"cell_type": "markdown",
"source": [
"# KoboldAI Launcher for generic Jupyter Notebooks\n",
"This notebook is meant as a way to easily launch KoboldAI on existing Jupyter instances that already have KoboldAI installed (For example a custom Saturn Cloud or Paperspace instance).\n",
"\n",
"For Google Colab please check out our Google Colab edition available at : https://colab.research.google.com/github/KoboldAI/KoboldAI-Client/blob/main/colab/TPU.ipynb"
],
"metadata": {
"id": "hMRnGz42Xsy3"
}
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "40B1QvI3Xv02"
},
"outputs": [],
"source": [
"!pip install -r requirements.txt\n",
"!python3 aiserver.py --remote"
]
}
]
}

164
readme.md
View File

@ -4,13 +4,13 @@ This is a browser-based front-end for AI-assisted writing with multiple local &
## Multiple ways to play
Stories can be played like a Novel, or played like a text adventure game with an easy toggle to change between the two gameplay styles. This makes KoboldAI both a writing assistant and a game. The way you play and how good the AI will be depends on the model or service you decide to use. No matter if you want to use the free, fast power of Google Colab, your own high end graphics card, an online service you have an API key for (Like OpenAI or Inferkit) or if you rather just run it slower on your CPU you will be able to find a way to use KoboldAI that works for you.
Stories can be played like a Novel, a text adventure game or used as a chatbot with an easy toggles to change between the multiple gameplay styles. This makes KoboldAI both a writing assistant, a game and a platform for so much more. The way you play and how good the AI will be depends on the model or service you decide to use. No matter if you want to use the free, fast power of Google Colab, your own high end graphics card, an online service you have an API key for (Like OpenAI or Inferkit) or if you rather just run it slower on your CPU you will be able to find a way to use KoboldAI that works for you.
### Adventure mode
By default KoboldAI will run in a generic mode optimized for writing, but with the right model you can play this like AI Dungeon without any issues. You can enable this in the settings and bring your own prompt, try generating a random prompt or download one of the prompts available at [prompts.aidg.club](https://prompts.aidg.club) .
The gameplay will be slightly different than the gameplay in AI Dungeon because we adopted the style of the Unleashed fork, giving you full control over all the characters because we do not automatically adapt your sentences behind the scenes. This means you can more reliably control characters that are not you.
The gameplay will be slightly different than the gameplay in AI Dungeon because we adopted the Type of the Unleashed fork, giving you full control over all the characters because we do not automatically adapt your sentences behind the scenes. This means you can more reliably control characters that are not you.
As a result of this what you need to type is slightly different, in AI Dungeon you would type ***take the sword*** while in KoboldAI you would type it like a sentence such as ***You take the sword*** and this is best done with the word You instead of I.
@ -23,22 +23,64 @@ If you want to do this with your friends we advice using the main character as Y
If you want to use KoboldAI as a writing assistant this is best done in the regular mode with a model optimized for Novels. These models do not make the assumption that there is a You character and focus on Novel like writing. For writing these will often give you better results than Adventure or Generic models. That said, if you give it a good introduction to the story large generic models like 6B can be used if a more specific model is not available for what you wish to write. You can also try to use models that are not specific to what you wish to do, for example a NSFW Novel model for a SFW story if a SFW model is unavailable. This will mean you will have to correct the model more often because of its bias, but can still produce good enough results if it is familiar enough with your topic.
### Chatbot Mode
In chatbot mode you can use a suitable model as a chatbot, this mode automatically adds your name to the beginning of the sentences and prevents the AI from talking as you. To use it properly you must write your story opening as both characters in the following format (You can use your own text) :
``` ChatBot Opening Example
Bot : Hey!
You : Hey Boyname, how have you been?
Bot : Been good! How about you?
You : Been great to, excited to try out KoboldAI
Bot : KoboldAI is really fun!
You : For sure! What is your favorite game?
```
Its recommended to have your own input be the last input, especially in the beginning its possible that the AI mixes up the names. In that case either retry or manually correct the name. This behavior improves as the chat progresses. Some models may swap names if they are more familiar with a different name that is similar to the name you defined for the bot. In that case you can either do the occasional manual correction or choose a name for your chatbot that the AI likes better.
This mode works the best on either a Generic model or a chatbot model specifically designed for it, some models like the AvrilAI model are instead designed to be used in Adventure mode and do not conform to the format above. These models typically ship with adventure mode enabled by default and should not be switched over to chatbot mode.
Novel or Adventure models are not recommended for this feature but might still work but can derail away from the conversation format quickly.
## Play KoboldAI online for free on Google Colab (The easiest way to play)
We provide multiple ready made versions to get you going, click on the name for a link to the specific version. These run entirely on Google's Servers and will automatically upload saves to your Google Drive if you choose to manually save a story. Each version has slightly different instructions on how to use them (Many need some space on your google drive to run, others may need some manual steps) that are listed on the page.
If you would like to play KoboldAI online for free on a powerful computer you can use Google Colaboraty. We provide two editions, a TPU and a GPU edition with a variety of models available. These run entirely on Google's Servers and will automatically upload saves to your Google Drive if you choose to save a story (Alternatively, you can choose to download your save instead so that it never gets stored on Google Drive). Detailed instructions on how to use them are at the bottom of the Colab's.
TPU editions work on any configuration of TPU Google gives out at the time of writing. GPU editions are subject to a GPU lottery and may crash on launch if you are unlucky (Especially if a lot of users are using up the good GPU's or you have been using Colab often).
Each edition features different models and requires different hardware to run, this means that if you are unable to obtain a TPU or a GPU you might still be able to use the other version. The models you can use are listed underneath the edition. To open a Colab click the big link featuring the editions name.
[Click here to open the Recommended version](https://henk.tech/colabkobold)
### [TPU Edition Model Descriptions](https://colab.research.google.com/github/KoboldAI/KoboldAI-Client/blob/main/colab/TPU.ipynb)
| Model | Size | Type | Drive Space | Description |
| ------------------------------ | ------ | --------- | ----------- | ------------------------------------------------------------ |
| Skein 6B by VE_FORBDRYDERNE | 6B TPU | Hybrid | 0 GB | Skein is our flagship 6B model, it is a hybrid between a Adventure model and a Novel model. Best used with either Adventure mode or the You Bias userscript enabled. Skein has been trained on high quality Novels along with CYOA adventure stories and is not as wackey as the Adventure model. It also has tagging support. |
| Adventure 6B by VE_FORBRYDERNE | 6B TPU | Adventure | 0 GB | Adventure is a 6B model designed to mimick the behavior of AI Dungeon. It is exclusively for Adventure Mode and can take you on the epic and wackey adventures that AI Dungeon players love. It also features the many tropes of AI Dungeon as it has been trained on very similar data. It must be used in second person (You). |
| Lit 6B by Haru | 6B TPU | NSFW | 8 GB / 12 GB | Lit is a great NSFW model trained by Haru on both a large set of Literotica stories and high quality novels along with tagging support. Creating a high quality model for your NSFW stories. This model is exclusively a novel model and is best used in third person. |
| Generic 6B by EleutherAI | 6B TPU | Generic | 10 GB / 12 GB | GPT-J-6B is what all other models are based on, if you need something that has no specific bias towards any particular subject this is the model for you. Best used when the other models are not suitable for what you wish to do. Such as homework assistance, blog writing, coding and more. It needs more hand holding than other models and is more prone to undesirable formatting changes. |
| C1 6B by Haru | 6B TPU | Chatbot | 8 GB / 12 GB | C1 has been trained on various internet chatrooms, it makes the basis for an interesting chatbot model and has been optimized to be used in the Chatmode. |
### [GPU Edition Colab](https://colab.research.google.com/github/KoboldAI/KoboldAI-Client/blob/main/colab/GPU.ipynb)
| Model | Size | Type | Description |
| ------------------------------------------------------------ | -------- | ---------- | ------------------------------------------------------------ |
| [GPT-Neo-2.7B-Picard](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Picard) by Mr Seeker | 2.7B GPU | Novel | Picard is a model trained for SFW Novels based on GPT-Neo-2.7B. It is focused on Novel Type writing without the NSFW bias. While the name suggests a sci-fi model this model is designed for Novels of a variety of genre's. It is meant to be used in KoboldAI's regular mode. |
| [GPT-Neo-2.7B-AID](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-AID) by melastacho | 2.7B GPU | Adventure | Also know as Adventure 2.7B this is a clone of the AI Dungeon Classic model and is best known for the epic wackey adventures that AI Dungeon Classic players love. |
| [GPT-Neo-2.7B-Horni-LN](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Horni-LN) by finetune | 2.7B GPU | Novel | This model is based on GPT-Neo-2.7B-Horni and retains its NSFW knowledge, but was then further biased towards SFW novel stories. If you seek a balance between a SFW Novel model and a NSFW model this model should be a good choice. |
| [GPT-Neo-2.7B-Horni](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Horni) by finetune | 2.7B GPU | NSFW | This model is tuned on Literotica to produce a Novel Type model biased towards NSFW content. Can still be used for SFW stories but will have a bias towards NSFW content. It is meant to be used in KoboldAI's regular mode. |
| [GPT-Neo-2.7B-Shinen](https://huggingface.co/KoboldAI/GPT-Neo-2.7B-Shinen) by Mr Seeker | 2.7B GPU | NSFW | Shinen is an alternative to the Horni model designed to be more explicit. If Horni is to tame for you shinen might produce better results. While it is a Novel model it is unsuitable for SFW stories due to its heavy NSFW bias. Shinen will not hold back. It is meant to be used in KoboldAI's regular mode. |
| [GPT-Neo-2.7B](https://huggingface.co/EleutherAI/gpt-neo-2.7B) by EleutherAI | 2.7B GPU | Generic | This is the base model for all the other 2.7B models, it is best used when you have a use case that we have no other models available for, such as writing blog articles or programming. It can also be a good basis for the experience of some of the softprompts if your softprompt is not about a subject the other models cover. |
### Model Types
| Type | Description |
| --------- | ------------------------------------------------------------ |
| Novel | For regular story writing, not compatible with Adventure mode or other specialty modes. |
| NSFW | Indicates that the model is strongly biased towards NSFW content and is not suitable for children, work environments or livestreaming. Most NSFW models are also Novel models in nature. |
| Adventure | These models are excellent for people willing to play KoboldAI like a Text Adventure game and are meant to be used with Adventure mode enabled. Even if you wish to use it as a Novel Type model you should always have Adventure mode on and set it to story. These models typically have a strong bias towards the use of the word You and without Adventure mode enabled break the story flow and write actions on your behalf. |
| Chatbot | These models are specifically trained for chatting and are best used with the Chatmode enabled. Typically trained on either public chatrooms or private chats. |
| Hybrid | Hybrid models are a blend between different Types, for example they are trained on both Novel stories and Adventure stories. These models are great variety models that you can use for multiple different playTypes and modes, but depending on your usage you may need to enable Adventure Mode or the You bias (in userscripts). |
| Generic | Generic models are not trained towards anything specific, typically used as a basis for other tasks and models. They can do everything the other models can do, but require much more handholding to work properly. Generic models are an ideal basis for tasks that we have no specific model for, or for experiencing a softprompt in its raw form. |
| Version | Model | Size | Style | Description |
| ------------------------------------------------------------ | ------------------------------------------------------------ | -------- | --------------- | ------------------------------------------------------------ |
| [Adventure 6B](https://colab.research.google.com/drive/1vdAsD0xCc_YsAXqBUxb_QAwPOXkFJtxm?usp=sharing#sandboxMode=true) | [gpt-j-6b-adventure-jax](https://wandb.ai/ve-forbryderne/adventure/runs/carol-data/files/models) by ve_forbryderne (Download the -hf version if you plan to run this locally) | 6B TPU | Adventure | This is the Recommended version for AI Dungeon players, this is effectively a Free Griffin but with more control. This Colab edition provides better memory than Griffin would have given you, allowing for a more coherent experience. And while it will still generate characters like The Great Litch Lord that AI Dungeon players are familiar with it was trained on stories beyond AI Dungeon and is more balanced in its approaches. This is a TPU edition so it can fit a lot in memory |
| [Skein](https://colab.research.google.com/drive/1ZAKgkSyyfiZN87npKYaRM8vL4OF2Btfg?usp=sharing#sandboxMode=true) | gpt-j-6b-skein-jax by ve_forbryderne (Download the -hf version if you plan to run this locally) | 6B TPU | Novel/Adventure | Skein is a hybrid between a Novel model and the Adventure model. Because of this it needs a bit more context about the writing style (Needing a few retries in the random story generator if you use this). It was trained on both Light Novels and choose your own adventure stories along side extra information to help it understand story themes better. It is recommended to play this with Adventure mode enabled to prevent it from doing "Actions" even if you wish to use it for Novel writing. If you wish to use it for Novel writing you can do this by toggling the input to Story. |
| [Generic 6B TPU](https://colab.research.google.com/drive/1pG9Gz9PrqklNBESPNaXvfctMVnvwf_Q8#forceEdit=true&sandboxMode=true&scrollTo=jcxnaOk5Th4x) | [Original GPT-6-JAX Slim](https://the-eye.eu/public/AI/GPT-J-6B/step_383500_slim.tar.gz) (Requires a TPU and does not work local) | 6B TPU | Novel | The recommended model if you want a generic experience. This model is not optimized for anything in particular and works best when you give it a longer introduction. Make sure to include examples for the AI to learn from and write the first part of the story entirely yourself. Then it should be able to learn from your style and continue from there. Very sensitive to a high temp because it knows webpages and code, so when configured incorrectly it will easily end a story with 'Rate my blogpost, follow me on twitter' and the likes. |
| [Horni](https://colab.research.google.com/drive/1QwjkK_JeK9aYEkyM_6nrJXQARFMnBDmG?usp=sharing#sandboxMode=true) (Formerly Novel/NSFW) | [GPT-Neo-2.7B-Horni](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-horni.7z) by finetune | 2.7B GPU | Novel | One of the oldest models in our collection, tuned on Literotica to produce a Novel style model optimized towards NSFW content. Can still be used for SFW stories but will have a bias towards NSFW content. Because this is an older 2.7B model it is only compatible as a GPU instance. Most GPU's in Colab are powerful enough to run this well but it will crash if you get something weak like a Nvidia P7. |
| [Picard](https://colab.research.google.com/drive/1VNVKtbPaTcmkQzy8bEQkd9SUiUJBdbEL?usp=sharing#sandboxMode=true) | [Picard](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-picard.7z) by Mr Seeker | 2.7B GPU | Novel | Picard is a model trained for SFW Novels based on GPT-Neo-2.7B. It is focused on Novel style writing without the NSFW bias. While the name suggests a sci-fi model this model is designed for Novels of a variety of genre's. Most GPU's in Colab are powerful enough to run this well but it will crash if you get something weak like a Nvidia P7. |
| [Shinen](https://colab.research.google.com/drive/1-7Lkj-np2DaSnmq1OdPYkel6W2rh4E-0?usp=sharing#sandboxMode=true) | [Shinen](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-shinen.7z) by Mr Seeker | 2.7B GPU | Novel | Shinen is an alternative to the Horni model designed to be more explicit. If Horni is to tame for you shinen might produce better results. While it is a Novel model it is unsuitable for SFW stories due to its heavy NSFW bias. Shinen will not hold back. Most GPU's in Colab are powerful enough to run this well but it will crash if you get something weak like a Nvidia P7. |
## Install KoboldAI on your own computer
@ -46,16 +88,25 @@ KoboldAI has a large number of dependencies you will need to install on your com
### Downloading the latest version of KoboldAI
KoboldAI is a rolling release on our github, the code you see is also the game. The easiest way to download the game is by clicking on the green Code button at the top of the page and clicking Download ZIP.
KoboldAI is a rolling release on our github, the code you see is also the game. You can the software by clicking on the green Code button at the top of the page and clicking Download ZIP.
### Installing KoboldAI on Windows 10 or higher using the KoboldAI Runtime Installer
The easiest way for Windows users is to use the [offline installer](https://sourceforge.net/projects/koboldai/files/latest/download) below.
### Installing KoboldAI offline bundle on Windows 7 or higher using the KoboldAI Offline Installer (Easiest)
1. [Download the latest offline installer from here](https://sourceforge.net/projects/koboldai/files/latest/download)
2. Run the installer to place KoboldAI on a location of choice, KoboldAI is portable software and is not bound to a specific harddrive. (Because of long paths inside our dependencies you may not be able to extract it many folders deep).
3. Update KoboldAI to the latest version with update-koboldai.bat if desired.
4. Use KoboldAI offline using play.bat or remotely with remote-play.bat
### Installing KoboldAI Github release on Windows 10 or higher using the KoboldAI Runtime Installer
1. Extract the .zip to a location you wish to install KoboldAI, you will need roughly 20GB of free space for the installation (this does not include the models).
2. Open install_requirements.bat as administrator.
3. Choose either the Finetuneanon or the Regular version of transformers (Finetuneanon works better for GPU players but breaks CPU mode, only use this version if you have a modern Nvidia GPU with enough VRAM for the model you wish to run).
4. You will now be asked to choose the installation mode, we **strongly** recommend the Temporary K: drive option for anyone who does not already have a K: drive on their computer. This option eliminates most installation issues and also makes KoboldAI portable. The K: drive will be gone after a reboot and will automatically be recreated each time you play KoboldAI.
2. Open install_requirements.bat as **administrator**.
3. Choose the regular version of Transformers (Option 1), finetuneanon is depreciated and no longer recommended.
4. You will now be asked to choose the installation mode, we **strongly** recommend the Temporary B: drive option. This option eliminates most installation issues and also makes KoboldAI portable. The B: drive will be gone after a reboot and will automatically be recreated each time you play KoboldAI.
5. The installation will now automatically install its requirements, some stages may appear to freeze do not close the installer until it asks you to press a key. Before pressing a key to exit the installer please check if errors occurred. Most problems with the game crashing are related to installation/download errors. Disabling your antivirus can help if you get errors.
6. Use play.bat to play the game.
6. Use play.bat to start KoboldAI.
### Manual installation / Linux / Mac
@ -63,20 +114,13 @@ We can not provide a step by step guide for manual installation due to the vast
If you would like to manually install KoboldAI you will need some python/conda package management knowledge to manually do one of the following steps :
1. Use our bundled environments files to install your own conda environment, this should also automatically install CUDA.
2. If you do not want to use conda install the requirements listed in requirements.txt and make sure that CUDA is properly installed.
3. Adapt and use our bundled docker files to create your own KoboldAI docker instance.
1. Use our bundled environments files to install your own conda environment, this should also automatically install CUDA (Recommended, you can get Miniconda from https://docs.conda.io/en/latest/miniconda.html#latest-miniconda-installer-links). The recommended configuration is huggingface.yml for CUDA users and rocm.yml for ROCm users.
2. If you have a working copy of Docker for either CUDA or ROCm try play-cuda.sh or play-rocm.sh to launch the docker versions. In this case the installation is mostly automatic.
3. If conda is proving difficult you could also look inside requirements.txt for the required dependencies and try to install them yourself. This will likely be a mixture of pip and your native package manager, just installing our requirements.txt is not recommended since to speed things up we do not force any version changes. For local installations definitely prioritize conda as that is a better way for us to enforce you have the latest compatible versions.
### Using an AMD GPU on Linux
### AMD GPU's
AMD GPU's have terrible compute support, this will currently not work on Windows and will only work for a select few Linux GPU's. [You can find a list of the compatible GPU's here](https://github.com/RadeonOpenCompute/ROCm#Hardware-and-Software-Support). Any GPU that is not listed is guaranteed not to work with KoboldAI and we will not be able to provide proper support on GPU's that are not compatible with the versions of ROCm we require. This guide requires that you already followed the appropriate steps to configure both [ROCm](https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html) and [Docker]([Install Docker Engine | Docker Documentation](https://docs.docker.com/engine/install/)) and is for advanced users only.
1. Make sure you have installed both the latest version of [Docker](https://docs.docker.com/engine/install/), docker-compose and [ROCm](https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html) on your system and have configured your user to have access to the Docker group (Sudo can interfere with the dialogues).
2. Assign our play-rocm.sh file execute permissions (chmod +x play-rocm.sh).
3. Run our play-rocm.sh file, it should now automatically install and create a suitable runtime for KoboldAI with AMD support and directly run the game afterwards. For X11 forwarding support you will need to run this as sudo at least once at the local machine. Otherwise use the command line options to load KoboldAI if you are playing this remotely.
4. Currently models automatically downloaded by the game are discarded on exit in the Docker version, it is strongly recommended that you manually download a model and load this using the custom model features to prevent unnecessary downloads.
If you hit strange errors with the ROCm version where it fails on the installation be sure you are running the latest version of Docker and Docker-compose. Some versions will fail on the root elevation or lack the appropriate formats.
AMD GPU's have terrible compute support, this will currently not work on Windows and will only work for a select few Linux GPU's. [You can find a list of the compatible GPU's here](https://github.com/RadeonOpenCompute/ROCm#Hardware-and-Software-Support). Any GPU that is not listed is guaranteed not to work with KoboldAI and we will not be able to provide proper support on GPU's that are not compatible with the versions of ROCm we require.
### Troubleshooting
@ -100,50 +144,74 @@ Like with Python version conflicts we recommend uninstalling CUDA from your syst
If you do not have a suitable Nvidia GPU that can run on CUDA10 or Higher and that supports Compute Capabilities 5.0 or higher we can not help you get the game detected on the GPU. Unless you are following our ROCm guide with a compatible AMD GPU.
#### "LayerNormKernelImpl" not implemented for 'Half'
This error only occurs when you are trying to run a model on the CPU mode while Finetuneanon's version of Transformers is installed. If you want/need to use the CPU mode use the install_requirements.bat file with the Official Transformers option and choose to delete all existing files.
#### vocab.json / config.json is not found error
If you get these errors you either did not select the correct folder for your custom model or the model you have downloaded is not (yet) compatible with KoboldAI. There exist a few models out there that are compatible and provide a pytorch_model.bin file but do not ship all the required files. In this case try downloading a compatible model of the same kind (For example another GPT-Neo if you downloaded a GPT-Neo model) and replace the pytorch_model.bin file with the one you are trying to run. Chances are this will work fine.
## KoboldAI Compatible Models
The models listed in the KoboldAI menu are generic models meant to easily get you going based on the Huggingface service. For higher quality models and fully offline use you will need to manually download a suitable model for your style. These are some of the models the community has available for you all tested to be compatible with KoboldAI and will be the brain of the AI.
Most of the high quality models have been integrated in the menu, these models have their download link removed since the easiest way to obtain them is to run them directly from the menu. KoboldAI will automatically download and convert the models to a offline format for later use.
If you have old 6B versions which end in -hf they will no longer be compatible with the newer versions of transformers and will no longer behave correctly. It is highly recommended that you install the official version of transformers (offline installers for KoboldAI contain this version by default) and redownload these models from the menu to get compatible versions. If you have very limited internet we will for a limited time also offer finetuneanon's fork in the install_requirements.bat file, when using that option you will not be able to use the 6B models in our main menu so definitely upgrade when your internet allows.
The VRAM requirements amounts are the recommended amounts for fast smooth play, playing with lower VRAM is possible but then you may need to either lower the amount of tokens in the settings, or you may need to put less layers on your GPU causing a significant performance loss.
**For CPU players and during the loading regular RAM usage is double of what we list here.**
| **Model** | Type | **(V)RAM** | Repetition Penalty | Description |
| ------------------------------------------------------------ | --------------------------------- | ---------- | ------------------ | ------------------------------------------------------------ |
| [gpt-j-6b-adventure-jax-hf](https://api.wandb.ai/files/ve-forbryderne/adventure/carol-data/models/gpt-j-6b-adventure-hf.7z) | Adventure / 6B / Neo Custom | 16GB | 1.2 | This model has been trained on the AI Dungeon set with additional stories thrown in. It is the most well rounded AI Dungeon like model and can be seen as an improved Griffin. If you wish to play KoboldAI like AI Dungeon this is the one to pick. It works great with the random story generator if your temp is 0.5 . |
| [gpt-j-6b-skein-jax-hf](https://api.wandb.ai/files/ve-forbryderne/skein/files/gpt-j-6b-skein-hf.7z) | Adventure Novel / 6B / Neo Custom | 16GB | 1.1 | A hybrid of a few different datasets aimed to create a balanced story driven experience. If the adventure model is to focused on its own adventures and you want something a bit more generic this is the one for you. This model understands tags and adventure mode but can also be used as a writing assistant for your Novel. Its a good middle ground between a finetuned model and a generic model. It needs more guidance than some of the other models do making it less suitable for random story generation, but still focusses on writing rather than websites or code. If you want to use a model for existing story idea's this is a great choice. |
| [gpt-neo-2.7B-aid](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-aid.7z) | Adventure / 2.7B / Neo Custom | 8GB | 2.0 | This is one of the closest replications of the original AI Dungeon Classic model. Tuned on the same data that got uploaded alongside AI Dungeon. In KoboldAI we noticed this model performs better than the conversions of the original AI Dungeon model. It has all the traits you expect of AI Dungeon Classic while not having as many artifacts as this model was trained specifically for KoboldAI. Must be played with Adventure mode enabled to prevent it from doing actions on your behalf. |
| [gpt-neo-2.7B-horni](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-horni.7z) | Novel / 2.7B / Neo Custom | 8GB | 2.0 | One of the best novel models available for 2.7B focused on NSFW content. This model trains the AI to write in a story like fashion using a very large collection of Literotica stories. It is one of the original finetuned models for 2.7B. |
| [gpt-neo-2.7B-horni-ln](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-horni-ln.7z) | Novel / 2.7B / Neo Custom | 8GB | 2.0 | This model is much like the one above, but has been additionally trained on regular light novels. More likely to go SFW and is more focused towards themes found in these light novels over general cultural references. This is a good model for Novel writing especially if you want to add erotica to the mix. |
| [gpt-neo-2.7B-picard](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-picard.7z) | Novel / 2.7B / Neo Custom | 8GB | 2.0 | Picard is another Novel model, this time exclusively focused on SFW content of various genres. Unlike the name suggests this goes far beyond Star Trek stories and is not exclusively sci-fi. |
| [gpt-neo-2.7B-shinen](https://storage.henk.tech/KoboldAI/gpt-neo-2.7B-shinen.7z) | Novel / 2.7B / Neo Custom | 8GB | 2.0 | The most NSFW of them all, Shinen WILL make things sexual. This model will assume that whatever you are doing is meant to be a sex story and will sexualize constantly. It is designed for people who find Horni to tame. It was trained on SexStories instead of Literotica and was trained on tags making it easier to guide the AI to the right context. |
| [GPT-J-6B (Converted)](https://storage.henk.tech/KoboldAI/gpt-j-6b.7z) | Generic / 6B / Neo Custom | 16GB | 1.1 | This is the basis for all the other GPT-J-6B models, it has been trained on The Pile and is an open alternative for GPT Curie. Because it is a generic model it is not particularly good at anything and needs a long introduction to understand what you want to do. It is however the most flexible because it has no bias. If you want to do something that has no specific model available, such as writing a webpage article or coding this can be a good one to try. This specific version was converted by our community to be able to run as a GPT-Neo model on your GPU. |
| Skein 6B by VE_FORBDRYERNE | Adventure Novel / 6B / Neo Custom | 16GB | 1.1 | Skein is our flagship 6B model, it is a hybrid between a Adventure model and a Novel model. Best used with either Adventure mode or the You Bias userscript enabled. Skein has been trained on high quality Novels along with CYOA adventure stories and is not as wackey as the Adventure model. It also has tagging support. |
| Adventure 6B by VE_FORBRYDERNE | Adventure / 6B / Neo Custom | 16GB | 1.2 | Adventure is a 6B model designed to mimick the behavior of AI Dungeon. It is exclusively for Adventure Mode and can take you on the epic and wackey adventures that AI Dungeon players love. It also features the many tropes of AI Dungeon as it has been trained on very similar data. It must be used in second person (You). |
| Adventure 2.7B by melastashco | Adventure / 2.7B / Neo Custom | 8GB | 2.0 | This is one of the closest replications of the original AI Dungeon Classic model. Tuned on the same data that got uploaded alongside AI Dungeon. In KoboldAI we noticed this model performs better than the conversions of the original AI Dungeon model. It has all the traits you expect of AI Dungeon Classic while not having as many artifacts as this model was trained specifically for KoboldAI. Must be played with Adventure mode enabled to prevent it from doing actions on your behalf. |
| Horni 2.7B by finetuneanon | Novel / 2.7B / Neo Custom | 8GB | 2.0 | One of the best novel models available for 2.7B focused on NSFW content. This model trains the AI to write in a story like fashion using a very large collection of Literotica stories. It is one of the original finetuned models for 2.7B. |
| Horni-LN 2.7B by finetuneanon | Novel / 2.7B / Neo Custom | 8GB | 2.0 | This model is much like the one above, but has been additionally trained on regular light novels. More likely to go SFW and is more focused towards themes found in these light novels over general cultural references. This is a good model for Novel writing especially if you want to add erotica to the mix. |
| Picard 2.7B by Mr Seeker | Novel / 2.7B / Neo Custom | 8GB | 2.0 | Picard is another Novel model, this time exclusively focused on SFW content of various genres. Unlike the name suggests this goes far beyond Star Trek stories and is not exclusively sci-fi. |
| Shinen 2.7B by Mr Seeker | Novel / 2.7B / Neo Custom | 8GB | 2.0 | The most NSFW of them all, Shinen WILL make things sexual. This model will assume that whatever you are doing is meant to be a sex story and will sexualize constantly. It is designed for people who find Horni to tame. It was trained on SexStories instead of Literotica and was trained on tags making it easier to guide the AI to the right context. |
| [AID-16Bit](https://storage.henk.tech/KoboldAI/aid-16bit.zip) | Adventure / 1.5B / GPT-2 Custom | 4GB | 2.0 | The original AI Dungeon Classic model converted to Pytorch and then converted to a 16-bit Model making it half the size. |
| [model_v5_pytorch](https://storage.henk.tech/KoboldAI/model_v5_pytorch.zip) (AI Dungeon's Original Model) | Adventure / 1.5B / GPT-2 Custom | 8GB | 2.0 | This is the original AI Dungeon Classic model converted to the Pytorch format compatible with AI Dungeon Clover and KoboldAI. We consider this model inferior to the GPT-Neo version because it has more artifacting due to its conversion. This is however the most authentic you can get to AI Dungeon Classic. |
| [Novel 774M](https://storage.henk.tech/KoboldAI/Novel%20model%20774M.rar) | Novel / 774M / GPT-2 Custom | 4GB | 2.0 | Novel 774M is made by the AI Dungeon Clover community, because of its small size and novel bias it is more suitable for CPU players that want to play with speed over substance or players who want to test a GPU with a low amount of VRAM. These performance savings are at the cost of story quality and you should not expect the kind of in depth story capabilities that the larger models offer. It was trained for SFW stories. |
| [Smut 774M](https://storage.henk.tech/KoboldAI/Smut%20model%20774M%2030K.rar) | Novel / 774M / GPT-2 Custom | 4GB | 2.0 | The NSFW version of the above, its a smaller GPT-2 based model made by the AI Dungeon Clover community. Gives decent speed on a CPU at the cost of story quality like the other 774M models. |
| [Mia](https://storage.henk.tech/KoboldAI/Mia.7z) | Adventure / 125M / Neo Custom | 1GB | 2.0 | Mia is the smallest Adventure model, it runs at very fast speeds on the CPU which makes it a good testing model for developers who do not have GPU access. Because of its small size it will constantly attempt to do actions on behalf of the player and it will not produce high quality stories. If you just need a small model for a quick test, or if you want to take the challenge of trying to run KoboldAI entirely on your phone this would be an easy model to use due to its small RAM requirements and fast (loading) speeds. |
| [Mia (GPT-Neo-125M-AID)](https://huggingface.co/KoboldAI/GPT-Neo-125M-AID) by Henk717 | Adventure / 125M / Neo Custom | 1GB | 2.0 | Mia is the smallest Adventure model, it runs at very fast speeds on the CPU which makes it a good testing model for developers who do not have GPU access. Because of its small size it will constantly attempt to do actions on behalf of the player and it will not produce high quality stories. If you just need a small model for a quick test, or if you want to take the challenge of trying to run KoboldAI entirely on your phone this would be an easy model to use due to its small RAM requirements and fast (loading) speeds. |
## Softprompts
Softprompts (also known as Modules in other products) are addons that can change the output of existing models. For example you may load a softprompt that biases the AI towards a certain subject and style like transcripts from your favorite TV show.
Since these softprompts are often based on existing franchises we currently do not bundle any of them with KoboldAI due to copyright concerns (We do not want to put the entire project at risk). Instead look at community resources like #softprompts on the [KoboldAI Discord](https://discord.gg/XuQWadgU9k) or the [community hosted mirror](https://storage.henk.tech/KoboldAI/softprompts/) .
That way we are better protected from any DMCA claims as things can be taken down easier than directly on Github. If you have a copyright free softprompt that you made from scratch and is not based on existing IP that you would like to see officially bundled with KoboldAI issue a pull request with your softprompt.
Training softprompts can be done for free with the [mtj-softtuner colab](https://colab.research.google.com/github/VE-FORBRYDERNE/mtj-softtuner/blob/main/mtj-softtuner.ipynb) , in that case you can leave most of the settings default. Your source data needs to be a folder with text files that are UTF-8 formatted and contain Unix line endings.
## Userscripts
Userscripts are scripts that can automate tasks in KoboldAI, or modify the AI behavior / input / output.
Scripting is done in LUA5.4 (Lua does not need to be separately installed as long as you got all the python requirements) and has sandboxing to help protect you from malicious behavior. Even with these measures in place we strongly advice you only run userscripts from places you trust and/or understand, otherwise consult the community for advice on how safe the script might be.
Inside the userscripts folder you will find our kaipreset scripts, these are default scripts that we think will be useful for our users. These scripts are automatically overwritten when you update KoboldAI, if you wish to modify these scripts make sure to first rename them to something else that does not contain kaipreset so your changes are not lost. These scripts range from a You Bias filter that prevents the AI from addressing characters as you. Ways to be able to prevent the AI from using words, word replacements and more.
Along with our preset scripts we also ship examples in the examples folder that merely serve as a demonstration and do not enhance your usage of KoboldAI. To use these scripts make sure to move them out of the examples folder before either using or modifying the script.
Lastly the all the features of our userscript API are documented inside the API Documentation files inside the userscripts folder.
For our TPU versions keep in mind that scripts modifying AI behavior relies on a different way of processing that is slower than if you leave these userscripts disabled even if your script only sporadically uses this modifier. If you want to partially use a script at its full speed than you can enable "No Gen Modifiers" to ensure that the parts that would make the TPU slow are not active.
## Contributors
This project contains work from the following contributors :
- The Gantian - Creator of KoboldAI, has created most features such as the interface, the different AI model / API integrations and in general the largest part of the project.
- VE FORBRYDERNE - Contributed many features such as the Editing overhaul, Adventure Mode, expansions to the world info section, breakmodel integration and much more.
- Henk717 - Contributed the installation scripts, this readme, random story generator, the docker scripts, the foundation for the commandline interface and other smaller changes as well as integrating multiple parts of the code of different forks to unite it all. Not all code Github attributes to Henk717 is by Henk717 as some of it has been integrations of other people's work. We try to clarify this in the contributors list as much as we can.
- Frogging101 - top_k / tfs support
- VE FORBRYDERNE - Contributed many features such as the Editing overhaul, Adventure Mode, expansions to the world info section, breakmodel integration, scripting support, softpromtps and much more. As well as vastly improving the TPU compatibility and integrating external code into KoboldAI so we could use official versions of Transformers with virtually no downsides.
- Henk717 - Contributed the installation scripts, this readme, random story generator, the docker scripts, the foundation for the commandline interface and other smaller changes as well as integrating multiple parts of the code of different forks to unite it all. He also optimized the model loading so that downloaded models get converted to efficient offline models and that in future models are more likely to work out of the box. Not all code Github attributes to Henk717 is by Henk717 as some of it has been integrations of other people's work. We try to clarify this in the contributors list as much as we can.
- Ebolam - Automatic Saving
- Frogging101 - top_k / tfs support (Part of this support was later redone by VE to integrate what was originally inside of finetuneanon's transformers)
- UWUplus (Ralf) - Contributed storage systems for community colabs, as well as cleaning up and integrating the website dependencies/code better. He is also the maintainer of flask-cloudflared which we use to generate the cloudflare links.
- Javalar - Initial Performance increases on the story_refresh
- LexSong - Initial environment file adaptation for conda that served as a basis for the install_requirements.bat overhaul.
- Arrmansa - Breakmodel support for other projects that served as a basis for VE FORBRYDERNE's integration.
- Jojorne - Small improvements to the response selection for gens per action.
As well as various Model creators who will be listed near their models, and all the testers who helped make this possible!

View File

@ -1,7 +1,11 @@
git+https://github.com/finetuneanon/transformers@gpt-neo-localattention3-rp-b
tensorflow-gpu
Flask == 1.1.2
Flask-SocketIO == 5.0.1
requests == 2.25.1
torch == 1.8.1
flask-cloudflared
transformers
Flask
Flask-SocketIO
requests
torch
flask-cloudflared
flask-ngrok
eventlet
lupa==1.10
markdown
bleach

18
requirements_mtj.txt Normal file
View File

@ -0,0 +1,18 @@
numpy
tqdm
requests
optax >= 0.0.5, <= 0.0.9
dm-haiku
ray[default]
jax == 0.2.21
transformers
progressbar2
git+https://github.com/VE-FORBRYDERNE/mesh-transformer-jax@ck
flask
Flask-SocketIO
flask-cloudflared >= 0.0.5
flask-ngrok
eventlet
lupa==1.10
markdown
bleach

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,15 @@ chunk {
font-weight: bold;
}
#gametext comment {
color: #888;
font-style: italic;
}
chunk.editing, chunk.editing * {
color: #cdf !important;
font-weight: normal !important;
font-style: normal !important;
}
#gametext, chunk, chunk * {
@ -21,13 +27,41 @@ chunk.editing, chunk.editing * {
}
#topmenu {
background-color: #337ab7;
background-color: #757575;
padding: 10px;
display: flex;
}
body.connected #topmenu, #topmenu.always-available {
background-color: #337ab7;
}
#topic {
margin-top: 20px;
resize: none;
overflow: auto;
background-color: #404040;
color: #ffffff;
}
#rngmemory {
height: 80px;
resize: none;
overflow:auto;
background-color: #404040;
color: #ffffff;
}
#chatname {
background-color: #404040;
color: #ffffff;
width: 200px;
margin-left: 10px;
}
#menuitems {
display: grid;
grid-template-columns: 80% 20%;
display: flex;
width: 100%;
}
#navbar {
@ -36,10 +70,14 @@ chunk.editing, chunk.editing * {
#navbar li {
margin-right: 5px;
background-color: #4787be;
background-color: #828282;
border-radius: 5px;
}
body.connected #navbar li, #navbar li.always-available {
background-color: #4787be;
}
#navbar li > a {
color: #ffffff;
font-weight: bold;
@ -48,25 +86,31 @@ chunk.editing, chunk.editing * {
#settingsmenu {
display: flex;
flex-wrap: wrap;
background-color: #295071;
background-color: #4d4d4d;
padding: 10px;
}
body.connected #settingsmenu, #settingsmenu.always-available {
background-color: #295071;
}
#formatmenu {
display:none;
background-color: #295071;
background-color: #4d4d4d;
padding: 10px;
}
body.connected #formatmenu, #formatmenu.always-available {
background-color: #295071;
}
#connectstatusdiv {
display: flex;
}
#connectstatusdiv span {
align-self: center;
text-align: right;
}
#gamescreen {
overflow-x: hidden;
height: 490px;
margin-top: 10px;
display: flex;
@ -148,6 +192,7 @@ chunk.editing, chunk.editing * {
overflow:auto;
background-color: #404040;
color: #ffffff;
resize: vertical;
}
#btnmode {
@ -162,7 +207,16 @@ chunk.editing, chunk.editing * {
height: 100%;
}
#btnsend.wait {
background-color: #6c6c6e;
}
#btnsend.wait:hover {
background-color: #98989a;
}
#waitanim {
pointer-events: none;
position:absolute;
top:18px;
left:5px;
@ -184,9 +238,19 @@ chunk.editing, chunk.editing * {
padding-right: 10px;
}
#anoteinput {
#anoteinput, #anotetemplate {
background-color: #404040;
color: #ffffff;
resize: none;
overflow: auto;
}
#anoteinput {
height: 60px;
}
#anotetemplate {
height: 60px;
}
#anoteslidelabel {
@ -217,6 +281,10 @@ chunk.editing, chunk.editing * {
#popuptitlebar {
padding: 10px;
background-color: #757575;
}
body.connected #popuptitlebar, #popuptitlebar.always-available {
background-color: #337ab7;
}
@ -245,6 +313,10 @@ chunk.editing, chunk.editing * {
padding: 10px;
display: flex;
justify-content: center;
background-color: #4d4d4d;
}
body.connected #popupfooter, #popupfooter.always-available {
background-color: #295071;
}
@ -255,6 +327,7 @@ chunk.editing, chunk.editing * {
}
#wimenu {
padding-top: 10px;
max-height: 100%;
width: 100%;
}
@ -307,6 +380,64 @@ chunk.editing, chunk.editing * {
overflow-y: scroll;
}
#sppopup {
width: 800px;
background-color: #262626;
margin-top: 100px;
}
@media (max-width: 768px) {
#sppopup {
width: 100%;
background-color: #262626;
margin-top: 100px;
}
}
#sppopupdelete {
width: 350px;
background-color: #262626;
margin-top: 200px;
}
#sppopuprename {
width: 350px;
background-color: #262626;
margin-top: 200px;
}
#splistcontent {
height: 425px;
overflow-y: scroll;
overflow-wrap: anywhere;
}
#uspopup {
width: 800px;
background-color: #262626;
margin-top: 100px;
}
@media (max-width: 768px) {
#uspopup {
width: 100%;
background-color: #262626;
margin-top: 100px;
}
}
#uslistunloaded {
height: 425px;
overflow-y: scroll;
overflow-wrap: anywhere;
}
#uslistloaded {
height: 425px;
overflow-y: scroll;
overflow-wrap: anywhere;
}
#nspopup {
width: 350px;
background-color: #262626;
@ -316,11 +447,49 @@ chunk.editing, chunk.editing * {
#rspopup {
width: 800px;
background-color: #262626;
margin-top: 200px;
margin-top: 50px;
}
/*================= Classes =================*/
body:not(.connected) .btn-primary {
background-color: #757575;
border-color: #4a4a4a;
}
.btn-primary.always-available {
background-color: #337ab7;
border-color: #2e6da4;
}
body:not(.connected) .btn-primary.focus, body:not(.connected) .btn-primary:focus {
background-color: #5c5c5c;
border-color: #292929;
}
.btn-primary.focus.always-available, .btn-primary.always-available:focus {
background-color: #286090;
border-color: #122b40;
}
body:not(.connected) .btn-primary:hover {
background-color: #5c5c5c;
border-color: #4a4a4a;
}
.btn-primary.always-available:hover {
background-color: #286090;
border-color: #204d74;
}
body:not(.connected) a.dropdown-item:focus, body:not(.connected) a.dropdown-item:hover {
color: #4f4f4f;
}
a.dropdown-item.always-available:focus, a.dropdown-item.always-available:hover {
color: #23527c !important;
}
.aidgpopupcontent {
padding: 10px 40px 10px 40px;
}
@ -341,6 +510,10 @@ chunk.editing, chunk.editing * {
color: #ffffff;
}
.anotelabel:not(.no-padding) {
padding-top: 10px;
}
.airange {
width: 100px;
}
@ -371,10 +544,10 @@ chunk.editing, chunk.editing * {
}
.colorfade, .colorfade * {
-moz-transition:color 1s ease-in;
-o-transition:color 1s ease-in;
-webkit-transition:color 1s ease-in;
transition:color 1s ease-in;
-moz-transition: color 1s ease-in, text-shadow 1s ease-in;
-o-transition: color 1s ease-in, text-shadow 1s ease-in;
-webkit-transition: color 1s ease-in, text-shadow 1s ease-in;
transition: color 1s ease-in, text-shadow 1s ease-in;
}
.color_orange {
@ -394,35 +567,68 @@ chunk.editing, chunk.editing * {
}
.dropdown-menu {
background-color: #337ab7;
background-color: #757575;
width: 200px;
}
body.connected .dropdown-menu, .dropdown-menu.always-available {
background-color: #337ab7;
}
.dropdown-item {
display: block;
padding: 10px;
color: #ffffff;
border-bottom: 1px solid #4d4d4d;
}
body.connected .dropdown-item, .dropdown-item.always-available {
border-bottom: 1px solid #295071;
}
.dropdown-item:first-child {
border-top: 1px solid #4d4d4d;
}
body.connected .dropdown-item:first-child, .dropdown-item:first-child.always-available {
border-top: 1px solid #295071;
}
.dropdown-item:hover {
background-color: #98bcdb;
background-color: #bababa;
text-decoration: none;
}
body.connected .dropdown-item:hover, .dropdown-item.always-available:hover {
background-color: #98bcdb;
}
.edit-flash, .edit-flash * {
color: #3bf723 !important;
}
.status-flash, .status-flash {
color: #fce94f !important;
text-shadow: 0 0 50px #fce94f, 0 0 50px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f;
}
.flex {
display: flex;
align-items: center;
}
.flex-row-container {
display: flex;
flex-flow: wrap;
}
.flex-row {
display: flex;
flex-flow: row;
flex-grow: 1;
width: 100%;
}
.flex-push-right {
margin-left: auto;
}
@ -459,6 +665,107 @@ chunk.editing, chunk.editing * {
height: 50%;
}
.wiheightfull {
height: 90%;
}
.wiheighthalf {
height: 45%;
}
.wicomment {
height: 10%;
grid-column-start: 2;
grid-column-end: 4;
padding-top: 10px;
padding-bottom: 6px;
padding-right: 0px;
}
.wihandle, .wifolderhandle {
grid-row: span 2;
line-height: 100%;
opacity: 30%;
font-size: 8px;
position: relative;
}
.wifoldericon {
font-size: 28px;
position: relative;
grid-row: span 2;
}
.wicentered {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
}
.wicentered-vertical {
position: absolute;
top: 50%;
transform: translate(0%, -50%);
-moz-transform: translate(0%, -50%);
-webkit-transform: translate(0%, -50%);
-ms-transform: translate(0%, -50%);
-o-transform: translate(0%, -50%);
}
.wihandle:hover {
cursor: move;
}
.wisortable-placeholder {
height: 4px;
transform: translate(0%, -14px);
-moz-transform: translate(0%, -14px);
-webkit-transform: translate(0%, -14px);
-ms-transform: translate(0%, -14px);
-o-transform: translate(0%, -14px);
background-color: #3bf723;
}
.ussortable-placeholder {
height: 4px;
background-color: #3bf723;
}
.wisortable-container.folder-expanded {
padding-bottom: 50px;
}
.wisortable-container[folder-uid] {
display: grid;
grid-template-columns: 5% 95%;
}
.wifoldergutter-container {
cursor: pointer;
margin-right: 14px;
display: grid;
}
.wifoldergutter {
background-color: #cdf;
margin-left: 48%;
margin-right: 48%;
margin-bottom: 20px;
}
.wisortable-body {
}
.wisortable-dummy {
padding: 6px;
}
.helpicon {
display: inline-block;
font-family: sans-serif;
@ -477,11 +784,34 @@ chunk.editing, chunk.editing * {
text-decoration: none;
}
.helpicon:hover {
cursor: pointer;
.statusicon {
display: inline-block;
font-weight: bold;
text-align: center;
padding-left: 8px;
padding-right: 8px;
font-size: 30px !important;
font-weight: bold;
text-align: center;
font-size: 1.4ex;
line-height: 1.8ex;
text-decoration: none;
color: #9e9e9e;
}
.helpicon:hover .helptext {
body.connected .statusicon, .statusicon.always-available {
color: #68a2d4;
}
.statusicon.active {
color: #3bf723 !important;
}
.helpicon:hover, .statusicon:hover {
cursor: pointer;
}
.helpicon:hover .helptext, .statusicon:hover .statustext, .statusicon.statustoggled .statustext {
display: inline-block;
width: 250px;
background-color: #1f2931;
@ -493,13 +823,63 @@ chunk.editing, chunk.editing * {
padding: 15px;
margin-left:10px;
border: 1px solid #337ab7;
position: absolute;
z-index: 1;
}
.helptext {
.statusicon:hover .statustext.statustext-wide, .statusicon.statustoggled .statustext.statustext-wide {
width: 350px;
}
.statusiconlabel {
pointer-events: none;
color: #757575;
text-align: center;
font-weight: bold;
font-size: 13px;
}
body.connected .statusiconlabel, .statusiconlabel.always-available {
color: #337ab7;
}
#usiconlabel {
transform: translate(-3px, 10px);
-moz-transform: translate(-3px, 10px);
-webkit-transform: translate(-3px, 10px);
-ms-transform: translate(-3px, 10px);
-o-transform: translate(-3px, 10px);
}
.status-container {
z-index: 1;
text-shadow: none !important;
}
.helptext, .statustext {
display: none;
font-family: sans-serif;
position: absolute;
z-index: 1;
text-shadow: none !important;
}
.statustext {
transform: translate(-105%, 30px);
-moz-transform: translate(-105%, 30px);
-webkit-transform: translate(-105%, 30px);
-ms-transform: translate(-105%, 30px);
-o-transform: translate(-105%, 30px);
}
.statusheader {
padding-bottom: 10px;
}
#stat-usactive {
text-align: left;
height: 270px;
overflow-y: scroll;
position: relative;
padding-left: 20px;
}
.justifyleft {
@ -528,6 +908,62 @@ chunk.editing, chunk.editing * {
position: relative;
}
.folder-expand {
opacity: 20%;
}
.folder-expand:hover {
opacity: 44%;
cursor: pointer;
}
.folder-expand.folder-expanded {
opacity: 80% !important;
}
.folder-expand.folder-expanded:hover {
opacity: 100% !important;
}
.selective-key-icon {
position: absolute !important;
top: 5px !important;
right: 28px !important;
z-index: 1;
opacity: 20%;
}
*:hover > .selective-key-icon {
opacity: 40%;
}
.selective-key-icon:hover {
opacity: 65%;
cursor: pointer;
}
.selective-key-icon-enabled {
color: #3bf723;
opacity: 65%
}
*:hover > .selective-key-icon-enabled {
opacity: 65%;
}
.selective-key-icon-enabled:hover {
opacity: 100%
}
.selective-key-icon-clickthrough {
opacity: 0% !important;
pointer-events: none;
}
.selective-key-icon-clickthrough.selective-key-icon-enabled {
opacity: 35% !important;
}
.constant-key-icon {
position: absolute !important;
top: 5px !important;
@ -620,25 +1056,67 @@ chunk.editing, chunk.editing * {
color: #fce94f
}
.usheadergrid {
display: grid;
grid-template-columns: 50% 50%;
color: #ffffff;
text-align: center;
padding-top: 5px;
padding-bottom: 5px;
}
.uslistgrid {
display: grid;
grid-template-columns: 50% 50%;
}
.navbar .navbar-nav .nav-link:hover {
border-radius: 5px;
background-color: #bababa;
}
body.connected .navbar .navbar-nav .nav-link:hover, .navbar .navbar-nav .nav-link.always-available:hover {
background-color: #98bcdb;
}
body .navbar .navbar-nav .dropdown-item.always-available {
background-color: #337ab7;
}
body .navbar .navbar-nav .dropdown-item.always-available:hover {
background-color: #98bcdb;
}
.navbar .navbar-nav .nav-link:focus {
border-radius: 5px;
background-color: #bababa;
}
body.connected .navbar .navbar-nav .nav-link:focus, .navbar .navbar-nav .nav-link.always-available:focus {
background-color: #98bcdb;
}
.navbar-toggler {
background-color: #337ab7;
border: 1px solid #98bcdb;
background-color: #757575;
border: 1px solid #bababa;
height: 45px;
width: 60px;
border-radius: 6px;
}
body.connected .navbar-toggler, .navbar-toggler.always-available {
border: 1px solid #98bcdb;
}
body .navbar-toggler {
background-color: #337ab7;
}
.navbar-toggler:hover {
background-color: #bababa;
}
body.connected .navbar-togger:hover, .navbar-togger.always-available:hover {
background-color: #98bcdb;
}
@ -666,7 +1144,7 @@ chunk.editing, chunk.editing * {
}
.navcontainer {
width: 100%;
}
.nowrap {
@ -708,6 +1186,10 @@ chunk.editing, chunk.editing * {
.popuptitlebar {
padding: 10px;
background-color: #757575;
}
body.connected .popuptitlebar {
background-color: #337ab7;
}
@ -729,6 +1211,10 @@ chunk.editing, chunk.editing * {
padding: 10px;
display: flex;
justify-content: center;
background-color: #4d4d4d;
}
body.connected .popupfooter, .popupfooter.always-available {
background-color: #295071;
}
@ -757,6 +1243,7 @@ chunk.editing, chunk.editing * {
-o-transition: all 0.15s ease-in;
-webkit-transition: all 0.15s ease-in;
transition: all 0.15s ease-in;
white-space: pre-wrap;
}
.seqselitem:hover {
@ -805,31 +1292,118 @@ chunk.editing, chunk.editing * {
width: 50px;
}
.splistheader {
padding-left: 68px;
padding-right: 20px;
display: flex;
color: #737373;
}
.splistitem {
padding: 12px 10px 12px 10px;
display: flex;
flex-grow: 1;
color: #ffffff;
-moz-transition: background-color 0.25s ease-in;
-o-transition: background-color 0.25s ease-in;
-webkit-transition: background-color 0.25s ease-in;
transition: background-color 0.25s ease-in;
}
.splistitemsub {
color: #ba9;
text-align: right;
}
.splistitem:hover {
cursor: pointer;
background-color: #688f1f;
}
.uslistitem {
padding: 12px 10px 12px 10px;
display: flex;
flex-grow: 1;
color: #ffffff;
-moz-transition: background-color 0.25s ease-in;
-o-transition: background-color 0.25s ease-in;
-webkit-transition: background-color 0.25s ease-in;
transition: background-color 0.25s ease-in;
}
.uslistitemsub {
color: #ba9;
}
.uslistitem:hover {
cursor: move;
background-color: #688f1f;
}
.width-auto {
width: auto;
}
.wilistitem {
height: 80px;
height: 120px;
display: grid;
grid-template-columns: 4% 30% 58% 8%;
margin-bottom: 10px;
grid-template-columns: 4% 30% 63.5% 2.5%;
margin-bottom: 24px;
background-color: #212122;
}
.wilistfolder {
height: 60px;
grid-column: span 2;
display: grid;
grid-template-columns: 4% 5% 88.5% 2.5%;
margin-bottom: 24px;
background-color: #212122;
}
.wientry {
padding-left: 10px;
padding-right: 10px;
padding-right: 0px;
background-color: #212122;
}
.wientry > textarea {
height: 100%;
height: 90%;
resize: none;
overflow:auto;
background-color: #404040;
color: #ffffff;
}
.wicomment > textarea {
resize: none;
height: 0px;
overflow: hidden;
background-color: #404040;
color: #ffffff;
}
.wifoldername {
position: relative;
grid-row: span 2;
}
.wifoldername > div {
width: 100%;
padding-left: 10px;
}
.wifoldername > div > textarea {
font-size: 20px;
resize: none;
height: 0px;
overflow: hidden;
background-color: #404040;
color: #ffffff;
}
.wikey {
background-color: #212122;
}
@ -839,12 +1413,13 @@ chunk.editing, chunk.editing * {
color: #ffffff;
}
.wiremove {
grid-row-start: 1;
grid-row-end: 3;
}
.wiremove > button {
width: 80%;
overflow: hidden;
font-size: 12pt;
}
.wiselective > button {
white-space: normal;
}

6
static/jquery-ui.sortable.min.css vendored Normal file
View File

@ -0,0 +1,6 @@
/*! jQuery UI - v1.13.0 - 2021-12-02
* http://jqueryui.com
* Includes: sortable.css
* Copyright jQuery Foundation and other contributors; Licensed MIT */
.ui-sortable-handle{-ms-touch-action:none;touch-action:none}

6
static/jquery-ui.sortable.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,17 +4,20 @@
<title>KoboldAI Client</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="static/jquery-ui.sortable.min.css">
<link rel="stylesheet" href="static/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap-toggle.min.css">
<link rel="stylesheet" href="static/open-iconic-bootstrap.min.css">
<link rel="stylesheet" href="static/custom.css?ver=1.17">
<script src="static/jquery-3.6.0.min.js"></script>
<script src="static/jquery-ui.sortable.min.js"></script>
<script src="static/socket.io.min.js"></script>
<script src="static/application.js?ver=1.16.4b"></script>
<script src="static/bootstrap.min.js"></script>
<script src="static/bootstrap-toggle.min.js"></script>
<script src="static/rangy-core.min.js"></script>
<link rel="stylesheet" href="static/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap-toggle.min.css">
<link rel="stylesheet" href="static/custom.css?ver=1.16.4a">
<link rel="stylesheet" href="static/open-iconic-bootstrap.min.css">
<script src="static/application.js?ver=1.17"></script>
</head>
<body>
<input type="file" id="remote-save-select" accept="application/json" style="display:none">
@ -37,13 +40,13 @@
<a class="dropdown-item" href="#" id="btn_rndgame">Random Story</a>
</div>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Save</a>
<li class="nav-item dropdown always-available">
<a class="nav-link dropdown-toggle always-available" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Save</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" id="btn_save">Save</a>
<a class="dropdown-item" href="#" id="btn_saveas">Save As</a>
<a class="dropdown-item" href="#" id="btn_savetofile">Save To File...</a>
<a class="dropdown-item" href="#" id="btn_download">Download Story as JSON</a>
<a class="dropdown-item always-available" href="#" id="btn_download">Download Story as JSON</a>
<a class="dropdown-item" href="#" id="btn_downloadtxt">Download Story as Plaintext</a>
</div>
</li>
@ -68,12 +71,33 @@
<li class="nav-item">
<a class="nav-link" href="#" id="btn_format">Formatting</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" id="btn_userscripts">Userscripts</a>
</li>
<li class="nav-item">
<a class="nav-link hidden" href="#" id="btn_softprompt">Soft Prompt</a>
</li>
</ul>
</div>
</nav>
</div>
<div id="connectstatusdiv">
<span id="connectstatus" class="color_orange">Waiting for connection...</span>
<div id="connectstatusdiv" class="flex-row-container">
<span id="connectstatus" class="color_orange flex-row">Waiting for connection...</span>
<div class="layer-container status-container flex-push-right">
<span class="oi oi-puzzle-piece statusicon layer-bottom" aria-hidden="true">
<div class="statustext statustext-wide">
<div id="stat-us" class="statusheader">No userscripts active</div>
<div id="stat-usactive"></div>
</div>
</span>
<div class="layer-top statusiconlabel" id="usiconlabel"></div>
</div>
<span class="oi oi-lightbulb statusicon" aria-hidden="true">
<div class="statustext">
<div id="stat-sp" class="statusheader">No soft prompt active</div>
<div id="stat-spactive"></div>
</div>
</span>
</div>
</div>
</div>
@ -101,6 +125,7 @@
<button type="button" class="btn btn-primary" id="btn_actundo">Back</button>
<button type="button" class="btn btn-primary" id="btn_actretry">Retry</button>
</div>
<input type="text" id="chatname" class="form-control hidden" placeholder="Chat name">
<div id="messagefield"></div>
<div class="box flex-push-right">
<input type="checkbox" data-toggle="toggle" data-onstyle="success" id="allowediting" disabled>
@ -122,11 +147,11 @@
<div id="anoterowcontainer">
<div id="anoterow">
<div id="anoterowleft">
<div class="anotelabel">
<div class="anotelabel no-padding">
Author's Note
</div>
<div class="anotefield">
<input class="form-control" type="text" placeholder="Author's Note" id="anoteinput">
<textarea class="form-control" placeholder="Author's Note" id="anoteinput"></textarea>
</div>
</div>
<div id="anoterowright">
@ -151,6 +176,14 @@
</div>
</div>
</div>
<div>
<div class="anotelabel">
Author's Note Template (the "&lt;|&gt;" will be replaced with the Author's Note text)
</div>
<div class="anotefield">
<textarea class="form-control" placeholder="Author's Note Template" id="anotetemplate"></textarea>
</div>
</div>
</div>
</div>
</div>
@ -226,6 +259,40 @@
</div>
</div>
</div>
<div class="popupcontainer hidden" id="spcontainer">
<div id="sppopup">
<div class="popuptitlebar">
<div class="popuptitletext">Select A Soft Prompt To Use</div>
</div>
<div id="splistcontent">
</div>
<div class="popupfooter">
<button type="button" class="btn btn-primary" id="btn_spaccept">Load</button>
<button type="button" class="btn btn-primary" id="btn_spclose">Cancel</button>
</div>
</div>
</div>
<div class="popupcontainer hidden" id="uscontainer">
<div id="uspopup">
<div class="popuptitlebar">
<div class="popuptitletext">Select userscripts to load; drag-and-drop to reorder</div>
</div>
<div class="usheadergrid">
<div>[AVAILABLE]</div>
<div>[ACTIVE]</div>
</div>
<div class="uslistgrid">
<div id="uslistunloaded">
</div>
<div id="uslistloaded">
</div>
</div>
<div class="popupfooter">
<button type="button" class="btn btn-primary" id="btn_usaccept">Load</button>
<button type="button" class="btn btn-primary" id="btn_usclose">Cancel</button>
</div>
</div>
</div>
<div class="popupcontainer hidden" id="loadcontainerdelete">
<div id="loadpopupdelete">
<div class="popuptitlebar">
@ -286,15 +353,18 @@
<div class="aidgpopuplistheader">
<br>
Story quality and topic depends on the model and your settings/suggestion (Around 0.5 temp is recommended).<br>
This feature works best with finetuned models like GPT-Neo-AID or GPT-Neo-Horni but is limited to what the AI knows.<br>
This feature works best with heavily themed models like the Adventure model and can also be influenced with softprompts .<br>
If you get random spam then your model is not capable of using this feature and if you get unrelated stories it does not understand the topic.<br>
Generated results are unfiltered and can be offensive or unsuitable for children.<br><br>
Generated results are unfiltered and can be offensive or unsuitable for children, the AI can make connections the model/softprompt creator did not intend.<br><br>
Unsaved data will be lost.<br><br>
Below you can input a genre suggestion for the AI to loosely base the story on (For example Horror or Cowboy).<br>
</div>
<div class="aidgpopupcontent">
<input class="form-control" type="text" placeholder="Story Genre Suggestion (Leave blank for fully random)" id="topic">
</div>
<div class="aidgpopupcontent">
<textarea class="form-control" placeholder="Memory" id="rngmemory"></textarea>
</div>
<div class="popupfooter">
<button type="button" class="btn btn-primary" id="btn_rsaccept">Accept</button>
<button type="button" class="btn btn-primary" id="btn_rsclose">Cancel</button>

837
tpu_mtj_backend.py Normal file
View File

@ -0,0 +1,837 @@
'''
This file is AGPL-licensed.
Some of the code in this file is from Clover Edition:
https://github.com/cloveranon/Clover-Edition/blob/master/aidungeon/gpt2generator.py
The license for Clover Edition is shown below:
Copyright (c) 2019 Nick Walton
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'''
import multiprocessing
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar
import progressbar
import time
import os
import requests
import random
import jax
from jax.config import config
from jax.experimental import maps
import jax.numpy as jnp
import numpy as np
import optax
import haiku as hk
import transformers
from mesh_transformer.checkpoint import read_ckpt_lowmem
from mesh_transformer.transformer_shard import CausalTransformer, CausalTransformerShard
params: Dict[str, Any] = {}
def warper_callback(logits) -> np.array:
raise NotImplementedError("`tpu_mtj_backend.warper_callback()` needs to be defined")
def stopping_callback(generated, n_generated, excluded_world_info) -> Tuple[List[set], bool, bool]:
raise NotImplementedError("`tpu_mtj_backend.stopping_callback()` needs to be defined")
def settings_callback() -> dict:
return {
"top_p": 0.9,
"temp": 0.5,
"top_k": 0,
"tfs": 1.0,
"repetition_penalty": 1.0,
"rpslope": 0.0,
"rprange": 0,
}
def started_compiling_callback() -> None:
pass
def stopped_compiling_callback() -> None:
pass
def compiling_callback() -> None:
pass
def show_spinner():
bar = progressbar.ProgressBar(max_value=progressbar.UnknownLength, widgets=[progressbar.Timer(), ' ', progressbar.BouncingBar(left='[', right=']', marker='')])
i = 0
while True:
bar.update(i)
time.sleep(0.1)
i += 1
__F = TypeVar("__F", bound=Callable)
__T = TypeVar("__T")
def __move_xmap(f: __F, out_axis: str) -> __F:
return maps.xmap(
f,
in_axes=(["shard", ...], ["batch", ...]),
out_axes=[out_axis, ...],
axis_resources={'shard': 'mp', 'batch': 'dp'},
)
def __shard_xmap(batch_dim=1):
xmap = __move_xmap(lambda s, b: s, "shard")
def inner(x: __T) -> __T:
return xmap(x, np.empty(batch_dim))
return inner
def __batch_xmap(shard_dim=1):
xmap = __move_xmap(lambda s, b: b, "batch")
def inner(x: __T) -> __T:
return xmap(np.empty(shard_dim), x)
return inner
def apply_repetition_penalty_dynamic(logits, tokens, repetition_penalty, generated_index, gen_length, rpslope, rprange):
'''
This gets called by generate_loop_fn to apply repetition penalty
to the 1D array logits using the provided 1D array of tokens to penalize
'''
tokens = np.minimum(tokens, params["n_vocab"]-1) # https://github.com/google/jax/issues/3774
rpslope = np.int32(rpslope)
rprange = np.int32(rprange)
clipped_rprange = rprange if rprange > 0 else tokens.shape[-1]
penalty_arange = np.roll(np.arange(tokens.shape[-1]) + (clipped_rprange - tokens.shape[-1]), generated_index, axis=-1)
# Make a new array with the same length as the tokens array but with
# each element replaced by the value at the corresponding index in the
# logits array; e.g.
# if logits is [77, 5, 3, 98] and tokens is [0, 1, 2, 3, 2, 3, 1],
# then penalty_logits will be [77, 5, 3, 98, 3, 98, 5]
penalty_logits = np.take(logits, tokens)
# Repetition penalty slope
if rpslope != 0.0 and rprange > 0:
_penalty = (penalty_arange/(rprange - 1)) * 2 - 1
_penalty = (rpslope * _penalty) / (1 + np.abs(_penalty) * (rpslope - 1))
_penalty = 1 + ((_penalty + 1) / 2) * (repetition_penalty - 1)
repetition_penalty = _penalty
# Divide positive values by repetition_penalty and multiply negative
# values by repetition_penalty (the academic publication that described
# this technique actually just only divided, but that would cause tokens
# with negative logits to become more likely, which is obviously wrong)
penalty_logits = np.where(
penalty_arange >= 0,
np.where(
penalty_logits > 0,
penalty_logits/repetition_penalty,
penalty_logits*repetition_penalty,
),
penalty_logits,
)
# Finally, put those penalized logit values back into their original
# positions in the logits array
logits[tokens] = penalty_logits
return logits
def kobold_sample_dynamic(key, logits, top_p=0.9, temp=0.5, top_k=0, tfs=1.0):
'''
This gets called by generate_loop_fn to apply a series of 4 filters
to the logits (top-k, then top-p, then TFS, then temperature) before
picking one token using the modified logits
'''
# Top-k (keep only the k tokens with the highest logits and remove
# the rest, by setting their logits to negative infinity)
def top_k_filter(logits):
# After sorting the logits array in descending order,
# sorted_indices_to_remove is a 1D array that is True for tokens
# in the sorted logits array we want to remove and False for ones
# we want to keep, in this case the first top_k elements will be
# False and the rest will be True
sorted_indices_to_remove = np.arange(len(logits)) >= top_k
# Unsort the logits array back to its original configuration and
# remove tokens we need to remove
_, indices_to_remove = jax.lax.sort_key_val(
np.argsort(-logits),
sorted_indices_to_remove,
)
return np.where(indices_to_remove, -np.inf, logits)
if top_k > 0:
logits = top_k_filter(logits)
# Top-p (after sorting the remaining tokens again in descending order of
# logit, remove the ones that have cumulative softmax probability
# greater than p)
def top_p_filter(logits):
# Sort the logits array in descending order, replace every element
# with e (Euler's number) to the power of that element, and divide
# each element of the new array by the sum of the elements in the
# new array
sorted_logits = -np.sort(-logits)
probabilities = np.array(jax.nn.softmax(sorted_logits), copy=True)
# Calculate cumulative_probabilities as the prefix-sum array of
# probabilities
cumulative_probabilities = np.cumsum(probabilities, axis=-1)
# We want to remove tokens with cumulative probability higher
# than top_p
sorted_indices_to_remove = cumulative_probabilities > top_p
# Don't ever remove the token with the highest logit, even if
# the probability is higher than top_p
sorted_indices_to_remove[0] = False
# Unsort and remove
_, indices_to_remove = jax.lax.sort_key_val(
np.argsort(-logits),
sorted_indices_to_remove,
)
return np.where(indices_to_remove, -np.inf, logits)
if top_p < 1.0:
logits = top_p_filter(logits)
# Tail free sampling (basically top-p a second time on remaining tokens
# except it's the "cumulative normalized absolute second finite
# differences of the softmax probabilities" instead of just the
# cumulative softmax probabilities)
def tail_free_filter(logits):
# Sort in descending order
sorted_logits = -np.sort(-logits)
# Softmax again
probabilities = np.array(jax.nn.softmax(sorted_logits), copy=True)
# Calculate the second finite differences of that array (i.e.
# calculate the difference array and then calculate the difference
# array of the difference array)
d2 = np.diff(np.diff(probabilities))
# Get the absolute values of all those second finite differences
d2 = np.abs(d2)
# Normalize (all elements in the array are divided by the sum of the
# array's elements)
d2 = d2 / d2.sum(axis=-1, keepdims=True)
# Get the prefix-sum array
cumulative_d2 = np.cumsum(d2, axis=-1)
# We will remove the tokens with a cumulative normalized absolute
# second finite difference larger than the TFS value
sorted_indices_to_remove = cumulative_d2 > tfs
# Don't remove the token with the highest logit
sorted_indices_to_remove[0] = False
# Since the d2 array has two fewer elements than the logits array,
# we'll add two extra Trues to the end
sorted_indices_to_remove = np.pad(
sorted_indices_to_remove,
(0, 2),
constant_values=True,
)
# Unsort and remove
_, indices_to_remove = jax.lax.sort_key_val(
np.argsort(-logits),
sorted_indices_to_remove,
)
return np.where(indices_to_remove, -np.inf, logits)
if tfs < 1.0:
logits = tail_free_filter(logits)
# Temperature (just divide the logits by the temperature)
logits /= temp
# Finally, pick one token using the softmax thingy again (it gives
# an array whose elements sum to 1 so it can be used nicely as a
# probability distribution)
return jax.random.categorical(key, logits, -1).astype(np.uint32)
def apply_repetition_penalty_static(logits, tokens, repetition_penalty, generated_index, gen_length, rpslope, rprange):
'''
This gets called by generate_loop_fn to apply repetition penalty
to the 1D array logits using the provided 1D array of tokens to penalize
'''
rpslope = jnp.int32(rpslope)
rprange = jnp.int32(rprange)
clipped_rprange = jax.lax.cond(rprange > 0, lambda x: x, lambda x: tokens.shape[-1], rprange)
penalty_arange = jnp.roll(jnp.arange(tokens.shape[-1]) + (clipped_rprange - tokens.shape[-1]), generated_index, axis=-1)
# Make a new array with the same length as the tokens array but with
# each element replaced by the value at the corresponding index in the
# logits array; e.g.
# if logits is [77, 5, 3, 98] and tokens is [0, 1, 2, 3, 2, 3, 1],
# then penalty_logits will be [77, 5, 3, 98, 3, 98, 5]
penalty_logits = jnp.take(logits, tokens)
# Repetition penalty slope
def apply_slope(carry):
repetition_penalty, rprange = carry
_penalty = (penalty_arange/(rprange - 1)) * 2 - 1
_penalty = (rpslope * _penalty) / (1 + jnp.abs(_penalty) * (rpslope - 1))
_penalty = 1 + ((_penalty + 1) / 2) * (repetition_penalty - 1)
return _penalty
repetition_penalty = jax.lax.cond(
(rpslope != 0.0) & (rprange > 0), # Not a typo; do not use `and` here, it makes JAX crash
apply_slope,
lambda carry: jnp.full(tokens.shape, carry[0]),
(repetition_penalty, rprange),
)
# Divide positive values by repetition_penalty and multiply negative
# values by repetition_penalty (the academic publication that described
# this technique actually just only divided, but that would cause tokens
# with negative logits to become more likely, which is obviously wrong)
penalty_logits = jnp.where(
penalty_arange >= 0,
jnp.where(
penalty_logits > 0,
penalty_logits/repetition_penalty,
penalty_logits*repetition_penalty,
),
penalty_logits,
)
# Finally, put those penalized logit values back into their original
# positions in the logits array
return logits.at[tokens].set(penalty_logits)
def kobold_sample_static(key, logits, top_p=0.9, temp=0.5, top_k=0, tfs=1.0):
'''
This gets called by generate_loop_fn to apply a series of 4 filters
to the logits (top-k, then top-p, then TFS, then temperature) before
picking one token using the modified logits
'''
# Top-k (keep only the k tokens with the highest logits and remove
# the rest, by setting their logits to negative infinity)
def top_k_filter(logits):
# After sorting the logits array in descending order,
# sorted_indices_to_remove is a 1D array that is True for tokens
# in the sorted logits array we want to remove and False for ones
# we want to keep, in this case the first top_k elements will be
# False and the rest will be True
sorted_indices_to_remove = jnp.arange(len(logits)) >= top_k
# Unsort the logits array back to its original configuration and
# remove tokens we need to remove
_, indices_to_remove = jax.lax.sort_key_val(
jnp.argsort(-logits),
sorted_indices_to_remove,
)
return jnp.where(indices_to_remove, -jnp.inf, logits)
logits = jax.lax.cond(top_k > 0, top_k_filter, lambda x: x, logits)
# Top-p (after sorting the remaining tokens again in descending order of
# logit, remove the ones that have cumulative softmax probability
# greater than p)
def top_p_filter(logits):
# Sort the logits array in descending order, replace every element
# with e (Euler's number) to the power of that element, and divide
# each element of the new array by the sum of the elements in the
# new array
sorted_logits = -jnp.sort(-logits)
probabilities = jax.nn.softmax(sorted_logits)
# Calculate cumulative_probabilities as the prefix-sum array of
# probabilities
cumulative_probabilities = jnp.cumsum(probabilities, axis=-1)
# We want to remove tokens with cumulative probability higher
# than top_p
sorted_indices_to_remove = cumulative_probabilities > top_p
# Don't ever remove the token with the highest logit, even if
# the probability is higher than top_p
sorted_indices_to_remove = sorted_indices_to_remove.at[0].set(False)
# Unsort and remove
_, indices_to_remove = jax.lax.sort_key_val(
jnp.argsort(-logits),
sorted_indices_to_remove,
)
return jnp.where(indices_to_remove, -jnp.inf, logits)
logits = jax.lax.cond(top_p < 1.0, top_p_filter, lambda x: x, logits)
# Tail free sampling (basically top-p a second time on remaining tokens
# except it's the "cumulative normalized absolute second finite
# differences of the softmax probabilities" instead of just the
# cumulative softmax probabilities)
def tail_free_filter(logits):
# Sort in descending order
sorted_logits = -jnp.sort(-logits)
# Softmax again
probabilities = jax.nn.softmax(sorted_logits)
# Calculate the second finite differences of that array (i.e.
# calculate the difference array and then calculate the difference
# array of the difference array)
d2 = jnp.diff(jnp.diff(probabilities))
# Get the absolute values of all those second finite differences
d2 = jnp.abs(d2)
# Normalize (all elements in the array are divided by the sum of the
# array's elements)
d2 = d2 / d2.sum(axis=-1, keepdims=True)
# Get the prefix-sum array
cumulative_d2 = jnp.cumsum(d2, axis=-1)
# We will remove the tokens with a cumulative normalized absolute
# second finite difference larger than the TFS value
sorted_indices_to_remove = cumulative_d2 > tfs
# Don't remove the token with the highest logit
sorted_indices_to_remove = sorted_indices_to_remove.at[0].set(False)
# Since the d2 array has two fewer elements than the logits array,
# we'll add two extra Trues to the end
sorted_indices_to_remove = jnp.pad(
sorted_indices_to_remove,
(0, 2),
constant_values=True,
)
# Unsort and remove
_, indices_to_remove = jax.lax.sort_key_val(
jnp.argsort(-logits),
sorted_indices_to_remove,
)
return jnp.where(indices_to_remove, -jnp.inf, logits)
logits = jax.lax.cond(tfs < 1.0, tail_free_filter, lambda x: x, logits)
# Temperature (just divide the logits by the temperature)
def temp_filter(logits):
return logits / temp
logits = jax.lax.cond(True, temp_filter, lambda x: x, logits)
# Finally, pick one token using the softmax thingy again (it gives
# an array whose elements sum to 1 so it can be used nicely as a
# probability distribution)
return jax.random.categorical(key, logits, -1).astype(jnp.uint32)
pad_token_id = 50256
def sample_func(data, key, numseqs_aux, badwords, repetition_penalty, generated_index, gen_length, rpslope, rprange, sampler_options):
numseqs = numseqs_aux.shape[0]
gi = data[0][1]
def sample_loop_fn(carry):
generated, generated_index, logits, _ = carry[0][0]
sample_key = carry[1]
# Get the pseudo-random number generator key that will
# be used by kobold_sample_dynamic to randomly pick a token
sample_key, new_key = jax.random.split(sample_key, num=2)
# Apply repetition penalty to all tokens that are
# currently inside the "generated" array
logits = apply_repetition_penalty_dynamic(
logits,
generated,
repetition_penalty,
generated_index,
gen_length,
rpslope,
rprange,
)
# Remove any tokens in the badwords list by setting
# their logits to negative infinity which effectively
# makes their probabilities of being chosen zero
logits[badwords] = -np.inf
# Use the sampler (kobold_sample_dynamic) to pick one token
# based on the logits array as a 0D uint32 array
# (higher logit means higher probability of being
# picked, non-linearly)
next_token = kobold_sample_dynamic(
sample_key,
logits,
**sampler_options,
)
# Remember what token was picked
generated[generated_index] = next_token
generated_index += 1
# Re-pack the current sample_loop_fn's state so we can
# get back the same variables the next time
carry[0][0] = [generated, generated_index, logits, next_token]
carry[0].append(carry[0].pop(0))
return carry[0], new_key
# return jax.lax.while_loop(
# lambda carry: carry[0][0][1] == gi,
# sample_loop_fn,
# (data, key),
# )
carry = (data, key)
while carry[0][0][1] == gi:
carry = sample_loop_fn(carry)
return carry
class PenalizingCausalTransformer(CausalTransformer):
def __init__(self, config):
# Initialize
super().__init__(config)
def generate_static(state, key, ctx, ctx_length, gen_length, numseqs_aux, sampler_options, soft_embeddings=None):
compiling_callback()
numseqs = numseqs_aux.shape[0]
# These are the tokens that we don't want the AI to ever write
self.badwords = jnp.array(vars.badwordsids).squeeze()
@hk.transform
def generate_sample(context, ctx_length):
# Give the initial context to the transformer
transformer = CausalTransformerShard(config)
def generate_initial_scan_fn(sequence_index, _):
_, initial_state = transformer.generate_initial(context, ctx_length, soft_embeddings=soft_embeddings)
# The "generated" array will contain the tokens from the
# context as well as the tokens picked by the sampler at
# each stage, padded with a bunch of 50256s, so we know
# which tokens have to be repetition penalized
generated = jnp.pad(context, (0, config["seq"]), constant_values=pad_token_id) # Let it start off with just the 2048 context tokens, plus some 50256s which will be eventually filled with sampler-chosen tokens
generated_index = config["seq"]
# Add that information to generate_loop_fn's starting state
initial_state = (generated, generated_index, sequence_index) + initial_state
return sequence_index+1, initial_state
_, initial_states = jax.lax.scan(generate_initial_scan_fn, 0, None, numseqs)
sample_key = initial_states[-1][0]
initial_states = list(jax.tree_map(lambda x: x[i], initial_states[:-1]) for i in range(numseqs))
# Get repetition penalty from the arguments
repetition_penalty = sampler_options.pop('repetition_penalty', None)
rpslope = sampler_options.pop('rpslope', None)
rprange = sampler_options.pop('rprange', None)
# This is the main generation loop
def generate_loop_fn(carry):
# Unpack current generate_loop_fn state
generated, generated_index, sequence_index, next_token, decode_state = carry[0][0]
sample_key = carry[1]
# Get the pseudo-random number generator key that will
# be used by kobold_sample_static to randomly pick a token
sample_key, new_key = jax.random.split(sample_key)
# Give the context to the model and get the logits it
# spits out
# (a 2D array with 1 row and 50400 columns representing
# how strongly it thinks each of the 50257 tokens in its
# vocabulary should be appended to the context, followed
# by 143 apparently useless columns ???)
logits, new_state = transformer.generate_once(next_token, decode_state, soft_embeddings=soft_embeddings)
# Verify that logits does indeed have that many rows and
# columns (if you get an error here, pray for mercy)
assert logits.shape == (1, config["n_vocab"])
# Flatten it into a 1D array to make it easier to use
logits = logits[0]
# Apply repetition penalty to all tokens that are
# currently inside the "generated" array
if repetition_penalty is not None:
logits = apply_repetition_penalty_static(
logits,
generated,
repetition_penalty,
generated_index,
gen_length,
rpslope,
rprange,
)
# Remove any tokens in the badwords list by setting
# their logits to negative infinity which effectively
# makes their probabilities of being chosen zero
logits = logits.at[self.badwords].set(-jnp.inf)
# Use the sampler (kobold_sample_static) to pick one token
# based on the logits array as a 0D uint32 array
# (higher logit means higher probability of being
# picked, non-linearly)
next_token = kobold_sample_static(
sample_key,
logits,
**sampler_options,
)
# Remember what token was picked
generated = generated.at[generated_index].set(next_token)
generated_index += 1
# Re-pack the current generate_loop_fn's state so we can
# get back the same variables the next time
carry[0][0] = (generated, generated_index, sequence_index, next_token[jnp.newaxis], new_state)
carry[0].append(carry[0].pop(0))
return carry[0], new_key
return jax.lax.while_loop(
lambda carry: carry[0][0][1] - config["seq"] < gen_length,
generate_loop_fn,
(initial_states, sample_key),
)
return generate_sample.apply(state["params"], key, ctx, ctx_length)
self.generate_static_xmap = jax.experimental.maps.xmap(
fun=generate_static,
in_axes=(
["shard", ...],
["batch", ...],
["batch", ...],
["batch", ...],
["batch", ...],
["batch", ...],
["batch", ...],
["shard", ...],
),
out_axes=["shard", "batch", ...],
axis_resources={'shard': 'mp', 'batch': 'dp'},
)
def generate_initial(state, key, ctx, ctx_length, numseqs_aux, soft_embeddings=None):
compiling_callback()
numseqs = numseqs_aux.shape[0]
@hk.transform
def generate_initial_inner(context, ctx_length):
# Give the initial context to the transformer
transformer = CausalTransformerShard(config)
def generate_initial_scan_fn(sequence_index, c):
_, initial_state = transformer.generate_initial(c, ctx_length, soft_embeddings=soft_embeddings)
generated_index = config["seq"]
# Add that information to generate_loop_fn's starting state
initial_state = (jnp.empty(config["n_vocab"], dtype=jnp.float32), generated_index, sequence_index) + initial_state
return sequence_index+1, initial_state
_, initial_states = jax.lax.scan(generate_initial_scan_fn, 0, context, numseqs)
sample_key = initial_states[-1][0]
initial_states = list(list(jax.tree_map(lambda x: x[i], initial_states[:-1])) for i in range(numseqs))
return initial_states, sample_key
return generate_initial_inner.apply(state["params"], key, ctx, ctx_length)
self.generate_initial_xmap = jax.experimental.maps.xmap(
fun=generate_initial,
in_axes=(
["shard", ...],
["batch", ...],
["batch", ...],
["batch", ...],
["batch", ...],
["shard", ...],
),
out_axes=["shard", "batch", ...],
axis_resources={'shard': 'mp', 'batch': 'dp'},
)
def generate_once(data, state, numseqs_aux, soft_embeddings=None):
numseqs = numseqs_aux.shape[0]
@hk.without_apply_rng
@hk.transform
def generate_once_inner():
gi = data[0][1]
# Give the initial context to the transformer
transformer = CausalTransformerShard(config)
# This is the main generation loop
def generate_loop_fn(carry):
# Unpack current generate_loop_fn state
_, generated_index, sequence_index, next_token, decode_state = carry[0][0]
# Give the context to the model and get the logits it
# spits out
# (a 2D array with 1 row and 50400 columns representing
# how strongly it thinks each of the 50257 tokens in its
# vocabulary should be appended to the context, followed
# by 143 apparently useless columns ???)
logits, new_state = transformer.generate_once(next_token, decode_state, soft_embeddings=soft_embeddings)
# Verify that logits does indeed have that many rows and
# columns (if you get an error here, pray for mercy)
assert logits.shape == (1, config["n_vocab"])
assert logits.dtype == jnp.float32
# Flatten it into a 1D array to make it easier to use
logits = logits[0]
# Re-pack the current generate_loop_fn's state so we can
# get back the same variables the next time
generated_index += 1
carry[0][0] = [logits, generated_index, sequence_index, next_token, new_state]
carry[0].append(carry[0].pop(0))
return carry[0],
return jax.lax.while_loop(
lambda carry: carry[0][0][1] == gi,
generate_loop_fn,
(data,),
)
return generate_once_inner.apply(state["params"])
self.generate_once_xmap = jax.experimental.maps.xmap(
fun=generate_once,
in_axes=(
["shard", "batch", ...],
["shard", ...],
["batch", ...],
["shard", ...],
),
out_axes=["shard", "batch", ...],
axis_resources={'shard': 'mp', 'batch': 'dp'},
)
def generate_dynamic(self, ctx, ctx_length, gen_length, numseqs, return_logits=False, soft_embeddings=None, excluded_world_info=None, use_callback=True):
assert excluded_world_info is not None
assert not return_logits
assert gen_length.ndim == 1
assert soft_embeddings is not None
key = hk.PRNGSequence(random.randint(0, 2 ** 60))
batch_size = ctx.shape[0]
self.batch_size = batch_size
_numseqs_aux = jnp.empty((batch_size, numseqs), dtype=np.uint32)
numseqs_aux = batch_xmap(_numseqs_aux)
sample_data = [
[
np.pad(ctx[0][i], (0, params["seq"]), constant_values=pad_token_id),
params["seq"],
None,
np.empty((), dtype=np.uint32),
]
for i in range(numseqs)
]
n_generated = 0
regeneration_required = False
halt = False
started_compiling_callback()
generate_data, sample_key = self.generate_initial_xmap(self.state, jnp.array(key.take(batch_size)), ctx, ctx_length, numseqs_aux, soft_embeddings)
sample_key = np.asarray(sample_key[0, 0])
while True:
generate_data, = self.generate_once_xmap(generate_data, self.state, numseqs_aux, soft_embeddings)
for i in range(numseqs):
sample_data[i][2] = np.array(generate_data[i][0][0, 0], copy=True)
if use_callback:
logits = np.float32(tuple(d[2] for d in sample_data))
logits = warper_callback(logits)
for i in range(numseqs):
sample_data[i][2] = logits[i]
sampler_options = settings_callback()
repetition_penalty = sampler_options.pop("repetition_penalty", 1.0)
rpslope = sampler_options.pop("rpslope", 0.0)
rprange = sampler_options.pop("rprange", 0)
sample_data, sample_key = sample_func(sample_data, sample_key, _numseqs_aux, badwords, repetition_penalty, params["seq"] + n_generated, gen_length, rpslope, rprange, sampler_options)
n_generated += 1
for i in range(numseqs):
generate_data[i][3] = np.tile(sample_data[i][0][sample_data[i][1]-1][np.newaxis, np.newaxis], (params["cores_per_replica"], 1, 1))
if use_callback:
generated = np.uint32(tuple(d[0] for d in sample_data))
excluded_world_info, regeneration_required, halt = stopping_callback(generated, n_generated, excluded_world_info)
if regeneration_required or halt:
break
else:
break
stopped_compiling_callback()
return sample_data, n_generated, regeneration_required, halt
def generate_static(self, ctx, ctx_length, gen_length, numseqs, sampler_options, return_logits=False, soft_embeddings=None):
assert not return_logits
key = hk.PRNGSequence(random.randint(0, 2 ** 60))
batch_size = ctx.shape[0]
self.batch_size = batch_size
started_compiling_callback()
result = self.generate_static_xmap(
self.state,
jnp.array(key.take(batch_size)),
ctx,
np.array(ctx_length, dtype=np.uint32),
np.array(gen_length, dtype=np.uint32),
np.empty((batch_size, numseqs), dtype=np.uint8),
sampler_options,
soft_embeddings,
)
stopped_compiling_callback()
return result
def infer_dynamic(
context: np.array,
numseqs=1,
gen_len=80,
soft_embeddings: Optional[np.array] = None,
soft_tokens: Optional[np.array] = None,
excluded_world_info = None,
use_callback=True,
) -> Tuple[List[np.array], int, bool, bool]:
assert excluded_world_info is not None
maps.thread_resources.env = thread_resources_env
total_batch = 1
tokens = context
if(soft_tokens is not None):
tokens = np.uint32(np.concatenate((np.tile(soft_tokens, (tokens.shape[0], 1)), tokens), axis=-1))
provided_ctx = tokens.shape[-1]
pad_amount = seq - provided_ctx
padded_tokens = np.pad(tokens, ((0, 0), (pad_amount, 0)), constant_values=pad_token_id)
batched_tokens = np.array([padded_tokens] * total_batch)
samples = []
output = network.generate_dynamic(
batched_tokens,
np.ones(total_batch, dtype=np.uint32) * provided_ctx,
np.ones(total_batch, dtype=np.uint32) * gen_len,
numseqs,
soft_embeddings=soft_embeddings,
excluded_world_info=excluded_world_info,
use_callback=use_callback,
)
for out in output[0]:
samples.append(out[0][params["seq"] : params["seq"] + gen_len])
return (samples,) + output[1:]
def infer_static(
context: np.array,
top_p=0.9,
temp=0.5,
top_k=0,
tfs=1.0,
repetition_penalty=1.0,
rpslope=0.0,
rprange=0,
numseqs=1,
gen_len=80,
soft_embeddings: Optional[np.array] = None,
soft_tokens: Optional[np.array] = None,
) -> List[np.array]:
maps.thread_resources.env = thread_resources_env
total_batch = 1
tokens = context
if(soft_tokens is not None):
tokens = np.uint32(np.concatenate((soft_tokens, tokens)))
provided_ctx = tokens.shape[0]
pad_amount = seq - provided_ctx
padded_tokens = np.pad(tokens, ((pad_amount, 0),), constant_values=pad_token_id)
batched_tokens = np.array([padded_tokens] * total_batch)
samples = []
batched_generator_params = {
"temp": temp * np.ones(total_batch),
"top_p": top_p * np.ones(total_batch),
"tfs": tfs * np.ones(total_batch),
"repetition_penalty": repetition_penalty * np.ones(total_batch),
"rpslope": rpslope * np.ones(total_batch),
"rprange": np.full(total_batch, rprange, dtype=np.uint32),
"top_k": np.full(total_batch, top_k, dtype=np.uint32)
}
output = network.generate_static(
batched_tokens,
np.ones(total_batch, dtype=np.uint32) * provided_ctx,
np.ones(total_batch, dtype=np.uint32) * gen_len,
numseqs,
batched_generator_params,
soft_embeddings=soft_embeddings,
)[0]
for o in output:
samples.append(o[0][0, 0, params["seq"] : params["seq"] + gen_len])
return samples
def load_model(path: str, driver_version="tpu_driver0.1_dev20210607", **kwargs) -> None:
global thread_resources_env, seq, tokenizer, network, params
default_params = {
"compat": "j",
"layers": 28,
"d_model": 4096,
"n_heads": 16,
"n_vocab": 50400,
"n_vocab_padding": 0,
"norm": "layernorm",
"pe": "rotary",
"pe_rotary_dims": 64,
"seq": 2048,
"cores_per_replica": 8,
}
params = kwargs
for param in default_params:
if param not in params:
params[param] = default_params[param]
# Disable JAX warnings about these two functions having been renamed
jax.host_count = jax.process_count
jax.host_id = jax.process_index
print("Connecting to your Colab instance's TPU", flush=True)
spinner = multiprocessing.Process(target=show_spinner, args=())
spinner.start()
colab_tpu_addr = os.environ['COLAB_TPU_ADDR'].split(':')[0]
url = f'http://{colab_tpu_addr}:8475/requestversion/{driver_version}'
requests.post(url)
spinner.terminate()
print()
config.FLAGS.jax_xla_backend = "tpu_driver"
config.FLAGS.jax_backend_target = "grpc://" + os.environ['COLAB_TPU_ADDR']
cores_per_replica = params["cores_per_replica"]
seq = params["seq"]
params["optimizer"] = optax.scale(0)
mesh_shape = (1, cores_per_replica)
devices = np.array(jax.devices()[:cores_per_replica]).reshape(mesh_shape)
thread_resources_env = maps.ResourceEnv(maps.Mesh(devices, ('dp', 'mp')), ())
maps.thread_resources.env = thread_resources_env
tokenizer = transformers.GPT2TokenizerFast.from_pretrained('gpt2')
global shard_xmap, batch_xmap
shard_xmap = __shard_xmap()
batch_xmap = __batch_xmap(shard_dim=cores_per_replica)
global badwords
# These are the tokens that we don't want the AI to ever write
badwords = jnp.array(vars.badwordsids).squeeze()
if not path.endswith("/"):
path += "/"
network = PenalizingCausalTransformer(params)
network.state = read_ckpt_lowmem(network.state, path, devices.shape[1])
network.state = network.move_xmap(network.state, np.zeros(cores_per_replica))

53
update-koboldai.bat Normal file
View File

@ -0,0 +1,53 @@
@echo off
%~d0
cd %~dp0
TITLE KoboldAI - Updater
SET /P M=<loader.settings
IF %M%==1 GOTO drivemap
IF %M%==2 GOTO subfolder
IF %M%==3 GOTO drivemap_B
:subfolder
SET TEMP=%~DP0MINICONDA3
SET TMP=%~DP0MINICONDA3
call miniconda3\condabin\activate
GOTO GIT
:drivemap
subst K: miniconda3 >nul
SET TEMP=K:\
SET TMP=K:\
call K:\python\condabin\activate
GOTO GIT
:drivemap_B
subst B: miniconda3 >nul
SET TEMP=B:\
SET TMP=B:\
call B:\python\condabin\activate
GOTO GIT
:GIT
ECHO 1. KoboldAI Main (The Official stable version of KoboldAI)
ECHO 2. KoboldAI United (Development Version, new features but may break at any time)
SET /P V=Enter your desired version or type your own GIT URL:
IF %V%==1 (
SET origin=https://github.com/koboldai/koboldai-client
SET branch=main
) ELSE (
IF %V%==2 (
SET origin=https://github.com/henk717/koboldai
SET branch=united
) ELSE (
SET origin=%v%
SET /P branch=Specify the GIT Branch:
)
)
git init
git remote remove origin
git remote add origin %origin%
git fetch --all
git checkout %branch% -f
git reset --hard origin/%branch%
cmd /k

2
userscripts/Readme.txt Normal file
View File

@ -0,0 +1,2 @@
This folder contains userscripts for KoboldAI, any script that begins with kaipreset_ is treated as a official part of KoboldAI and can be overwritten by updates.
If you would like to make modifications to any of the lua scripts it is recommended you that you either rename the script, or create a new copy with a new name.

720
userscripts/api_documentation.html vendored Normal file
View File

@ -0,0 +1,720 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>API</title>
<link rel="stylesheet" href="https://stackedit.io/style.css" />
</head>
<body class="stackedit">
<div class="stackedit__left">
<div class="stackedit__toc">
<ul>
<li><a href="#kobold">kobold</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.decode">kobold.decode()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.encode">kobold.encode()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.get_config_file">kobold.get_config_file()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.halt_generation">kobold.halt_generation()</a></li>
<li><a href="#kobold.restart_generation">kobold.restart_generation()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.authorsnote">kobold.authorsnote</a></li>
<li><a href="#kobold.authorsnotetemplate">kobold.authorsnotetemplate</a></li>
<li><a href="#kobold.custmodpth">kobold.custmodpth</a></li>
<li><a href="#kobold.feedback">kobold.feedback</a></li>
<li><a href="#kobold.generated">kobold.generated</a></li>
<li><a href="#kobold.generated_cols">kobold.generated_cols</a></li>
<li><a href="#kobold.generated_rows">kobold.generated_rows</a></li>
<li><a href="#kobold.is_config_file_open">kobold.is_config_file_open</a></li>
<li><a href="#kobold.logits">kobold.logits</a></li>
<li><a href="#kobold.logits_cols">kobold.logits_cols</a></li>
<li><a href="#kobold.logits_rows">kobold.logits_rows</a></li>
<li><a href="#kobold.memory">kobold.memory</a></li>
<li><a href="#kobold.modelbackend">kobold.modelbackend</a></li>
<li><a href="#kobold.modeltype">kobold.modeltype</a></li>
<li><a href="#kobold.num_outputs">kobold.num_outputs</a></li>
<li><a href="#kobold.outputs">kobold.outputs</a></li>
<li><a href="#kobold.settings">kobold.settings</a></li>
<li><a href="#kobold.story">kobold.story</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.storyforward_iter">kobold.story:forward_iter()</a></li>
<li><a href="#kobold.storyreverse_iter">kobold.story:reverse_iter()</a></li>
<li><a href="#koboldstorychunk">KoboldStoryChunk</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldstorychunk.content">KoboldStoryChunk.content</a></li>
<li><a href="#koboldstorychunk.num">KoboldStoryChunk.num</a></li>
<li><a href="#kobold.submission">kobold.submission</a></li>
<li><a href="#kobold.worldinfo">kobold.worldinfo</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.worldinfocompute_context">kobold.worldinfo:compute_context()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.worldinfofinduid">kobold.worldinfo:finduid()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#kobold.worldinfois_valid">kobold.worldinfo:is_valid()</a></li>
<li><a href="#kobold.worldinfo.folders">kobold.worldinfo.folders</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfoentry">KoboldWorldInfoEntry</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfoentrycompute_context">KoboldWorldInfoEntry:compute_context()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfoentryis_valid">KoboldWorldInfoEntry:is_valid()</a></li>
<li><a href="#koboldworldinfoentry.comment">KoboldWorldInfoEntry.comment</a></li>
<li><a href="#koboldworldinfoentry.constant">KoboldWorldInfoEntry.constant</a></li>
<li><a href="#koboldworldinfoentry.content">KoboldWorldInfoEntry.content</a></li>
<li><a href="#koboldworldinfoentry.folder">KoboldWorldInfoEntry.folder</a></li>
<li><a href="#koboldworldinfoentry.key">KoboldWorldInfoEntry.key</a></li>
<li><a href="#koboldworldinfoentry.keysecondary">KoboldWorldInfoEntry.keysecondary</a></li>
<li><a href="#koboldworldinfoentry.num">KoboldWorldInfoEntry.num</a></li>
<li><a href="#koboldworldinfoentry.selective">KoboldWorldInfoEntry.selective</a></li>
<li><a href="#koboldworldinfoentry.uid">KoboldWorldInfoEntry.uid</a></li>
<li><a href="#koboldworldinfofolderselectorfinduid">KoboldWorldInfoFolderSelector:finduid()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfofolderselectoris_valid">KoboldWorldInfoFolderSelector:is_valid()</a></li>
<li><a href="#koboldworldinfofolder">KoboldWorldInfoFolder</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfofoldercompute_context">KoboldWorldInfoFolder:compute_context()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfofolderfinduid">KoboldWorldInfoFolder:finduid()</a>
<ul>
<li></li>
</ul>
</li>
<li><a href="#koboldworldinfofolderis_valid">KoboldWorldInfoFolder:is_valid()</a></li>
<li><a href="#koboldworldinfofolder.name">KoboldWorldInfoFolder.name</a></li>
<li><a href="#koboldworldinfofolder.uid">KoboldWorldInfoFolder.uid</a></li>
</ul>
</div>
</div>
<div class="stackedit__right">
<div class="stackedit__html">
<h1 id="kobold">kobold</h1>
<pre class=" language-lua"><code class="prism language-lua">global kobold<span class="token punctuation">:</span> KoboldLib
</code></pre>
<h3 id="methods">Methods:</h3>
<ul>
<li><code>kobold.decode()</code></li>
<li><code>kobold.encode()</code></li>
<li><code>kobold.get_config_file()</code></li>
<li><code>kobold.halt_generation()</code></li>
<li><code>kobold.restart_generation()</code></li>
</ul>
<h3 id="fields">Fields:</h3>
<ul>
<li><code>kobold.authorsnote</code></li>
<li><code>kobold.authorsnotetemplate</code></li>
<li><code>kobold.custmodpth</code></li>
<li><code>kobold.feedback</code></li>
<li><code>kobold.generated</code></li>
<li><code>kobold.generated_cols</code></li>
<li><code>kobold.generated_rows</code></li>
<li><code>kobold.is_config_file_open</code></li>
<li><code>kobold.logits</code></li>
<li><code>kobold.logits_cols</code></li>
<li><code>kobold.logits_rows</code></li>
<li><code>kobold.memory</code></li>
<li><code>kobold.modelbackend</code></li>
<li><code>kobold.modeltype</code></li>
<li><code>kobold.num_outputs</code></li>
<li><code>kobold.outputs</code></li>
<li><code>kobold.settings</code></li>
<li><code>kobold.story</code></li>
<li><code>kobold.submission</code></li>
<li><code>kobold.worldinfo</code></li>
</ul>
<h1 id="kobold.decode">kobold.decode()</h1>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldLib<span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span>tok<span class="token punctuation">:</span> integer<span class="token operator">|</span>table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> integer<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> string
</code></pre>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<p>Decodes the given token or list of tokens using the current tokenizer. If <code>kobold.backend</code> is <code>'readonly'</code> or <code>'api'</code>, the tokenizer used is the GPT-2 tokenizer, otherwise the models tokenizer is used. This function is the inverse of <code>kobold.encode()</code>.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token function">print</span><span class="token punctuation">(</span>kobold<span class="token punctuation">.</span><span class="token function">decode</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token number">15496</span><span class="token punctuation">,</span> <span class="token number">2159</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">-- 'Hello World'</span>
</code></pre>
<h3 id="parameters">Parameters:</h3>
<ul>
<li>tok (<code>integer|table&lt;integer, integer&gt;</code>): Array of token IDs to decode, or the token ID of a single token.</li>
</ul>
<h3 id="returns">Returns:</h3>
<ul>
<li><code>string</code>: Decoded tokens.</li>
</ul>
<h1 id="kobold.encode">kobold.encode()</h1>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldLib<span class="token punctuation">.</span><span class="token function">encode</span><span class="token punctuation">(</span>str<span class="token punctuation">:</span> string<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> integer<span class="token operator">&gt;</span>
</code></pre>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<p>Encodes the given string using the current tokenizer into an array of tokens. If <code>kobold.backend</code> is <code>'readonly'</code> or <code>'api'</code>, the tokenizer used is the GPT-2 tokenizer, otherwise the models tokenizer is used. This function is the inverse of <code>kobold.decode()</code>.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">local</span> tokens <span class="token operator">=</span> kobold<span class="token punctuation">.</span><span class="token function">encode</span><span class="token punctuation">(</span><span class="token string">"Hello World"</span><span class="token punctuation">)</span>
<span class="token function">print</span><span class="token punctuation">(</span><span class="token operator">#</span>tokens<span class="token punctuation">)</span> <span class="token comment">-- 2</span>
<span class="token function">print</span><span class="token punctuation">(</span>tokens<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">-- 15496</span>
<span class="token function">print</span><span class="token punctuation">(</span>tokens<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">-- 2159</span>
</code></pre>
<h3 id="parameters-1">Parameters:</h3>
<ul>
<li>tok (<code>integer|table&lt;integer, integer&gt;</code>): Array of token IDs to decode, or the token ID of a single token.</li>
</ul>
<h3 id="returns-1">Returns:</h3>
<ul>
<li><code>string</code>: Decoded tokens.</li>
</ul>
<h1 id="kobold.get_config_file">kobold.get_config_file()</h1>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldLib<span class="token punctuation">.</span><span class="token function">get_config_file</span><span class="token punctuation">(</span>clear?<span class="token punctuation">:</span> boolean<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> file<span class="token operator">*</span>
</code></pre>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<p>Returns a file handle representing your scripts configuration file, which is usually the file in the userscripts folder with the same filename as your script but with “.conf” appended at the end. This function throws an error on failure.</p>
<p>If the configuration file does not exist when this function is called, the configuration file will first be created as a new empty file.</p>
<p>If KoboldAI does not possess an open file handle to the configuration file, this function opens the file in <code>w+b</code> mode if the <code>clear</code> parameter is a truthy value, otherwise the file is opened in <code>r+b</code> mode. These are mostly the same the file is opened in binary read-write mode and then seeked to the start of the file except the former mode deletes the contents of the file prior to opening it and the latter mode does not.</p>
<p>If KoboldAI does possess an open file handle to the configuration file, that open file handle is returned without seeking or deleting the contents of the file. You can check if KoboldAI possesses an open file handle to the configuration file by using <code>kobold.is_config_file_open</code>.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">local</span> example_config <span class="token operator">=</span> <span class="token string">"return 'Hello World'"</span>
<span class="token keyword">local</span> cfg
<span class="token keyword">do</span>
<span class="token comment">-- If config file is empty, write example config</span>
<span class="token keyword">local</span> f <span class="token operator">&lt;</span>close<span class="token operator">&gt;</span> <span class="token operator">=</span> kobold<span class="token punctuation">.</span><span class="token function">get_config_file</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
f<span class="token punctuation">:</span><span class="token function">seek</span><span class="token punctuation">(</span><span class="token string">"set"</span><span class="token punctuation">)</span>
<span class="token keyword">if</span> f<span class="token punctuation">:</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token keyword">nil</span> <span class="token keyword">then</span> f<span class="token punctuation">:</span><span class="token function">write</span><span class="token punctuation">(</span>example_config<span class="token punctuation">)</span> <span class="token keyword">end</span>
f<span class="token punctuation">:</span><span class="token function">seek</span><span class="token punctuation">(</span><span class="token string">"set"</span><span class="token punctuation">)</span>
<span class="token comment">-- Read config</span>
<span class="token keyword">local</span> err
cfg<span class="token punctuation">,</span> err <span class="token operator">=</span> <span class="token function">load</span><span class="token punctuation">(</span>f<span class="token punctuation">:</span><span class="token function">read</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">if</span> err <span class="token operator">~=</span> <span class="token keyword">nil</span> <span class="token keyword">then</span> <span class="token function">error</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token keyword">end</span>
cfg <span class="token operator">=</span> <span class="token function">cfg</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<h3 id="parameters-2">Parameters:</h3>
<ul>
<li>clear? (<code>bool</code>): If KoboldAI does not possess an open file handle to the configuration object, this determines whether the file will be opened in <code>w+b</code> or <code>r+b</code> mode. This parameter defaults to <code>false</code>.</li>
</ul>
<h3 id="returns-2">Returns:</h3>
<ul>
<li><code>file*</code>: File handle for the configuration file.</li>
</ul>
<h1 id="kobold.halt_generation">kobold.halt_generation()</h1>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldLib<span class="token punctuation">.</span><span class="token function">halt_generation</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> <span class="token keyword">nil</span>
</code></pre>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<p>If called from an input modifier, prevents the users input from being sent to the model and skips directly to the output modifier.</p>
<p>If called from a generation modifier, stops generation after the current token is generated and then skips to the output modifier. In other words, if, when you call this function, <code>kobold.generated</code> has n columns, it will have exactly n+1 columns when the output modifier is called.</p>
<p>If called from an output modifier, has no effect.</p>
<h1 id="kobold.restart_generation">kobold.restart_generation()</h1>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldLib<span class="token punctuation">.</span><span class="token function">restart_generation</span><span class="token punctuation">(</span>sequence?<span class="token punctuation">:</span> integer<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> <span class="token keyword">nil</span>
</code></pre>
<p><em><strong>Callable from:</strong></em> output modifier</p>
<p>After the current output is sent to the GUI, starts another generation using the empty string as the submission.</p>
<p>Whatever ends up being the output selected by the user or by the <code>sequence</code> parameter will be saved in <code>kobold.feedback</code> when the new generation begins.</p>
<h3 id="parameters-3">Parameters:</h3>
<ul>
<li>sequence? (<code>integer</code>): If you have multiple Gens Per Action, this can be used to choose which sequence to use as the output, where 1 is the first, 2 is the second and so on. If you set this to 0, the user will be prompted to choose the sequence instead. Defaults to 0.</li>
</ul>
<h1 id="kobold.authorsnote">kobold.authorsnote</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>authorsnote<span class="token punctuation">:</span> string
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<p>The authors note as set from the “Memory” button in the GUI.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="kobold.authorsnotetemplate">kobold.authorsnotetemplate</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>authorsnotetemplate<span class="token punctuation">:</span> string
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<p>The authors note template as set from the “Memory” button in the GUI.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="kobold.custmodpth">kobold.custmodpth</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>custmodpth<span class="token punctuation">:</span> string
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Path to a directory that the user chose either via the file dialog that appears when KoboldAI asks you to choose the path to your custom model or via the <code>--path</code> command-line flag.</p>
<p>If the user loaded a built-in model from the menu, this is instead the model ID of the model on Hugging Faces model hub, such as “KoboldAI/GPT-Neo-2.7B-Picard” or “hakurei/lit-6B”.</p>
<h1 id="kobold.feedback">kobold.feedback</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>feedback<span class="token punctuation">:</span> string?
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>If this is a repeat generation caused by <code>kobold.restart_generation()</code>, this will be a string containing the previous output. If not, this will be <code>nil</code>.</p>
<h1 id="kobold.generated">kobold.generated</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>generated<span class="token punctuation">:</span> table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> integer<span class="token operator">&gt;&gt;</span>?
</code></pre>
<p><em><strong>Readable from:</strong></em> generation modifier and output modifier, but only if <code>kobold.modelbackend</code> is not <code>'api'</code> or <code>'readonly'</code><br>
<em><strong>Writable from:</strong></em> generation modifier</p>
<p>Two-dimensional array of tokens generated thus far. Each row represents one sequence, each column one token.</p>
<h1 id="kobold.generated_cols">kobold.generated_cols</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>generated_cols<span class="token punctuation">:</span> integer
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Number of columns in <code>kobold.generated</code>. In other words, the number of tokens generated thus far, which is equal to the number of times that the generation modifier has been called, not including the current time if this is being read from a generation modifier.</p>
<p>If <code>kobold.modelbackend</code> is <code>'api'</code> or <code>'readonly'</code>, this returns 0 instead.</p>
<h1 id="kobold.generated_rows">kobold.generated_rows</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>generated_rows<span class="token punctuation">:</span> integer
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Number of rows in <code>kobold.generated</code>, equal to <code>kobold.settings.numseqs</code>.</p>
<h1 id="kobold.is_config_file_open">kobold.is_config_file_open</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>is_config_file_open<span class="token punctuation">:</span> boolean
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Whether or not KoboldAI possesses an open file handle to your scripts configuration file. See <code>kobold.get_config_file()</code> for more details.</p>
<h1 id="kobold.logits">kobold.logits</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>logits<span class="token punctuation">:</span> table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> number<span class="token operator">&gt;&gt;</span>?
</code></pre>
<p><em><strong>Readable from:</strong></em> generation modifier, but only if <code>kobold.modelbackend</code> is not <code>'api'</code> or <code>'readonly'</code><br>
<em><strong>Writable from:</strong></em> generation modifier</p>
<p>Two-dimensional array of <a href="https://datascience.stackexchange.com/questions/31041/what-does-logits-in-machine-learning-mean">logits</a> prior to being filtered by top-p sampling, etc. Each row represents one sequence, each column one of the tokens in the models vocabulary. The ith column represents the logit score of token i-1, so if you want to access the logit score of token 18435 (" Hello" with a leading space), you need to access column 18436. You may alter this two-dimensional array to encourage or deter certain tokens from appearing in the output in a stochastic manner.</p>
<p>Dont modify this table unnecessarily unless you know what you are doing! The bias example scripts show how to use this feature properly.</p>
<h1 id="kobold.logits_cols">kobold.logits_cols</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>logits_cols<span class="token punctuation">:</span> integer
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Number of columns in <code>kobold.logits</code>, equal to the vocabulary size of the current model. Most models based on GPT-2 (e.g. GPT-Neo and GPT-J) have a vocabulary size of 50257. GPT-J models in particular have a vocabulary size of 50400 instead, although GPT-J models arent trained to use the rightmost 143 tokens of the logits array.</p>
<p>If <code>kobold.modelbackend</code> is <code>'api'</code> or <code>'readonly'</code>, this returns 0 instead.</p>
<h1 id="kobold.logits_rows">kobold.logits_rows</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>logits_rows<span class="token punctuation">:</span> integer
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Number of rows in <code>kobold.generated</code>, equal to <code>kobold.settings.numseqs</code>. a local KoboldAI install.</p>
<h1 id="kobold.memory">kobold.memory</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>memory<span class="token punctuation">:</span> string
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<p>The memory as set from the “Memory” button in the GUI.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="kobold.modelbackend">kobold.modelbackend</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>modelbackend<span class="token punctuation">:</span> string
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>One of the following values:</p>
<ul>
<li><code>'api'</code>: InferKit, OpenAI or legacy Colab mode</li>
<li><code>'readonly'</code>: Read-only no AI mode</li>
<li><code>'transformers'</code>: Models running on your own computer, and Colab GPU backend (currently used for 2.7B models on Colab)</li>
<li><code>'mtj'</code>: Colab TPU backend (currently used for 6B models on Colab)</li>
</ul>
<h1 id="kobold.modeltype">kobold.modeltype</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>modeltype<span class="token punctuation">:</span> string
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>One of the following values:</p>
<ul>
<li><code>'api'</code>: InferKit, OpenAI or legacy Colab mode</li>
<li><code>'readonly'</code>: Read-only no AI mode</li>
<li><code>'unknown'</code></li>
<li><code>'gpt2'</code>: GPT-2-Small</li>
<li><code>'gpt2-medium'</code></li>
<li><code>'gpt2-large'</code></li>
<li><code>'gpt2-xl'</code></li>
<li><code>'gpt-neo-125M'</code></li>
<li><code>'gpt-neo-1.3B'</code></li>
<li><code>'gpt-neo-2.7B'</code></li>
<li><code>'gpt-j-6B'</code></li>
</ul>
<h1 id="kobold.num_outputs">kobold.num_outputs</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>num_outputs<span class="token punctuation">:</span> integer
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<p>Number of rows in <code>kobold.outputs</code>. This is equal to <code>kobold.settings.numseqs</code> unless youre using a non-Colab third-party API such as OpenAI or InferKit, in which case this is 1. If you decide to write to <code>kobold.settings.numseqs</code> from an output modifier, this value remains unchanged.</p>
<h1 id="kobold.outputs">kobold.outputs</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>outputs<span class="token punctuation">:</span> table<span class="token operator">&lt;</span>integer<span class="token punctuation">,</span> string<span class="token operator">&gt;</span>
</code></pre>
<p><em><strong>Readable from:</strong></em> output modifier<br>
<em><strong>Writable from:</strong></em> output modifier</p>
<p>Model output before applying output formatting. One row per “Gens Per Action”, unless youre using OpenAI or InferKit, in which case this always has exactly one row.</p>
<h1 id="kobold.settings">kobold.settings</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>settings<span class="token punctuation">:</span> KoboldSettings
</code></pre>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (does not affect other scripts when written to since each script has its own copy of this object)</p>
<p>Contains most of the settings. They have the same names as in gensettings.py, so the top-p value is <code>kobold.settings.settopp</code>.</p>
<p>All the settings can be read from anywhere and written from anywhere, except <code>kobold.settings.numseqs</code> which can only be written to from an input modifier or output modifier.</p>
<p>Modifying certain fields from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess. Currently, only the following fields and their aliases cause this to occur:</p>
<ul>
<li><code>kobold.settings.settknmax</code> (Max Tokens)</li>
<li><code>kobold.settings.anotedepth</code> (Authors Note Depth)</li>
<li><code>kobold.settings.setwidepth</code> (World Info Depth)</li>
<li><code>kobold.settings.setuseprompt</code> (Always Use Prompt)</li>
</ul>
<h1 id="kobold.story">kobold.story</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>story<span class="token punctuation">:</span> KoboldStory
</code></pre>
<p>Contains the chunks of the current story. Dont use <code>pairs</code> or <code>ipairs</code> to iterate over the story chunks, use <code>kobold.story:forward_iter()</code> or <code>kobold.story:reverse_iter()</code>, which guarantee amortized worst-case iteration time complexity linear to the number of chunks in the story regardless of what the highest chunk number is.</p>
<p>You can index this object to get a story chunk (as a <code>KoboldStoryChunk</code> object) by its number, which is an integer. The prompt chunk, if it exists, is guaranteed to be chunk 0. Aside from that, the chunk numbers are not guaranteed to be contiguous or ordered in any way.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">local</span> prompt_chunk <span class="token operator">=</span> kobold<span class="token punctuation">.</span>story<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token comment">-- KoboldStoryChunk object referring to the prompt chunk</span>
</code></pre>
<h3 id="methods-1">Methods:</h3>
<ul>
<li><code>kobold.story:forward_iter()</code></li>
<li><code>kobold.story:reverse_iter()</code></li>
</ul>
<h1 id="kobold.storyforward_iter">kobold.story:forward_iter()</h1>
<p><em><strong>Callable from</strong></em>: anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldStory<span class="token punctuation">:</span><span class="token function">forward_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> KoboldStoryChunk<span class="token punctuation">,</span> table<span class="token punctuation">,</span> <span class="token keyword">nil</span>
</code></pre>
<p>Returns a stateful iterator that efficiently iterates through story chunks from top to bottom.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">for</span> chunk <span class="token keyword">in</span> kobold<span class="token punctuation">.</span>story<span class="token punctuation">:</span><span class="token function">forward_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">do</span>
<span class="token function">print</span><span class="token punctuation">(</span>chunk<span class="token punctuation">.</span>num<span class="token punctuation">,</span> chunk<span class="token punctuation">.</span>content<span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<h1 id="kobold.storyreverse_iter">kobold.story:reverse_iter()</h1>
<p><em><strong>Callable from</strong></em>: anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldStory<span class="token punctuation">:</span><span class="token function">reverse_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> KoboldStoryChunk<span class="token punctuation">,</span> table<span class="token punctuation">,</span> <span class="token keyword">nil</span>
</code></pre>
<p>Returns a stateful iterator that efficiently iterates through story chunks from bottom to top.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">for</span> chunk <span class="token keyword">in</span> kobold<span class="token punctuation">.</span>story<span class="token punctuation">:</span><span class="token function">reverse_iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">do</span>
<span class="token function">print</span><span class="token punctuation">(</span>chunk<span class="token punctuation">.</span>num<span class="token punctuation">,</span> chunk<span class="token punctuation">.</span>content<span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<h1 id="koboldstorychunk">KoboldStoryChunk</h1>
<p>Represents a story chunk.</p>
<h3 id="fields-1">Fields:</h3>
<ul>
<li><code>KoboldStoryChunk.content</code></li>
<li><code>KoboldStoryChunk.num</code></li>
</ul>
<h1 id="koboldstorychunk.content">KoboldStoryChunk.content</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldStoryChunk<span class="token punctuation">.</span>content<span class="token punctuation">:</span> string
</code></pre>
<p>The text inside of the story chunk.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="koboldstorychunk.num">KoboldStoryChunk.num</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldStoryChunk<span class="token punctuation">.</span>num<span class="token punctuation">:</span> integer
</code></pre>
<p>The number of the story chunk. Chunk 0 is guaranteed to be the prompt chunk if it exists; no guarantees can be made about the numbers of other chunks.</p>
<h1 id="kobold.submission">kobold.submission</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> input modifier</p>
<pre class=" language-lua"><code class="prism language-lua">field kobold<span class="token punctuation">.</span>submission<span class="token punctuation">:</span> string
</code></pre>
<p>The user-submitted text after being formatted by input formatting. If this is a repeated generation incurred by <code>kobold.restart_generation()</code>, then this is the empty string.</p>
<h1 id="kobold.worldinfo">kobold.worldinfo</h1>
<pre class=" language-lua"><code class="prism language-lua">field KoboldLib<span class="token punctuation">.</span>worldinfo<span class="token punctuation">:</span> KoboldWorldInfo
</code></pre>
<p>Represents the world info entries.</p>
<p>Indexing this object at index i returns the ith world info entry from the top in amortized constant worst-case time as a <code>KoboldWorldInfoEntry</code>. This includes world info entries that are inside folders.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">local</span> entry <span class="token operator">=</span> kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token comment">-- Retrieves fifth entry from top as a KoboldWorldInfoEntry</span>
</code></pre>
<p>You can use <code>ipairs</code> or a numeric loop to iterate from top to bottom:</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">for</span> index<span class="token punctuation">,</span> entry <span class="token keyword">in</span> <span class="token function">ipairs</span><span class="token punctuation">(</span>kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token function">print</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> entry<span class="token punctuation">.</span>content<span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">for</span> index <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">#</span>kobold<span class="token punctuation">.</span>worldinfo <span class="token keyword">do</span><span class="token punctuation">:</span>
<span class="token function">print</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">.</span>content<span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<h3 id="methods-2">Methods:</h3>
<ul>
<li><code>kobold.story:compute_context()</code></li>
<li><code>kobold.story:finduid()</code></li>
<li><code>kobold.story:is_valid()</code></li>
</ul>
<h3 id="fields-2">Fields:</h3>
<ul>
<li><code>kobold.story.folders</code></li>
</ul>
<h1 id="kobold.worldinfocompute_context">kobold.worldinfo:compute_context()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfo<span class="token punctuation">:</span><span class="token function">compute_context</span><span class="token punctuation">(</span>submission<span class="token punctuation">:</span> string<span class="token punctuation">,</span> entries?<span class="token punctuation">:</span> KoboldWorldInfoEntry<span class="token operator">|</span>table<span class="token operator">&lt;</span>any<span class="token punctuation">,</span> KoboldWorldInfoEntry<span class="token operator">&gt;</span><span class="token punctuation">,</span> kwargs?<span class="token punctuation">:</span> table<span class="token operator">&lt;</span>string<span class="token punctuation">,</span> any<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> string
</code></pre>
<p>Computes the context that would be sent to the generator with the users current settings if <code>submission</code> were the users input after being formatted by input formatting. The context would include memory at the top, followed by active world info entries, followed by some story chunks with the authors note somewhere, followed by <code>submission</code>.</p>
<h3 id="parameters-4">Parameters</h3>
<ul>
<li>submission (<code>string</code>): String to use as simulated users input after being formatted by input formatting.</li>
<li>entries? (<code>KoboldWorldInfoEntry|table&lt;any, KoboldWorldInfoEntry&gt;</code>): A <code>KoboldWorldInfoEntry</code> or table thereof that indicates an allowed subset of world info entries to include in the context. Defaults to all world info entries.</li>
<li>kwargs? (<code>table&lt;string, any&gt;</code>): Table of optional keyword arguments from the following list. Defaults to <code>{}</code>.
<ul>
<li>scan_story? (<code>boolean</code>): Whether or not to scan the past few actions of the story for world info keys in addition to the submission like how world info normally behaves. If this is set to <code>false</code>, only the <code>submission</code> is scanned for world info keys. Defaults to <code>true</code>.</li>
</ul>
</li>
</ul>
<h3 id="returns-3">Returns</h3>
<p><code>string</code>: Computed context.</p>
<h1 id="kobold.worldinfofinduid">kobold.worldinfo:finduid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfo<span class="token punctuation">:</span><span class="token function">finduid</span><span class="token punctuation">(</span>u<span class="token punctuation">:</span> integer<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> KoboldWorldInfoEntry?
</code></pre>
<p>Returns the world info entry with the given UID in amortized constant worst-case time, or <code>nil</code> if not found.</p>
<h3 id="parameters-5">Parameters</h3>
<ul>
<li>u (<code>integer</code>): UID.</li>
</ul>
<h3 id="returns-4">Returns</h3>
<ul>
<li><code>KoboldWorldInfoEntry?</code>: The world info entry with requested UID, or <code>nil</code> if no such entry exists.</li>
</ul>
<h1 id="kobold.worldinfois_valid">kobold.worldinfo:is_valid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfo<span class="token punctuation">:</span><span class="token function">is_valid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> boolean
</code></pre>
<p>This always returns true.</p>
<h1 id="kobold.worldinfo.folders">kobold.worldinfo.folders</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfo<span class="token punctuation">.</span>folders<span class="token punctuation">:</span> KoboldWorldInfoFolderSelector
</code></pre>
<p>Can be indexed in amortized constant worst-case time and iterated over and has a <code>finduid</code> method just like <code>kobold.worldinfo</code>, but gets folders (as <code>KoboldWorldInfoFolder</code> objects) instead.</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">local</span> folder <span class="token operator">=</span> kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">.</span>folders<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token comment">-- Retrieves fifth folder from top as a KoboldWorldInfoFolder</span>
</code></pre>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">for</span> index<span class="token punctuation">,</span> folder <span class="token keyword">in</span> <span class="token function">ipairs</span><span class="token punctuation">(</span>kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">.</span>folders<span class="token punctuation">)</span><span class="token punctuation">:</span>
<span class="token function">print</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> folder<span class="token punctuation">.</span>name<span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">for</span> index <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">#</span>kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">.</span>folders <span class="token keyword">do</span><span class="token punctuation">:</span>
<span class="token function">print</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span> kobold<span class="token punctuation">.</span>worldinfo<span class="token punctuation">.</span>folders<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">.</span>name<span class="token punctuation">)</span>
<span class="token keyword">end</span>
</code></pre>
<h3 id="methods-3">Methods</h3>
<ul>
<li><code>kobold.story.folders:finduid()</code></li>
<li><code>kobold.story.folders:is_valid()</code></li>
</ul>
<h1 id="koboldworldinfoentry">KoboldWorldInfoEntry</h1>
<p>Represents a world info entry.</p>
<h3 id="methods-4">Methods:</h3>
<ul>
<li><code>KoboldWorldInfoEntry:compute_context()</code></li>
<li><code>KoboldWorldInfoEntry:is_valid()</code></li>
</ul>
<h3 id="fields-3">Fields:</h3>
<ul>
<li><code>KoboldWorldInfoEntry.comment</code></li>
<li><code>KoboldWorldInfoEntry.constant</code></li>
<li><code>KoboldWorldInfoEntry.content</code></li>
<li><code>KoboldWorldInfoEntry.folder</code></li>
<li><code>KoboldWorldInfoEntry.key</code></li>
<li><code>KoboldWorldInfoEntry.keysecondary</code></li>
<li><code>KoboldWorldInfoEntry.num</code></li>
<li><code>KoboldWorldInfoEntry.selective</code></li>
<li><code>KoboldWorldInfoEntry.uid</code></li>
</ul>
<h1 id="koboldworldinfoentrycompute_context">KoboldWorldInfoEntry:compute_context()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoEntry<span class="token punctuation">:</span><span class="token function">compute_context</span><span class="token punctuation">(</span>submission<span class="token punctuation">:</span> string<span class="token punctuation">,</span> kwargs?<span class="token punctuation">:</span> table<span class="token operator">&lt;</span>string<span class="token punctuation">,</span> any<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> string
</code></pre>
<p>The same as calling <code>kobold.worldinfo:compute_context()</code> with this world info entry as the argument.</p>
<h3 id="parameters-6">Parameters</h3>
<ul>
<li>submission (<code>string</code>): String to use as simulated users input after being formatted by input formatting.</li>
<li>kwargs? (<code>table&lt;string, any&gt;</code>): Table of optional keyword arguments from the following list. Defaults to <code>{}</code>.
<ul>
<li>scan_story? (<code>boolean</code>): Whether or not to scan the past few actions of the story for world info keys in addition to the submission like how world info normally behaves. If this is set to <code>false</code>, only the <code>submission</code> is scanned for world info keys. Defaults to <code>true</code>.</li>
</ul>
</li>
</ul>
<h3 id="returns-5">Returns</h3>
<p><code>string</code>: Computed context.</p>
<h1 id="koboldworldinfoentryis_valid">KoboldWorldInfoEntry:is_valid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoEntry<span class="token punctuation">:</span><span class="token function">is_valid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> boolean
</code></pre>
<p>Returns true if this world info entry still exists (i.e. wasnt deleted), otherwise returns false.</p>
<h1 id="koboldworldinfoentry.comment">KoboldWorldInfoEntry.comment</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>comment<span class="token punctuation">:</span> string
</code></pre>
<p>The world info entrys comment that appears in its topmost text box.</p>
<h1 id="koboldworldinfoentry.constant">KoboldWorldInfoEntry.constant</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>constant<span class="token punctuation">:</span> boolean
</code></pre>
<p>Whether or not this world info entry is constant. Constant world info entries are always included in the context regardless of whether or not its keys match the story chunks in the context.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="koboldworldinfoentry.content">KoboldWorldInfoEntry.content</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>content<span class="token punctuation">:</span> string
</code></pre>
<p>The text in the “What To Remember” text box that gets included in the context when the world info entry is active.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="koboldworldinfoentry.folder">KoboldWorldInfoEntry.folder</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntryfolder<span class="token punctuation">:</span> integer?
</code></pre>
<p>UID of the folder the world info entry is in, or <code>nil</code> if its outside of a folder.</p>
<h1 id="koboldworldinfoentry.key">KoboldWorldInfoEntry.key</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>key<span class="token punctuation">:</span> string
</code></pre>
<p>For non-selective world info entries, this is the world info entrys comma-separated list of keys. For selective world info entries, this is the comma-separated list of primary keys.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="koboldworldinfoentry.keysecondary">KoboldWorldInfoEntry.keysecondary</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>keysecondary<span class="token punctuation">:</span> string
</code></pre>
<p>For non-selective world info entries, the value of this field is undefined and writing to it has no effect. For selective world info entries, this is the comma-separated list of secondary keys.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="koboldworldinfoentry.num">KoboldWorldInfoEntry.num</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>num<span class="token punctuation">:</span> integer
</code></pre>
<p>This is 0 if the entry is the first one from the top, 1 if second from the top, and so on.</p>
<h1 id="koboldworldinfoentry.selective">KoboldWorldInfoEntry.selective</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere (triggers regeneration when written to from generation modifier)</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>selective<span class="token punctuation">:</span> boolean
</code></pre>
<p>Whether or not the world info entry is selective. Selective entries have both primary and secondary keys.</p>
<p>Modifying this field from inside of a generation modifier triggers a regeneration, which means that the context is recomputed after modification and generation begins again with the new context and previously generated tokens. This incurs a small performance penalty and should not be performed in excess.</p>
<h1 id="koboldworldinfoentry.uid">KoboldWorldInfoEntry.uid</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoEntry<span class="token punctuation">.</span>uid<span class="token punctuation">:</span> integer
</code></pre>
<p>UID of the world info entry.</p>
<h1 id="koboldworldinfofolderselectorfinduid">KoboldWorldInfoFolderSelector:finduid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoFolderSelector<span class="token punctuation">:</span><span class="token function">finduid</span><span class="token punctuation">(</span>u<span class="token punctuation">:</span> integer<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> KoboldWorldInfoFolder?
</code></pre>
<p>Returns the world info folder with the given UID in amortized constant worst-case time, or <code>nil</code> if not found.</p>
<h3 id="parameters-7">Parameters</h3>
<ul>
<li>u (<code>integer</code>): UID.</li>
</ul>
<h3 id="returns-6">Returns</h3>
<ul>
<li><code>KoboldWorldInfoFolder?</code>: The world info folder with requested UID, or <code>nil</code> if no such folder exists.</li>
</ul>
<h1 id="koboldworldinfofolderselectoris_valid">KoboldWorldInfoFolderSelector:is_valid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoFolderSelector<span class="token punctuation">:</span><span class="token function">is_valid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> boolean
</code></pre>
<p>This always returns true.</p>
<h1 id="koboldworldinfofolder">KoboldWorldInfoFolder</h1>
<p>Represents a world info folder.</p>
<h3 id="methods-5">Methods:</h3>
<ul>
<li><code>KoboldWorldInfoFolder:compute_context()</code></li>
<li><code>KoboldWorldInfoFolder:finduid()</code></li>
<li><code>KoboldWorldInfoFolder:is_valid()</code></li>
</ul>
<h3 id="fields-4">Fields:</h3>
<ul>
<li><code>KoboldWorldInfoFolder.name</code></li>
<li><code>KoboldWorldInfoFolder.uid</code></li>
</ul>
<h1 id="koboldworldinfofoldercompute_context">KoboldWorldInfoFolder:compute_context()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoFolder<span class="token punctuation">:</span><span class="token function">compute_context</span><span class="token punctuation">(</span>submission<span class="token punctuation">:</span> string<span class="token punctuation">,</span> entries?<span class="token punctuation">:</span> KoboldWorldInfoEntry<span class="token operator">|</span>table<span class="token operator">&lt;</span>any<span class="token punctuation">,</span> KoboldWorldInfoEntry<span class="token operator">&gt;</span><span class="token punctuation">,</span> kwargs?<span class="token punctuation">:</span> table<span class="token operator">&lt;</span>string<span class="token punctuation">,</span> any<span class="token operator">&gt;</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> string
</code></pre>
<p>Computes the context that would be sent to the generator with the users current settings if <code>submission</code> were the users input after being formatted by input formatting. The context would include memory at the top, followed by active world info entries, followed by some story chunks with the authors note somewhere, followed by <code>submission</code>.</p>
<p>Unlike <code>kobold.worldinfo:compute_context()</code>, this function doesnt include world info keys outside of the folder.</p>
<h3 id="parameters-8">Parameters</h3>
<ul>
<li>submission (<code>string</code>): String to use as simulated users input after being formatted by input formatting.</li>
<li>entries? (<code>KoboldWorldInfoEntry|table&lt;any, KoboldWorldInfoEntry&gt;</code>): A <code>KoboldWorldInfoEntry</code> or table thereof that indicates an allowed subset of world info entries to include in the context. Entries that are not inside of the folder are still not included. Defaults to all world info entries in the folder.</li>
<li>kwargs? (<code>table&lt;string, any&gt;</code>): Table of optional keyword arguments from the following list. Defaults to <code>{}</code>.
<ul>
<li>scan_story? (<code>boolean</code>): Whether or not to scan the past few actions of the story for world info keys in addition to the submission like how world info normally behaves. If this is set to <code>false</code>, only the <code>submission</code> is scanned for world info keys. Defaults to <code>true</code>.</li>
</ul>
</li>
</ul>
<h3 id="returns-7">Returns</h3>
<p><code>string</code>: Computed context.</p>
<h1 id="koboldworldinfofolderfinduid">KoboldWorldInfoFolder:finduid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoFolder<span class="token punctuation">:</span><span class="token function">finduid</span><span class="token punctuation">(</span>u<span class="token punctuation">:</span> integer<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> KoboldWorldInfoEntry?
</code></pre>
<p>Returns the world info entry inside of the folder with the given UID in amortized constant worst-case time, or <code>nil</code> if not found.</p>
<h3 id="parameters-9">Parameters</h3>
<ul>
<li>u (<code>integer</code>): UID.</li>
</ul>
<h3 id="returns-8">Returns</h3>
<ul>
<li><code>KoboldWorldInfoEntry?</code>: The world info entry with requested UID, or <code>nil</code> if no such entry exists or if its outside of the folder.</li>
</ul>
<h1 id="koboldworldinfofolderis_valid">KoboldWorldInfoFolder:is_valid()</h1>
<p><em><strong>Callable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua"><span class="token keyword">function</span> KoboldWorldInfoFolder<span class="token punctuation">:</span><span class="token function">is_valid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> boolean
</code></pre>
<p>Returns whether or not the folder still exists (i.e. wasnt deleted).</p>
<h1 id="koboldworldinfofolder.name">KoboldWorldInfoFolder.name</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> anywhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoFolder<span class="token punctuation">.</span>name<span class="token punctuation">:</span> string
</code></pre>
<p>Name of the world info folder as defined in its one text box.</p>
<h1 id="koboldworldinfofolder.uid">KoboldWorldInfoFolder.uid</h1>
<p><em><strong>Readable from:</strong></em> anywhere<br>
<em><strong>Writable from:</strong></em> nowhere</p>
<pre class=" language-lua"><code class="prism language-lua">field KoboldWorldInfoFolder<span class="token punctuation">.</span>uid<span class="token punctuation">:</span> integer
</code></pre>
<p>UID of the world info folder.</p>
</div>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More