├── .gitignore ├── requirements.txt ├── requirements-local.txt ├── src ├── utils.py ├── parsing.py ├── prompting.py ├── koboldai_client.py ├── model.py ├── app.py └── gradio_ui.py ├── README.md ├── notebooks └── GPU.ipynb └── LICENSE.md /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .venv 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | gradio<=3.18.0 2 | requests 3 | -------------------------------------------------------------------------------- /requirements-local.txt: -------------------------------------------------------------------------------- 1 | accelerate 2 | safetensors 3 | transformers 4 | -------------------------------------------------------------------------------- /src/utils.py: -------------------------------------------------------------------------------- 1 | def clear_stdout(): 2 | ''' 3 | Attempts to clear stdout, whether running in a notebook (IPython) or locally 4 | in a Unix envirnoment. 5 | ''' 6 | try: 7 | from IPython.display import clear_output 8 | clear_output(wait=True) 9 | except ImportError: 10 | import os 11 | os.system("clear") 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gradio-ui 2 | 3 | ## Attention: Unfortunately, any mention of "PygmalionAI" has been banned from Google Colab. Please seek other ways to use our Pygmalion models. We apologize for the inconvenience. 4 | --- 5 | 6 | **DEPRECIATED**: 7 | 8 | This is a prototype Gradio-based UI which allows you to chat with the [Pygmalion models](https://huggingface.co/PygmalionAI). 9 | 10 | We provide a notebook which directly interacts with this code in our repo, which can be found [here](./notebooks/GPU.ipynb). The notebook can either be run locally or can be used on [Google Colab](https://colab.research.google.com/github/PygmalionAI/gradio-ui/blob/master/notebooks/GPU.ipynb). 11 | -------------------------------------------------------------------------------- /src/parsing.py: -------------------------------------------------------------------------------- 1 | import re 2 | import typing as t 3 | 4 | def parse_messages_from_str(string: str, names: t.List[str]) -> t.List[str]: 5 | ''' 6 | Given a big string containing raw chat history, this function attempts to 7 | parse it out into a list where each item is an individual message. 8 | ''' 9 | sanitized_names = [ 10 | re.escape(name) for name in names 11 | ] 12 | 13 | speaker_regex = re.compile(rf"^({'|'.join(sanitized_names)}): ?", 14 | re.MULTILINE) 15 | 16 | message_start_indexes = [] 17 | for match in speaker_regex.finditer(string): 18 | message_start_indexes.append(match.start()) 19 | 20 | if len(message_start_indexes) < 2: 21 | # Single message in the string. 22 | return [string.strip()] 23 | 24 | prev_start_idx = message_start_indexes[0] 25 | messages = [] 26 | 27 | for start_idx in message_start_indexes[1:]: 28 | message = string[prev_start_idx:start_idx].strip() 29 | messages.append(message) 30 | prev_start_idx = start_idx 31 | 32 | # add the last message 33 | messages.append(string[prev_start_idx:].strip()) 34 | 35 | return messages 36 | 37 | 38 | def serialize_chat_history(history: t.List[str]) -> str: 39 | '''Given a structured chat history object, collapses it down to a string.''' 40 | return "\n".join(history) 41 | -------------------------------------------------------------------------------- /notebooks/GPU.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "colab_type": "text", 7 | "id": "view-in-github" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "attachments": {}, 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "Due to Colab cracking down on this notebook, we've been forced to take it offline for a while. We're really, really sorry about this.\n", 19 | "Please find other, alternative ways to use Pygmalion 6B.\n", 20 | "\n", 21 | "We'll try to be back soon. Our deepest apologies." 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [] 28 | } 29 | ], 30 | "metadata": { 31 | "accelerator": "GPU", 32 | "colab": { 33 | "provenance": [] 34 | }, 35 | "gpuClass": "standard", 36 | "kernelspec": { 37 | "display_name": "Python 3", 38 | "name": "python3" 39 | }, 40 | "language_info": { 41 | "name": "python" 42 | } 43 | }, 44 | "nbformat": 4, 45 | "nbformat_minor": 0 46 | } 47 | -------------------------------------------------------------------------------- /src/prompting.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import typing as t 3 | 4 | from parsing import parse_messages_from_str 5 | 6 | logger = logging.getLogger(__name__) 7 | 8 | 9 | def build_prompt_for( 10 | history: t.List[str], 11 | user_message: str, 12 | char_name: str, 13 | char_persona: t.Optional[str] = None, 14 | example_dialogue: t.Optional[str] = None, 15 | world_scenario: t.Optional[str] = None, 16 | ) -> str: 17 | '''Converts all the given stuff into a proper input prompt for the model.''' 18 | 19 | # If example dialogue is given, parse the history out from it and append 20 | # that at the beginning of the dialogue history. 21 | example_history = parse_messages_from_str( 22 | example_dialogue, ["You", char_name]) if example_dialogue else [] 23 | concatenated_history = [*example_history, *history] 24 | 25 | # Construct the base turns with the info we already have. 26 | prompt_turns = [ 27 | # TODO(11b): Shouldn't be here on the original 350M. 28 | "", 29 | 30 | # TODO(11b): Arbitrary limit. See if it's possible to vary this 31 | # based on available context size and VRAM instead. 32 | *concatenated_history[-8:], 33 | f"You: {user_message}", 34 | f"{char_name}:", 35 | ] 36 | 37 | # If we have a scenario or the character has a persona definition, add those 38 | # to the beginning of the prompt. 39 | if world_scenario: 40 | prompt_turns.insert( 41 | 0, 42 | f"Scenario: {world_scenario}", 43 | ) 44 | 45 | if char_persona: 46 | prompt_turns.insert( 47 | 0, 48 | f"{char_name}'s Persona: {char_persona}", 49 | ) 50 | 51 | # Done! 52 | logger.debug("Constructed prompt is: `%s`", prompt_turns) 53 | prompt_str = "\n".join(prompt_turns) 54 | return prompt_str 55 | -------------------------------------------------------------------------------- /src/koboldai_client.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import logging 3 | import time 4 | 5 | import requests 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | class KoboldApiServerException(Exception): 11 | pass 12 | 13 | 14 | def wait_for_kai_server(koboldai_url: str, max_wait_time_seconds: int) -> None: 15 | '''Blocks until the KAI server is up.''' 16 | start_time = datetime.datetime.now() 17 | 18 | while True: 19 | try: 20 | requests.head(koboldai_url, timeout=(5, 5)) 21 | break 22 | except requests.exceptions.ConnectionError as ex: 23 | if "Connection refused" not in str(ex): 24 | raise ex 25 | 26 | abort_at = start_time + datetime.timedelta( 27 | seconds=max_wait_time_seconds) 28 | 29 | if datetime.datetime.now() > abort_at: 30 | raise TimeoutError( 31 | f"Waited for {max_wait_time_seconds} seconds but KoboldAI" 32 | " server is still not up, aborting.") 33 | 34 | time.sleep(1) 35 | 36 | 37 | def run_raw_inference_on_kai( 38 | koboldai_url: str, 39 | prompt: str, 40 | max_new_tokens: int, 41 | do_sample: bool, 42 | typical_p: float, 43 | repetition_penalty: float, 44 | **kwargs, 45 | ) -> str: 46 | endpoint = f"{koboldai_url}/api/v1/generate" 47 | payload = { 48 | "prompt": prompt, 49 | 50 | # Incredibly low max len for reasons explained in the "while True" loop 51 | # below. 52 | "max_length": 32, 53 | 54 | # Take care of parameters which are named differently between Kobold and 55 | # HuggingFace. 56 | "sampler_full_determinism": not do_sample, 57 | "typical": typical_p, 58 | "rep_pen": repetition_penalty, 59 | 60 | # Disable any pre or post-processing on the KoboldAI side, we'd rather 61 | # take care of things on our own. 62 | "frmttriminc": False, 63 | "frmtrmspch": False, 64 | "frmtrmblln": False, 65 | "frmtadsnsp": False, 66 | 67 | # Append any other generation parameters that we didn't handle manually. 68 | **kwargs, 69 | } 70 | generated_text = "" 71 | 72 | # Currently, Kobold doesn't support custom stopping criteria, and their chat 73 | # mode can't handle multi-line responses. To work around both of those, we 74 | # use the regular adventure mode generation but keep asking for more tokens 75 | # until the model starts trying to talk as the user, then we stop. 76 | attempts = 0 77 | max_extra_attempts = 4 78 | while attempts < (payload["max_length"] / 79 | max_new_tokens) + max_extra_attempts: 80 | attempts += 1 81 | response = requests.post(endpoint, json=payload) 82 | if not response.ok: 83 | error_message = response.text 84 | raise KoboldApiServerException( 85 | "The KoboldAI API server returned an error" 86 | f" (HTTP status code {response.status_code}): {error_message}") 87 | 88 | inference_result = response.json()["results"][0]["text"] 89 | generated_text += inference_result 90 | 91 | # Model started to talk as us. Stop generating and return results, the 92 | # rest of the code will take care of trimming it properly. 93 | if "\nYou:" in generated_text: 94 | logger.debug("Hit `\nYou:`: `%s`", generated_text) 95 | return generated_text 96 | 97 | # For SFT: hit an EOS token. Trim and return. 98 | if generated_text.endswith("<|endoftext|>"): 99 | logger.debug("Got EOS token: `%s`", generated_text) 100 | 101 | # We add a fake generated "\nYou:" here so the trimming code doesn't 102 | # need to handle SFT and UFT models differently. 103 | return generated_text.replace("<|endoftext|>", "\nYou:") 104 | 105 | # Hit the configured generation limit. 106 | if len(generated_text.split()) >= max_new_tokens: 107 | logger.debug("Hit max length: `%s`", generated_text) 108 | return generated_text 109 | 110 | # Model still hasn't finished what it had to say. Append its output to 111 | # the prompt and feed it back in. 112 | logger.debug("Got another %s tokens, but still not done: `%s`", 113 | payload["max_length"], generated_text) 114 | payload["prompt"] += inference_result 115 | 116 | logger.debug("Exhausted generation attempts: `%s`", generated_text) 117 | return generated_text 118 | -------------------------------------------------------------------------------- /src/model.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import typing as t 3 | 4 | import torch 5 | import transformers 6 | 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | def build_model_and_tokenizer_for( 11 | model_name: str 12 | ) -> t.Tuple[transformers.AutoModelForCausalLM, transformers.AutoTokenizer]: 13 | '''Sets up the model and accompanying objects.''' 14 | logger.info(f"Loading tokenizer for {model_name}") 15 | tokenizer = transformers.AutoTokenizer.from_pretrained(model_name) 16 | 17 | # NOTE(11b): non-OPT models support passing this in at inference time, might 18 | # be worth refactoring for a debug version so we're able to experiment on 19 | # the fly 20 | bad_words_ids = [ 21 | tokenizer(bad_word, add_special_tokens=False).input_ids 22 | for bad_word in _build_bad_words_list_for(model_name) 23 | ] 24 | 25 | logger.info(f"Loading the {model_name} model") 26 | model = transformers.AutoModelForCausalLM.from_pretrained( 27 | model_name, bad_words_ids=bad_words_ids) 28 | model.eval().half().to("cuda") 29 | 30 | logger.info("Model and tokenizer are ready") 31 | return model, tokenizer 32 | 33 | 34 | def run_raw_inference(model: transformers.AutoModelForCausalLM, 35 | tokenizer: transformers.AutoTokenizer, prompt: str, 36 | user_message: str, **kwargs: t.Any) -> str: 37 | ''' 38 | Runs inference on the model, and attempts to returns only the newly 39 | generated text. 40 | 41 | :param model: Model to perform inference with. 42 | :param tokenizer: Tokenizer to tokenize input with. 43 | :param prompt: Input to feed to the model. 44 | :param user_message: The user's raw message, exactly as appended to the end 45 | of `prompt`. Used for trimming the original input from the model output. 46 | :return: Decoded model generation. 47 | ''' 48 | tokenized_items = tokenizer(prompt, return_tensors="pt").to("cuda") 49 | 50 | # Atrocious code to stop generation when the model outputs "\nYou: " in 51 | # freshly generated text. Feel free to send in a PR if you know of a 52 | # cleaner way to do this. 53 | stopping_criteria_list = transformers.StoppingCriteriaList([ 54 | _SentinelTokenStoppingCriteria( 55 | sentinel_token_ids=tokenizer( 56 | "\nYou:", 57 | add_special_tokens=False, 58 | return_tensors="pt", 59 | ).input_ids.to("cuda"), 60 | starting_idx=tokenized_items.input_ids.shape[-1]) 61 | ]) 62 | 63 | logits = model.generate(stopping_criteria=stopping_criteria_list, 64 | **tokenized_items, 65 | **kwargs) 66 | output = tokenizer.decode(logits[0], skip_special_tokens=True) 67 | 68 | logger.debug("Before trimming, model output was: `%s`", output) 69 | 70 | # Trim out the input prompt from the generated output. 71 | if (idx := prompt.rfind(user_message)) != -1: 72 | trimmed_output = output[idx + len(user_message) - 1:].strip() 73 | logger.debug("After trimming, it became: `%s`", trimmed_output) 74 | 75 | return trimmed_output 76 | else: 77 | raise Exception( 78 | "Couldn't find user message in the model's output. What?") 79 | 80 | 81 | def _build_bad_words_list_for(_model_name: str) -> t.List[str]: 82 | '''Builds a list of bad words for the given model.''' 83 | 84 | # NOTE(11b): This was implemented as a function because each model size 85 | # seems to have it quirks at the moment, but this is a rushed implementation 86 | # so I'm not handling that, hence the dumb return here. 87 | return ["Persona:", "Scenario:", ""] 88 | 89 | 90 | class _SentinelTokenStoppingCriteria(transformers.StoppingCriteria): 91 | 92 | def __init__(self, sentinel_token_ids: torch.LongTensor, 93 | starting_idx: int): 94 | transformers.StoppingCriteria.__init__(self) 95 | self.sentinel_token_ids = sentinel_token_ids 96 | self.starting_idx = starting_idx 97 | 98 | def __call__(self, input_ids: torch.LongTensor, 99 | _scores: torch.FloatTensor) -> bool: 100 | for sample in input_ids: 101 | trimmed_sample = sample[self.starting_idx:] 102 | # Can't unfold, output is still too tiny. Skip. 103 | if trimmed_sample.shape[-1] < self.sentinel_token_ids.shape[-1]: 104 | continue 105 | 106 | for window in trimmed_sample.unfold( 107 | 0, self.sentinel_token_ids.shape[-1], 1): 108 | if torch.all(torch.eq(self.sentinel_token_ids, window)): 109 | return True 110 | return False 111 | -------------------------------------------------------------------------------- /src/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import logging 4 | import typing as t 5 | 6 | from gradio_ui import build_gradio_ui_for 7 | from koboldai_client import run_raw_inference_on_kai, wait_for_kai_server 8 | from parsing import parse_messages_from_str 9 | from prompting import build_prompt_for 10 | from utils import clear_stdout 11 | 12 | logger = logging.getLogger(__name__) 13 | logging.basicConfig(level=logging.INFO) 14 | 15 | # For UI debugging purposes. 16 | DONT_USE_MODEL = False 17 | 18 | 19 | def main(server_port: int, 20 | share_gradio_link: bool = False, 21 | model_name: t.Optional[str] = None, 22 | koboldai_url: t.Optional[str] = None) -> None: 23 | '''Script entrypoint.''' 24 | if model_name and not DONT_USE_MODEL: 25 | from model import build_model_and_tokenizer_for, run_raw_inference 26 | model, tokenizer = build_model_and_tokenizer_for(model_name) 27 | else: 28 | model, tokenizer = None, None 29 | 30 | def inference_fn(history: t.List[str], user_input: str, 31 | generation_settings: t.Dict[str, t.Any], 32 | *char_settings: t.Any) -> str: 33 | if DONT_USE_MODEL: 34 | return "Mock response for UI tests." 35 | 36 | # Brittle. Comes from the order defined in gradio_ui.py. 37 | [ 38 | char_name, 39 | _user_name, 40 | char_persona, 41 | char_greeting, 42 | world_scenario, 43 | example_dialogue, 44 | ] = char_settings 45 | 46 | # If we're just starting the conversation and the character has a greeting 47 | # configured, return that instead. This is a workaround for the fact that 48 | # Gradio assumed that a chatbot cannot possibly start a conversation, so we 49 | # can't just have the greeting there automatically, it needs to be in 50 | # response to a user message. 51 | if len(history) == 0 and char_greeting is not None: 52 | return f"{char_name}: {char_greeting}" 53 | 54 | prompt = build_prompt_for(history=history, 55 | user_message=user_input, 56 | char_name=char_name, 57 | char_persona=char_persona, 58 | example_dialogue=example_dialogue, 59 | world_scenario=world_scenario) 60 | 61 | if model and tokenizer: 62 | model_output = run_raw_inference(model, tokenizer, prompt, 63 | user_input, **generation_settings) 64 | elif koboldai_url: 65 | model_output = f"{char_name}:" 66 | model_output += run_raw_inference_on_kai(koboldai_url, prompt, 67 | **generation_settings) 68 | else: 69 | raise Exception( 70 | "Not using local inference, but no Kobold instance URL was" 71 | " given. Nowhere to perform inference on.") 72 | 73 | generated_messages = parse_messages_from_str(model_output, 74 | ["You", char_name]) 75 | logger.debug("Parsed model response is: `%s`", generated_messages) 76 | bot_message = generated_messages[0] 77 | 78 | return bot_message 79 | 80 | ui = build_gradio_ui_for(inference_fn, for_kobold=koboldai_url is not None) 81 | ui.launch(server_port=server_port, share=share_gradio_link) 82 | 83 | 84 | def _parse_args_from_argv() -> argparse.Namespace: 85 | '''Parses arguments coming in from the command line.''' 86 | parser = argparse.ArgumentParser() 87 | parser.add_argument( 88 | "-m", 89 | "--model-name", 90 | help= 91 | "HuggingFace Transformers model name, if not using a KoboldAI instance as an inference server.", 92 | ) 93 | parser.add_argument( 94 | "-p", 95 | "--port", 96 | type=int, 97 | default=3000, 98 | help="Port to listen on.", 99 | ) 100 | parser.add_argument( 101 | "-k", 102 | "--koboldai-url", 103 | help="URL to a KoboldAI instance to use as an inference server.", 104 | ) 105 | parser.add_argument( 106 | "-s", 107 | "--share", 108 | action="store_true", 109 | help="Enable to generate a public link for the Gradio UI.", 110 | ) 111 | 112 | return parser.parse_args() 113 | 114 | 115 | if __name__ == "__main__": 116 | args = _parse_args_from_argv() 117 | 118 | if args.koboldai_url: 119 | # I have no idea how long a safe wait time is, but we'd rather wait for 120 | # too long rather than just cut the user off _right_ when the setup is 121 | # about to finish, so let's pick something absurd here. 122 | wait_for_kai_server(args.koboldai_url, max_wait_time_seconds=60 * 30) 123 | 124 | # Clear out any Kobold logs so the user can clearly see the Gradio link 125 | # that's about to show up afterwards. 126 | clear_stdout() 127 | 128 | main(model_name=args.model_name, 129 | server_port=args.port, 130 | koboldai_url=args.koboldai_url, 131 | share_gradio_link=args.share) 132 | -------------------------------------------------------------------------------- /src/gradio_ui.py: -------------------------------------------------------------------------------- 1 | import json 2 | import logging 3 | 4 | import gradio as gr 5 | 6 | 7 | def get_generation_defaults(for_kobold): 8 | defaults = { 9 | "do_sample": True, 10 | "max_new_tokens": 196, 11 | "temperature": 0.5, 12 | "top_p": 0.9, 13 | "top_k": 0, 14 | "typical_p": 1.0, 15 | "repetition_penalty": 1.05, 16 | } 17 | 18 | if for_kobold: 19 | defaults.update({"max_context_length": 768}) 20 | else: 21 | defaults.update({"penalty_alpha": 0.6}) 22 | 23 | return defaults 24 | 25 | 26 | logger = logging.getLogger(__name__) 27 | 28 | 29 | def build_gradio_ui_for(inference_fn, for_kobold): 30 | ''' 31 | Builds a Gradio UI to interact with the model. Big thanks to TearGosling for 32 | the initial version that inspired this. 33 | ''' 34 | with gr.Blocks(title="Pygmalion", analytics_enabled=False) as interface: 35 | history_for_gradio = gr.State([]) 36 | history_for_model = gr.State([]) 37 | generation_settings = gr.State( 38 | get_generation_defaults(for_kobold=for_kobold)) 39 | 40 | def _update_generation_settings( 41 | original_settings, 42 | param_name, 43 | new_value, 44 | ): 45 | ''' 46 | Merges `{param_name: new_value}` into `original_settings` and 47 | returns a new dictionary. 48 | ''' 49 | updated_settings = {**original_settings, param_name: new_value} 50 | logging.debug("Generation settings updated to: `%s`", 51 | updated_settings) 52 | return updated_settings 53 | 54 | def _run_inference( 55 | model_history, 56 | gradio_history, 57 | user_input, 58 | generation_settings, 59 | *char_setting_states, 60 | ): 61 | ''' 62 | Runs inference on the model, and formats the returned response for 63 | the Gradio state and chatbot component. 64 | ''' 65 | char_name = char_setting_states[0] 66 | user_name = char_setting_states[1] 67 | 68 | # If user input is blank, format it as if user was silent 69 | if user_input is None or user_input.strip() == "": 70 | user_input = "..." 71 | 72 | inference_result = inference_fn(model_history, user_input, 73 | generation_settings, 74 | *char_setting_states) 75 | 76 | inference_result_for_gradio = inference_result \ 77 | .replace(f"{char_name}:", f"**{char_name}:**") \ 78 | .replace("", user_name) \ 79 | .replace("\n", "
") # Gradio chatbot component can display br tag as linebreak 80 | 81 | model_history.append(f"You: {user_input}") 82 | model_history.append(inference_result) 83 | gradio_history.append((user_input, inference_result_for_gradio)) 84 | 85 | return None, model_history, gradio_history, gradio_history 86 | 87 | def _regenerate( 88 | model_history, 89 | gradio_history, 90 | generation_settings, 91 | *char_setting_states, 92 | ): 93 | '''Regenerates the last response.''' 94 | return _run_inference( 95 | model_history[:-2], 96 | gradio_history[:-1], 97 | model_history[-2].replace("You: ", ""), 98 | generation_settings, 99 | *char_setting_states, 100 | ) 101 | 102 | def _undo_last_exchange(model_history, gradio_history): 103 | '''Undoes the last exchange (message pair).''' 104 | return model_history[:-2], gradio_history[:-1], gradio_history[:-1] 105 | 106 | def _save_chat_history(model_history, *char_setting_states): 107 | '''Saves the current chat history to a .json file.''' 108 | char_name = char_setting_states[0] 109 | with open(f"{char_name}_conversation.json", "w") as f: 110 | f.write(json.dumps({"chat": model_history})) 111 | return f"{char_name}_conversation.json" 112 | 113 | def _load_chat_history(file_obj, *char_setting_states): 114 | '''Loads up a chat history from a .json file.''' 115 | # ############################################################################################# 116 | # TODO(TG): Automatically detect and convert any CAI dump files loaded in to Pygmalion format # 117 | # ############################################################################################# 118 | 119 | # https://stackoverflow.com/questions/5389507/iterating-over-every-two-elements-in-a-list 120 | def pairwise(iterable): 121 | # "s -> (s0, s1), (s2, s3), (s4, s5), ..." 122 | a = iter(iterable) 123 | return zip(a, a) 124 | 125 | char_name = char_setting_states[0] 126 | user_name = char_setting_states[1] 127 | 128 | file_data = json.loads(file_obj.decode('utf-8')) 129 | model_history = file_data["chat"] 130 | # Construct a new gradio history 131 | new_gradio_history = [] 132 | for human_turn, bot_turn in pairwise(model_history): 133 | # Handle the situation where convo history may be loaded before character defs 134 | if char_name == "": 135 | # Grab char name from the model history 136 | char_name = bot_turn.split(":")[0] 137 | # Format the user and bot utterances 138 | user_turn = human_turn.replace("You: ", "") 139 | bot_turn = bot_turn.replace(f"{char_name}:", f"**{char_name}:**") 140 | 141 | # Somebody released a script on /g/ which tries to convert CAI dump logs 142 | # to Pygmalion character settings and chats. The anonymization of the dumps, however, means that 143 | # [NAME_IN_MESSAGE_REDACTED] is left in the conversational history. We obviously wouldn't want this 144 | # This therefore accomodates users of that script, so that [NAME_IN_MESSAGE_REDACTED] doesn't have 145 | # to be manually edited in the conversation JSON. 146 | # The model shouldn't generate [NAME_IN_MESSAGE_REDACTED] by itself. 147 | user_turn = user_turn.replace("[NAME_IN_MESSAGE_REDACTED]", user_name) 148 | bot_turn = bot_turn.replace("[NAME_IN_MESSAGE_REDACTED]", user_name) 149 | 150 | new_gradio_history.append((user_turn, bot_turn)) 151 | 152 | return model_history, new_gradio_history, new_gradio_history 153 | 154 | with gr.Tab("Character Settings") as settings_tab: 155 | charfile, char_setting_states = _build_character_settings_ui() 156 | 157 | with gr.Tab("Chat Window"): 158 | chatbot = gr.Chatbot( 159 | label="Your conversation will show up here").style( 160 | color_map=("#326efd", "#212528")) 161 | 162 | char_name, _user_name, char_persona, char_greeting, world_scenario, example_dialogue = char_setting_states 163 | charfile.upload( 164 | fn=_char_file_upload, 165 | inputs=[charfile, history_for_model, history_for_gradio], 166 | outputs=[history_for_model, history_for_gradio, chatbot, char_name, char_persona, char_greeting, world_scenario, example_dialogue] 167 | ) 168 | 169 | message = gr.Textbox( 170 | label="Your message (hit Enter to send)", 171 | placeholder="Write a message...", 172 | ) 173 | message.submit( 174 | fn=_run_inference, 175 | inputs=[ 176 | history_for_model, history_for_gradio, message, 177 | generation_settings, *char_setting_states 178 | ], 179 | outputs=[ 180 | message, history_for_model, history_for_gradio, chatbot 181 | ], 182 | ) 183 | 184 | with gr.Row(): 185 | send_btn = gr.Button("Send", variant="primary") 186 | send_btn.click( 187 | fn=_run_inference, 188 | inputs=[ 189 | history_for_model, history_for_gradio, message, 190 | generation_settings, *char_setting_states 191 | ], 192 | outputs=[ 193 | message, history_for_model, history_for_gradio, chatbot 194 | ], 195 | ) 196 | 197 | regenerate_btn = gr.Button("Regenerate") 198 | regenerate_btn.click( 199 | fn=_regenerate, 200 | inputs=[ 201 | history_for_model, history_for_gradio, 202 | generation_settings, *char_setting_states 203 | ], 204 | outputs=[ 205 | message, history_for_model, history_for_gradio, chatbot 206 | ], 207 | ) 208 | 209 | undo_btn = gr.Button("Undo last exchange") 210 | undo_btn.click( 211 | fn=_undo_last_exchange, 212 | inputs=[history_for_model, history_for_gradio], 213 | outputs=[history_for_model, history_for_gradio, chatbot], 214 | ) 215 | 216 | with gr.Row(): 217 | with gr.Column(): 218 | chatfile = gr.File(type="binary", file_types=[".json"], interactive=True) 219 | chatfile.upload( 220 | fn=_load_chat_history, 221 | inputs=[chatfile, *char_setting_states], 222 | outputs=[history_for_model, history_for_gradio, chatbot] 223 | ) 224 | 225 | save_char_btn = gr.Button(value="Save Conversation History") 226 | save_char_btn.click(_save_chat_history, inputs=[history_for_model, *char_setting_states], outputs=[chatfile]) 227 | with gr.Column(): 228 | gr.Markdown(""" 229 | ### To save a chat 230 | Click "Save Conversation History". The file will appear above the button and you can click to download it. 231 | 232 | ### To load a chat 233 | Drag a valid .json file onto the upload box, or click the box to browse. 234 | 235 | **Remember to fill out/load up your character definitions before resuming a chat!** 236 | """) 237 | 238 | 239 | 240 | with gr.Tab("Generation Settings"): 241 | _build_generation_settings_ui( 242 | state=generation_settings, 243 | fn=_update_generation_settings, 244 | for_kobold=for_kobold, 245 | ) 246 | 247 | return interface 248 | 249 | 250 | def _char_file_upload(file_obj, history_model, history_gradio): 251 | file_data = json.loads(file_obj.decode('utf-8')) 252 | char_name = file_data["char_name"] 253 | greeting = file_data["char_greeting"] 254 | empty_history = not history_model or (len(history_model) <= 2 and history_model[0] == '') 255 | if empty_history and char_name and greeting: 256 | # if chat history is empty so far, and there is a character greeting, add character greeting to the chat 257 | s = f'{char_name}: {greeting}' 258 | t = f'**{char_name}**: {greeting}' 259 | history_model = ['', s] 260 | history_gradio = [('', t)] 261 | return history_model, history_gradio, history_gradio, char_name, file_data["char_persona"], greeting, file_data["world_scenario"], file_data["example_dialogue"] 262 | 263 | def _build_character_settings_ui(): 264 | 265 | def char_file_create(char_name, char_persona, char_greeting, world_scenario, example_dialogue): 266 | with open(char_name + ".json", "w") as f: 267 | f.write(json.dumps({"char_name": char_name, "char_persona": char_persona, "char_greeting": char_greeting, "world_scenario": world_scenario, "example_dialogue": example_dialogue})) 268 | return char_name + ".json" 269 | 270 | with gr.Column(): 271 | with gr.Row(): 272 | char_name = gr.Textbox( 273 | label="Character Name", 274 | placeholder="The character's name", 275 | ) 276 | user_name = gr.Textbox( 277 | label="Your Name", 278 | placeholder="How the character should call you", 279 | ) 280 | 281 | char_persona = gr.Textbox( 282 | label="Character Persona", 283 | placeholder= 284 | "Describe the character's persona here. Think of this as CharacterAI's description + definitions in one box.", 285 | lines=4, 286 | ) 287 | char_greeting = gr.Textbox( 288 | label="Character Greeting", 289 | placeholder= 290 | "Write the character's greeting here. They will say this verbatim as their first response.", 291 | lines=3, 292 | ) 293 | 294 | world_scenario = gr.Textbox( 295 | label="Scenario", 296 | placeholder= 297 | "Optionally, describe the starting scenario in a few short sentences.", 298 | ) 299 | example_dialogue = gr.Textbox( 300 | label="Example Chat", 301 | placeholder= 302 | "Optionally, write in an example chat here. This is useful for showing how the character should behave, for example.", 303 | lines=4, 304 | ) 305 | 306 | with gr.Row(): 307 | with gr.Column(): 308 | charfile = gr.File(type="binary", file_types=[".json"]) 309 | 310 | save_char_btn = gr.Button(value="Generate Character File") 311 | save_char_btn.click(char_file_create, inputs=[char_name, char_persona, char_greeting, world_scenario, example_dialogue], outputs=[charfile]) 312 | with gr.Column(): 313 | gr.Markdown(""" 314 | ### To save a character 315 | Click "Generate Character File". The file will appear above the button and you can click to download it. 316 | 317 | ### To upload a character 318 | Drag a valid .json file onto the upload box, or click the box to browse. 319 | """) 320 | 321 | return charfile, (char_name, user_name, char_persona, char_greeting, world_scenario, example_dialogue) 322 | 323 | 324 | def _build_generation_settings_ui(state, fn, for_kobold): 325 | generation_defaults = get_generation_defaults(for_kobold=for_kobold) 326 | 327 | with gr.Row(): 328 | with gr.Column(): 329 | max_new_tokens = gr.Slider( 330 | 16, 331 | 512, 332 | value=generation_defaults["max_new_tokens"], 333 | step=4, 334 | label="max_new_tokens", 335 | ) 336 | max_new_tokens.change( 337 | lambda state, value: fn(state, "max_new_tokens", value), 338 | inputs=[state, max_new_tokens], 339 | outputs=state, 340 | ) 341 | 342 | temperature = gr.Slider( 343 | 0.1, 344 | 2, 345 | value=generation_defaults["temperature"], 346 | step=0.01, 347 | label="temperature", 348 | ) 349 | temperature.change( 350 | lambda state, value: fn(state, "temperature", value), 351 | inputs=[state, temperature], 352 | outputs=state, 353 | ) 354 | 355 | top_p = gr.Slider( 356 | 0.0, 357 | 1.0, 358 | value=generation_defaults["top_p"], 359 | step=0.01, 360 | label="top_p", 361 | ) 362 | top_p.change( 363 | lambda state, value: fn(state, "top_p", value), 364 | inputs=[state, top_p], 365 | outputs=state, 366 | ) 367 | 368 | with gr.Column(): 369 | typical_p = gr.Slider( 370 | 0.0, 371 | 1.0, 372 | value=generation_defaults["typical_p"], 373 | step=0.01, 374 | label="typical_p", 375 | ) 376 | typical_p.change( 377 | lambda state, value: fn(state, "typical_p", value), 378 | inputs=[state, typical_p], 379 | outputs=state, 380 | ) 381 | 382 | repetition_penalty = gr.Slider( 383 | 1.0, 384 | 3.0, 385 | value=generation_defaults["repetition_penalty"], 386 | step=0.01, 387 | label="repetition_penalty", 388 | ) 389 | repetition_penalty.change( 390 | lambda state, value: fn(state, "repetition_penalty", value), 391 | inputs=[state, repetition_penalty], 392 | outputs=state, 393 | ) 394 | 395 | top_k = gr.Slider( 396 | 0, 397 | 100, 398 | value=generation_defaults["top_k"], 399 | step=1, 400 | label="top_k", 401 | ) 402 | top_k.change( 403 | lambda state, value: fn(state, "top_k", value), 404 | inputs=[state, top_k], 405 | outputs=state, 406 | ) 407 | 408 | if not for_kobold: 409 | penalty_alpha = gr.Slider( 410 | 0, 411 | 1, 412 | value=generation_defaults["penalty_alpha"], 413 | step=0.05, 414 | label="penalty_alpha", 415 | ) 416 | penalty_alpha.change( 417 | lambda state, value: fn(state, "penalty_alpha", value), 418 | inputs=[state, penalty_alpha], 419 | outputs=state, 420 | ) 421 | 422 | # 423 | # Some of these explanations are taken from Kobold: 424 | # https://github.com/KoboldAI/KoboldAI-Client/blob/main/gensettings.py 425 | # 426 | # They're passed directly into the `generate` call, so they should exist here: 427 | # https://huggingface.co/docs/transformers/main_classes/text_generation#transformers.GenerationConfig 428 | # 429 | with gr.Accordion(label="Helpful information", open=False): 430 | gr.Markdown(""" 431 | Here's a basic rundown of each setting: 432 | 433 | - `max_new_tokens`: Number of tokens the AI should generate. Higher numbers will take longer to generate. 434 | - `temperature`: Randomness of sampling. High values can increase creativity but may make text less sensible. Lower values will make text more predictable but can become repetitious. 435 | - `top_p`: Used to discard unlikely text in the sampling process. Lower values will make text more predictable but can become repetitious. (Put this value on 1 to disable its effect) 436 | - `top_k`: Alternative sampling method, can be combined with top_p. The number of highest probability vocabulary tokens to keep for top-k-filtering. (Put this value on 0 to disable its effect) 437 | - `typical_p`: Alternative sampling method described in the paper "Typical_p Decoding for Natural Language Generation" (10.48550/ARXIV.2202.00666). The paper suggests 0.2 as a good value for this setting. Set this setting to 1 to disable its effect. 438 | - `repetition_penalty`: Used to penalize words that were already generated or belong to the context (Going over 1.2 breaks 6B models. Set to 1.0 to disable). 439 | - `penalty_alpha`: The alpha coefficient when using contrastive search. 440 | 441 | Some settings might not show up depending on which inference backend is being used. 442 | """) 443 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### GNU AFFERO GENERAL PUBLIC LICENSE 2 | 3 | Version 3, 19 November 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | ### Preamble 12 | 13 | The GNU Affero General Public License is a free, copyleft license for 14 | software and other kinds of works, specifically designed to ensure 15 | cooperation with the community in the case of network server software. 16 | 17 | The licenses for most software and other practical works are designed 18 | to take away your freedom to share and change the works. By contrast, 19 | our General Public Licenses are intended to guarantee your freedom to 20 | share and change all versions of a program--to make sure it remains 21 | free software for all its users. 22 | 23 | When we speak of free software, we are referring to freedom, not 24 | price. Our General Public Licenses are designed to make sure that you 25 | have the freedom to distribute copies of free software (and charge for 26 | them if you wish), that you receive source code or can get it if you 27 | want it, that you can change the software or use pieces of it in new 28 | free programs, and that you know you can do these things. 29 | 30 | Developers that use our General Public Licenses protect your rights 31 | with two steps: (1) assert copyright on the software, and (2) offer 32 | you this License which gives you legal permission to copy, distribute 33 | and/or modify the software. 34 | 35 | A secondary benefit of defending all users' freedom is that 36 | improvements made in alternate versions of the program, if they 37 | receive widespread use, become available for other developers to 38 | incorporate. Many developers of free software are heartened and 39 | encouraged by the resulting cooperation. However, in the case of 40 | software used on network servers, this result may fail to come about. 41 | The GNU General Public License permits making a modified version and 42 | letting the public access it on a server without ever releasing its 43 | source code to the public. 44 | 45 | The GNU Affero General Public License is designed specifically to 46 | ensure that, in such cases, the modified source code becomes available 47 | to the community. It requires the operator of a network server to 48 | provide the source code of the modified version running there to the 49 | users of that server. Therefore, public use of a modified version, on 50 | a publicly accessible server, gives the public access to the source 51 | code of the modified version. 52 | 53 | An older license, called the Affero General Public License and 54 | published by Affero, was designed to accomplish similar goals. This is 55 | a different license, not a version of the Affero GPL, but Affero has 56 | released a new version of the Affero GPL which permits relicensing 57 | under this license. 58 | 59 | The precise terms and conditions for copying, distribution and 60 | modification follow. 61 | 62 | ### TERMS AND CONDITIONS 63 | 64 | #### 0. Definitions. 65 | 66 | "This License" refers to version 3 of the GNU Affero General Public 67 | License. 68 | 69 | "Copyright" also means copyright-like laws that apply to other kinds 70 | of works, such as semiconductor masks. 71 | 72 | "The Program" refers to any copyrightable work licensed under this 73 | License. Each licensee is addressed as "you". "Licensees" and 74 | "recipients" may be individuals or organizations. 75 | 76 | To "modify" a work means to copy from or adapt all or part of the work 77 | in a fashion requiring copyright permission, other than the making of 78 | an exact copy. The resulting work is called a "modified version" of 79 | the earlier work or a work "based on" the earlier work. 80 | 81 | A "covered work" means either the unmodified Program or a work based 82 | on the Program. 83 | 84 | To "propagate" a work means to do anything with it that, without 85 | permission, would make you directly or secondarily liable for 86 | infringement under applicable copyright law, except executing it on a 87 | computer or modifying a private copy. Propagation includes copying, 88 | distribution (with or without modification), making available to the 89 | public, and in some countries other activities as well. 90 | 91 | To "convey" a work means any kind of propagation that enables other 92 | parties to make or receive copies. Mere interaction with a user 93 | through a computer network, with no transfer of a copy, is not 94 | conveying. 95 | 96 | An interactive user interface displays "Appropriate Legal Notices" to 97 | the extent that it includes a convenient and prominently visible 98 | feature that (1) displays an appropriate copyright notice, and (2) 99 | tells the user that there is no warranty for the work (except to the 100 | extent that warranties are provided), that licensees may convey the 101 | work under this License, and how to view a copy of this License. If 102 | the interface presents a list of user commands or options, such as a 103 | menu, a prominent item in the list meets this criterion. 104 | 105 | #### 1. Source Code. 106 | 107 | The "source code" for a work means the preferred form of the work for 108 | making modifications to it. "Object code" means any non-source form of 109 | a work. 110 | 111 | A "Standard Interface" means an interface that either is an official 112 | standard defined by a recognized standards body, or, in the case of 113 | interfaces specified for a particular programming language, one that 114 | is widely used among developers working in that language. 115 | 116 | The "System Libraries" of an executable work include anything, other 117 | than the work as a whole, that (a) is included in the normal form of 118 | packaging a Major Component, but which is not part of that Major 119 | Component, and (b) serves only to enable use of the work with that 120 | Major Component, or to implement a Standard Interface for which an 121 | implementation is available to the public in source code form. A 122 | "Major Component", in this context, means a major essential component 123 | (kernel, window system, and so on) of the specific operating system 124 | (if any) on which the executable work runs, or a compiler used to 125 | produce the work, or an object code interpreter used to run it. 126 | 127 | The "Corresponding Source" for a work in object code form means all 128 | the source code needed to generate, install, and (for an executable 129 | work) run the object code and to modify the work, including scripts to 130 | control those activities. However, it does not include the work's 131 | System Libraries, or general-purpose tools or generally available free 132 | programs which are used unmodified in performing those activities but 133 | which are not part of the work. For example, Corresponding Source 134 | includes interface definition files associated with source files for 135 | the work, and the source code for shared libraries and dynamically 136 | linked subprograms that the work is specifically designed to require, 137 | such as by intimate data communication or control flow between those 138 | subprograms and other parts of the work. 139 | 140 | The Corresponding Source need not include anything that users can 141 | regenerate automatically from other parts of the Corresponding Source. 142 | 143 | The Corresponding Source for a work in source code form is that same 144 | work. 145 | 146 | #### 2. Basic Permissions. 147 | 148 | All rights granted under this License are granted for the term of 149 | copyright on the Program, and are irrevocable provided the stated 150 | conditions are met. This License explicitly affirms your unlimited 151 | permission to run the unmodified Program. The output from running a 152 | covered work is covered by this License only if the output, given its 153 | content, constitutes a covered work. This License acknowledges your 154 | rights of fair use or other equivalent, as provided by copyright law. 155 | 156 | You may make, run and propagate covered works that you do not convey, 157 | without conditions so long as your license otherwise remains in force. 158 | You may convey covered works to others for the sole purpose of having 159 | them make modifications exclusively for you, or provide you with 160 | facilities for running those works, provided that you comply with the 161 | terms of this License in conveying all material for which you do not 162 | control copyright. Those thus making or running the covered works for 163 | you must do so exclusively on your behalf, under your direction and 164 | control, on terms that prohibit them from making any copies of your 165 | copyrighted material outside their relationship with you. 166 | 167 | Conveying under any other circumstances is permitted solely under the 168 | conditions stated below. Sublicensing is not allowed; section 10 makes 169 | it unnecessary. 170 | 171 | #### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 172 | 173 | No covered work shall be deemed part of an effective technological 174 | measure under any applicable law fulfilling obligations under article 175 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 176 | similar laws prohibiting or restricting circumvention of such 177 | measures. 178 | 179 | When you convey a covered work, you waive any legal power to forbid 180 | circumvention of technological measures to the extent such 181 | circumvention is effected by exercising rights under this License with 182 | respect to the covered work, and you disclaim any intention to limit 183 | operation or modification of the work as a means of enforcing, against 184 | the work's users, your or third parties' legal rights to forbid 185 | circumvention of technological measures. 186 | 187 | #### 4. Conveying Verbatim Copies. 188 | 189 | You may convey verbatim copies of the Program's source code as you 190 | receive it, in any medium, provided that you conspicuously and 191 | appropriately publish on each copy an appropriate copyright notice; 192 | keep intact all notices stating that this License and any 193 | non-permissive terms added in accord with section 7 apply to the code; 194 | keep intact all notices of the absence of any warranty; and give all 195 | recipients a copy of this License along with the Program. 196 | 197 | You may charge any price or no price for each copy that you convey, 198 | and you may offer support or warranty protection for a fee. 199 | 200 | #### 5. Conveying Modified Source Versions. 201 | 202 | You may convey a work based on the Program, or the modifications to 203 | produce it from the Program, in the form of source code under the 204 | terms of section 4, provided that you also meet all of these 205 | conditions: 206 | 207 | - a) The work must carry prominent notices stating that you modified 208 | it, and giving a relevant date. 209 | - b) The work must carry prominent notices stating that it is 210 | released under this License and any conditions added under 211 | section 7. This requirement modifies the requirement in section 4 212 | to "keep intact all notices". 213 | - c) You must license the entire work, as a whole, under this 214 | License to anyone who comes into possession of a copy. This 215 | License will therefore apply, along with any applicable section 7 216 | additional terms, to the whole of the work, and all its parts, 217 | regardless of how they are packaged. This License gives no 218 | permission to license the work in any other way, but it does not 219 | invalidate such permission if you have separately received it. 220 | - d) If the work has interactive user interfaces, each must display 221 | Appropriate Legal Notices; however, if the Program has interactive 222 | interfaces that do not display Appropriate Legal Notices, your 223 | work need not make them do so. 224 | 225 | A compilation of a covered work with other separate and independent 226 | works, which are not by their nature extensions of the covered work, 227 | and which are not combined with it such as to form a larger program, 228 | in or on a volume of a storage or distribution medium, is called an 229 | "aggregate" if the compilation and its resulting copyright are not 230 | used to limit the access or legal rights of the compilation's users 231 | beyond what the individual works permit. Inclusion of a covered work 232 | in an aggregate does not cause this License to apply to the other 233 | parts of the aggregate. 234 | 235 | #### 6. Conveying Non-Source Forms. 236 | 237 | You may convey a covered work in object code form under the terms of 238 | sections 4 and 5, provided that you also convey the machine-readable 239 | Corresponding Source under the terms of this License, in one of these 240 | ways: 241 | 242 | - a) Convey the object code in, or embodied in, a physical product 243 | (including a physical distribution medium), accompanied by the 244 | Corresponding Source fixed on a durable physical medium 245 | customarily used for software interchange. 246 | - b) Convey the object code in, or embodied in, a physical product 247 | (including a physical distribution medium), accompanied by a 248 | written offer, valid for at least three years and valid for as 249 | long as you offer spare parts or customer support for that product 250 | model, to give anyone who possesses the object code either (1) a 251 | copy of the Corresponding Source for all the software in the 252 | product that is covered by this License, on a durable physical 253 | medium customarily used for software interchange, for a price no 254 | more than your reasonable cost of physically performing this 255 | conveying of source, or (2) access to copy the Corresponding 256 | Source from a network server at no charge. 257 | - c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | - d) Convey the object code by offering access from a designated 263 | place (gratis or for a charge), and offer equivalent access to the 264 | Corresponding Source in the same way through the same place at no 265 | further charge. You need not require recipients to copy the 266 | Corresponding Source along with the object code. If the place to 267 | copy the object code is a network server, the Corresponding Source 268 | may be on a different server (operated by you or a third party) 269 | that supports equivalent copying facilities, provided you maintain 270 | clear directions next to the object code saying where to find the 271 | Corresponding Source. Regardless of what server hosts the 272 | Corresponding Source, you remain obligated to ensure that it is 273 | available for as long as needed to satisfy these requirements. 274 | - e) Convey the object code using peer-to-peer transmission, 275 | provided you inform other peers where the object code and 276 | Corresponding Source of the work are being offered to the general 277 | public at no charge under subsection 6d. 278 | 279 | A separable portion of the object code, whose source code is excluded 280 | from the Corresponding Source as a System Library, need not be 281 | included in conveying the object code work. 282 | 283 | A "User Product" is either (1) a "consumer product", which means any 284 | tangible personal property which is normally used for personal, 285 | family, or household purposes, or (2) anything designed or sold for 286 | incorporation into a dwelling. In determining whether a product is a 287 | consumer product, doubtful cases shall be resolved in favor of 288 | coverage. For a particular product received by a particular user, 289 | "normally used" refers to a typical or common use of that class of 290 | product, regardless of the status of the particular user or of the way 291 | in which the particular user actually uses, or expects or is expected 292 | to use, the product. A product is a consumer product regardless of 293 | whether the product has substantial commercial, industrial or 294 | non-consumer uses, unless such uses represent the only significant 295 | mode of use of the product. 296 | 297 | "Installation Information" for a User Product means any methods, 298 | procedures, authorization keys, or other information required to 299 | install and execute modified versions of a covered work in that User 300 | Product from a modified version of its Corresponding Source. The 301 | information must suffice to ensure that the continued functioning of 302 | the modified object code is in no case prevented or interfered with 303 | solely because modification has been made. 304 | 305 | If you convey an object code work under this section in, or with, or 306 | specifically for use in, a User Product, and the conveying occurs as 307 | part of a transaction in which the right of possession and use of the 308 | User Product is transferred to the recipient in perpetuity or for a 309 | fixed term (regardless of how the transaction is characterized), the 310 | Corresponding Source conveyed under this section must be accompanied 311 | by the Installation Information. But this requirement does not apply 312 | if neither you nor any third party retains the ability to install 313 | modified object code on the User Product (for example, the work has 314 | been installed in ROM). 315 | 316 | The requirement to provide Installation Information does not include a 317 | requirement to continue to provide support service, warranty, or 318 | updates for a work that has been modified or installed by the 319 | recipient, or for the User Product in which it has been modified or 320 | installed. Access to a network may be denied when the modification 321 | itself materially and adversely affects the operation of the network 322 | or violates the rules and protocols for communication across the 323 | network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | #### 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders 351 | of that material) supplement the terms of this License with terms: 352 | 353 | - a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | - b) Requiring preservation of specified reasonable legal notices or 356 | author attributions in that material or in the Appropriate Legal 357 | Notices displayed by works containing it; or 358 | - c) Prohibiting misrepresentation of the origin of that material, 359 | or requiring that modified versions of such material be marked in 360 | reasonable ways as different from the original version; or 361 | - d) Limiting the use for publicity purposes of names of licensors 362 | or authors of the material; or 363 | - e) Declining to grant rights under trademark law for use of some 364 | trade names, trademarks, or service marks; or 365 | - f) Requiring indemnification of licensors and authors of that 366 | material by anyone who conveys the material (or modified versions 367 | of it) with contractual assumptions of liability to the recipient, 368 | for any liability that these contractual assumptions directly 369 | impose on those licensors and authors. 370 | 371 | All other non-permissive additional terms are considered "further 372 | restrictions" within the meaning of section 10. If the Program as you 373 | received it, or any part of it, contains a notice stating that it is 374 | governed by this License along with a term that is a further 375 | restriction, you may remove that term. If a license document contains 376 | a further restriction but permits relicensing or conveying under this 377 | License, you may add to a covered work material governed by the terms 378 | of that license document, provided that the further restriction does 379 | not survive such relicensing or conveying. 380 | 381 | If you add terms to a covered work in accord with this section, you 382 | must place, in the relevant source files, a statement of the 383 | additional terms that apply to those files, or a notice indicating 384 | where to find the applicable terms. 385 | 386 | Additional terms, permissive or non-permissive, may be stated in the 387 | form of a separately written license, or stated as exceptions; the 388 | above requirements apply either way. 389 | 390 | #### 8. Termination. 391 | 392 | You may not propagate or modify a covered work except as expressly 393 | provided under this License. Any attempt otherwise to propagate or 394 | modify it is void, and will automatically terminate your rights under 395 | this License (including any patent licenses granted under the third 396 | paragraph of section 11). 397 | 398 | However, if you cease all violation of this License, then your license 399 | from a particular copyright holder is reinstated (a) provisionally, 400 | unless and until the copyright holder explicitly and finally 401 | terminates your license, and (b) permanently, if the copyright holder 402 | fails to notify you of the violation by some reasonable means prior to 403 | 60 days after the cessation. 404 | 405 | Moreover, your license from a particular copyright holder is 406 | reinstated permanently if the copyright holder notifies you of the 407 | violation by some reasonable means, this is the first time you have 408 | received notice of violation of this License (for any work) from that 409 | copyright holder, and you cure the violation prior to 30 days after 410 | your receipt of the notice. 411 | 412 | Termination of your rights under this section does not terminate the 413 | licenses of parties who have received copies or rights from you under 414 | this License. If your rights have been terminated and not permanently 415 | reinstated, you do not qualify to receive new licenses for the same 416 | material under section 10. 417 | 418 | #### 9. Acceptance Not Required for Having Copies. 419 | 420 | You are not required to accept this License in order to receive or run 421 | a copy of the Program. Ancillary propagation of a covered work 422 | occurring solely as a consequence of using peer-to-peer transmission 423 | to receive a copy likewise does not require acceptance. However, 424 | nothing other than this License grants you permission to propagate or 425 | modify any covered work. These actions infringe copyright if you do 426 | not accept this License. Therefore, by modifying or propagating a 427 | covered work, you indicate your acceptance of this License to do so. 428 | 429 | #### 10. Automatic Licensing of Downstream Recipients. 430 | 431 | Each time you convey a covered work, the recipient automatically 432 | receives a license from the original licensors, to run, modify and 433 | propagate that work, subject to this License. You are not responsible 434 | for enforcing compliance by third parties with this License. 435 | 436 | An "entity transaction" is a transaction transferring control of an 437 | organization, or substantially all assets of one, or subdividing an 438 | organization, or merging organizations. If propagation of a covered 439 | work results from an entity transaction, each party to that 440 | transaction who receives a copy of the work also receives whatever 441 | licenses to the work the party's predecessor in interest had or could 442 | give under the previous paragraph, plus a right to possession of the 443 | Corresponding Source of the work from the predecessor in interest, if 444 | the predecessor has it or can get it with reasonable efforts. 445 | 446 | You may not impose any further restrictions on the exercise of the 447 | rights granted or affirmed under this License. For example, you may 448 | not impose a license fee, royalty, or other charge for exercise of 449 | rights granted under this License, and you may not initiate litigation 450 | (including a cross-claim or counterclaim in a lawsuit) alleging that 451 | any patent claim is infringed by making, using, selling, offering for 452 | sale, or importing the Program or any portion of it. 453 | 454 | #### 11. Patents. 455 | 456 | A "contributor" is a copyright holder who authorizes use under this 457 | License of the Program or a work on which the Program is based. The 458 | work thus licensed is called the contributor's "contributor version". 459 | 460 | A contributor's "essential patent claims" are all patent claims owned 461 | or controlled by the contributor, whether already acquired or 462 | hereafter acquired, that would be infringed by some manner, permitted 463 | by this License, of making, using, or selling its contributor version, 464 | but do not include claims that would be infringed only as a 465 | consequence of further modification of the contributor version. For 466 | purposes of this definition, "control" includes the right to grant 467 | patent sublicenses in a manner consistent with the requirements of 468 | this License. 469 | 470 | Each contributor grants you a non-exclusive, worldwide, royalty-free 471 | patent license under the contributor's essential patent claims, to 472 | make, use, sell, offer for sale, import and otherwise run, modify and 473 | propagate the contents of its contributor version. 474 | 475 | In the following three paragraphs, a "patent license" is any express 476 | agreement or commitment, however denominated, not to enforce a patent 477 | (such as an express permission to practice a patent or covenant not to 478 | sue for patent infringement). To "grant" such a patent license to a 479 | party means to make such an agreement or commitment not to enforce a 480 | patent against the party. 481 | 482 | If you convey a covered work, knowingly relying on a patent license, 483 | and the Corresponding Source of the work is not available for anyone 484 | to copy, free of charge and under the terms of this License, through a 485 | publicly available network server or other readily accessible means, 486 | then you must either (1) cause the Corresponding Source to be so 487 | available, or (2) arrange to deprive yourself of the benefit of the 488 | patent license for this particular work, or (3) arrange, in a manner 489 | consistent with the requirements of this License, to extend the patent 490 | license to downstream recipients. "Knowingly relying" means you have 491 | actual knowledge that, but for the patent license, your conveying the 492 | covered work in a country, or your recipient's use of the covered work 493 | in a country, would infringe one or more identifiable patents in that 494 | country that you have reason to believe are valid. 495 | 496 | If, pursuant to or in connection with a single transaction or 497 | arrangement, you convey, or propagate by procuring conveyance of, a 498 | covered work, and grant a patent license to some of the parties 499 | receiving the covered work authorizing them to use, propagate, modify 500 | or convey a specific copy of the covered work, then the patent license 501 | you grant is automatically extended to all recipients of the covered 502 | work and works based on it. 503 | 504 | A patent license is "discriminatory" if it does not include within the 505 | scope of its coverage, prohibits the exercise of, or is conditioned on 506 | the non-exercise of one or more of the rights that are specifically 507 | granted under this License. You may not convey a covered work if you 508 | are a party to an arrangement with a third party that is in the 509 | business of distributing software, under which you make payment to the 510 | third party based on the extent of your activity of conveying the 511 | work, and under which the third party grants, to any of the parties 512 | who would receive the covered work from you, a discriminatory patent 513 | license (a) in connection with copies of the covered work conveyed by 514 | you (or copies made from those copies), or (b) primarily for and in 515 | connection with specific products or compilations that contain the 516 | covered work, unless you entered into that arrangement, or that patent 517 | license was granted, prior to 28 March 2007. 518 | 519 | Nothing in this License shall be construed as excluding or limiting 520 | any implied license or other defenses to infringement that may 521 | otherwise be available to you under applicable patent law. 522 | 523 | #### 12. No Surrender of Others' Freedom. 524 | 525 | If conditions are imposed on you (whether by court order, agreement or 526 | otherwise) that contradict the conditions of this License, they do not 527 | excuse you from the conditions of this License. If you cannot convey a 528 | covered work so as to satisfy simultaneously your obligations under 529 | this License and any other pertinent obligations, then as a 530 | consequence you may not convey it at all. For example, if you agree to 531 | terms that obligate you to collect a royalty for further conveying 532 | from those to whom you convey the Program, the only way you could 533 | satisfy both those terms and this License would be to refrain entirely 534 | from conveying the Program. 535 | 536 | #### 13. Remote Network Interaction; Use with the GNU General Public License. 537 | 538 | Notwithstanding any other provision of this License, if you modify the 539 | Program, your modified version must prominently offer all users 540 | interacting with it remotely through a computer network (if your 541 | version supports such interaction) an opportunity to receive the 542 | Corresponding Source of your version by providing access to the 543 | Corresponding Source from a network server at no charge, through some 544 | standard or customary means of facilitating copying of software. This 545 | Corresponding Source shall include the Corresponding Source for any 546 | work covered by version 3 of the GNU General Public License that is 547 | incorporated pursuant to the following paragraph. 548 | 549 | Notwithstanding any other provision of this License, you have 550 | permission to link or combine any covered work with a work licensed 551 | under version 3 of the GNU General Public License into a single 552 | combined work, and to convey the resulting work. The terms of this 553 | License will continue to apply to the part which is the covered work, 554 | but the work with which it is combined will remain governed by version 555 | 3 of the GNU General Public License. 556 | 557 | #### 14. Revised Versions of this License. 558 | 559 | The Free Software Foundation may publish revised and/or new versions 560 | of the GNU Affero General Public License from time to time. Such new 561 | versions will be similar in spirit to the present version, but may 562 | differ in detail to address new problems or concerns. 563 | 564 | Each version is given a distinguishing version number. If the Program 565 | specifies that a certain numbered version of the GNU Affero General 566 | Public License "or any later version" applies to it, you have the 567 | option of following the terms and conditions either of that numbered 568 | version or of any later version published by the Free Software 569 | Foundation. If the Program does not specify a version number of the 570 | GNU Affero General Public License, you may choose any version ever 571 | published by the Free Software Foundation. 572 | 573 | If the Program specifies that a proxy can decide which future versions 574 | of the GNU Affero General Public License can be used, that proxy's 575 | public statement of acceptance of a version permanently authorizes you 576 | to choose that version for the Program. 577 | 578 | Later license versions may give you additional or different 579 | permissions. However, no additional obligations are imposed on any 580 | author or copyright holder as a result of your choosing to follow a 581 | later version. 582 | 583 | #### 15. Disclaimer of Warranty. 584 | 585 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 586 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 587 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT 588 | WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 589 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 590 | A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 591 | PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 592 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 593 | CORRECTION. 594 | 595 | #### 16. Limitation of Liability. 596 | 597 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 598 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR 599 | CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 600 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES 601 | ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT 602 | NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 603 | LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM 604 | TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER 605 | PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 606 | 607 | #### 17. Interpretation of Sections 15 and 16. 608 | 609 | If the disclaimer of warranty and limitation of liability provided 610 | above cannot be given local legal effect according to their terms, 611 | reviewing courts shall apply local law that most closely approximates 612 | an absolute waiver of all civil liability in connection with the 613 | Program, unless a warranty or assumption of liability accompanies a 614 | copy of the Program in return for a fee. 615 | 616 | END OF TERMS AND CONDITIONS 617 | 618 | ### How to Apply These Terms to Your New Programs 619 | 620 | If you develop a new program, and you want it to be of the greatest 621 | possible use to the public, the best way to achieve this is to make it 622 | free software which everyone can redistribute and change under these 623 | terms. 624 | 625 | To do so, attach the following notices to the program. It is safest to 626 | attach them to the start of each source file to most effectively state 627 | the exclusion of warranty; and each file should have at least the 628 | "copyright" line and a pointer to where the full notice is found. 629 | 630 | 631 | Copyright (C) 632 | 633 | This program is free software: you can redistribute it and/or modify 634 | it under the terms of the GNU Affero General Public License as 635 | published by the Free Software Foundation, either version 3 of the 636 | License, or (at your option) any later version. 637 | 638 | This program is distributed in the hope that it will be useful, 639 | but WITHOUT ANY WARRANTY; without even the implied warranty of 640 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 641 | GNU Affero General Public License for more details. 642 | 643 | You should have received a copy of the GNU Affero General Public License 644 | along with this program. If not, see . 645 | 646 | Also add information on how to contact you by electronic and paper 647 | mail. 648 | 649 | If your software can interact with users remotely through a computer 650 | network, you should also make sure that it provides a way for users to 651 | get its source. For example, if your program is a web application, its 652 | interface could display a "Source" link that leads users to an archive 653 | of the code. There are many ways you could offer source, and different 654 | solutions will be better for different programs; see section 13 for 655 | the specific requirements. 656 | 657 | You should also get your employer (if you work as a programmer) or 658 | school, if any, to sign a "copyright disclaimer" for the program, if 659 | necessary. For more information on this, and how to apply and follow 660 | the GNU AGPL, see . 661 | --------------------------------------------------------------------------------