AgainstEntropy/Kanji-Streaming
0
1import argparse2import os3from queue import SimpleQueue4from threading import Thread5from typing import Iterator6 7import gradio as gr8import spaces9import torch10from gradio import Chatbot11from huggingface_hub import InferenceClient12 13from image_utils import ImageStitcher14from StreamDiffusionIO import LatentConsistencyModelStreamIO15 16MAX_MAX_NEW_TOKENS = 204817DEFAULT_MAX_NEW_TOKENS = 102418MAX_INPUT_TOKEN_LENGTH = int(os.getenv("MAX_INPUT_TOKEN_LENGTH", "4096"))19 20DESCRIPTION = """\21# Kanji-Streaming Chat22 23๐ This Space is adapted from [Llama-2-7b-chat](https://huggingface.co/spaces/huggingface-projects/llama-2-7b-chat) space, demonstrating how to "chat" with LLM with [Kanji-Streaming](https://github.com/AgainstEntropy/kanji).24 25๐จ The technique behind Kanji-Streaming is [StreamDiffusionIO](https://github.com/AgainstEntropy/StreamDiffusionIO), which is based on [StreamDiffusion](https://github.com/cumulo-autumn/StreamDiffusion), *but especially allows to render text streams into image streams*.26 27๐ For more details about Kanji-Streaming, take a look at the [github repository](https://github.com/AgainstEntropy/kanji).28"""29 30LICENSE = """31<p/>32 33---34As a derivate work of [Llama-2-7b-chat](https://huggingface.co/meta-llama/Llama-2-7b-chat) by Meta,35this demo is governed by the original [license](https://huggingface.co/spaces/huggingface-projects/llama-2-7b-chat/blob/main/LICENSE.txt) and [acceptable use policy](https://huggingface.co/spaces/huggingface-projects/llama-2-7b-chat/blob/main/USE_POLICY.md).36"""37 38 39parser = argparse.ArgumentParser(description="Gradio launcher for Streaming-Kanji.")40parser.add_argument(41 "--sd_model_id_or_path",42 type=str,43 default="stable-diffusion-v1-5/stable-diffusion-v1-5",44 required=False,45 help="Path to downloaded sd-1-5 model or model identifier from huggingface.co/models.",46)47parser.add_argument(48 "--lora_path",49 type=str,50 default="AgainstEntropy/kanji-lora-sd-v1-5",51 required=False,52 help="Path to downloaded LoRA weight or model identifier from huggingface.co/models.",53)54parser.add_argument(55 "--lcm_lora_path",56 type=str,57 default="AgainstEntropy/kanji-lcm-lora-sd-v1-5",58 required=False,59 help="Path to downloaded LCM-LoRA weight or model identifier from huggingface.co/models.",60)61parser.add_argument(62 "--img_res",63 type=int,64 default=64,65 required=False,66 help="Image resolution for displaying Kanji characters in ChatBot.",67)68parser.add_argument(69 "--img_per_line",70 type=int,71 default=16,72 required=False,73 help="Number of Kanji characters to display in a single line.",74)75parser.add_argument(76 "--tmp_dir",77 type=str,78 default="./tmp",79 required=False,80 help="Path to save temporary images generated by StreamDiffusionIO.",81)82 83args = parser.parse_args()84 85if torch.cuda.is_available():86 device = "cuda"87else:88 device = "cpu"89 DESCRIPTION += "\n<p>Running on CPU ๐ฅถ This demo works best on GPU.</p>"90 91client = InferenceClient(92 model="mistralai/Mixtral-8x7B-Instruct-v0.1",93)94 95def format_prompt(message, history, system_prompt=''):96 prompt = f"<s> {system_prompt}"97 for user_prompt, bot_response in history:98 prompt += f"[INST] {user_prompt} [/INST]"99 if isinstance(bot_response, tuple):100 bot_response = bot_response[1]101 if not bot_response.endswith("</s>"):102 bot_response += "</s>"103 prompt += f" {bot_response} "104 prompt += f"[INST] {message} [/INST]"105 return prompt106 107lcm_stream = LatentConsistencyModelStreamIO(108 model_id_or_path=args.sd_model_id_or_path,109 lcm_lora_path=args.lcm_lora_path,110 lora_dict={args.lora_path: 1},111 resolution=128,112 device=device,113 use_xformers=True,114 verbose=True,115)116 117tmp_dir_template = f"{args.tmp_dir}/%d"118response_num = 0119 120stitcher = ImageStitcher(121 tmp_dir=tmp_dir_template % response_num,122 img_res=args.img_res,123 img_per_line=args.img_per_line,124 verbose=True,125)126 127 128@spaces.GPU129def generate(130 message: str,131 chat_history: list[tuple[str, str]],132 show_original_response: bool,133 seed: int,134 system_prompt: str = '',135 max_new_tokens: int = 1024,136 temperature: float = 0.6,137 top_p: float = 0.9,138 top_k: int = 50,139 repetition_penalty: float = 1.2,140) -> Iterator[str]:141 142 if temperature < 1e-2:143 temperature = 1e-2144 145 generate_kwargs = dict(146 max_new_tokens=max_new_tokens,147 do_sample=True,148 top_p=top_p,149 top_k=top_k,150 temperature=temperature,151 repetition_penalty=repetition_penalty,152 )153 formatted_prompt = format_prompt(message, chat_history, system_prompt)154 print(formatted_prompt)155 streamer = client.text_generation(formatted_prompt, **generate_kwargs, stream=True, details=True, return_full_text=False)156 157 outputs = []158 prompt_queue = SimpleQueue()159 160 lcm_stream.reset(seed)161 stitcher.reset()162 163 global response_num164 response_num += 1165 stitcher.update_tmp_dir(tmp_dir_template % response_num)166 167 def append_to_queue():168 for response in streamer:169 text = response.token.text170 outputs.append(text)171 prompt = text.strip()172 if prompt and prompt not in ['</s>']:173 if prompt.endswith("."): prompt = prompt[:-1]174 prompt_queue.put(prompt)175 prompt_queue.put(None)176 177 append_thread = Thread(target=append_to_queue)178 append_thread.start()179 180 def show_image(prompt: str = None):181 image, text = lcm_stream(prompt)182 img_path = None183 if image is not None:184 img_path = stitcher.add(image, text)185 return img_path186 187 while True:188 prompt = prompt_queue.get()189 if prompt is None:190 break191 img_path = show_image(prompt)192 if img_path is not None:193 yield (img_path, )194 195 # Continue to display the remaining images196 while True:197 img_path = show_image()198 if img_path is not None:199 yield (img_path, ''.join(outputs))200 if lcm_stream.stop():201 break202 203 print(outputs)204 if show_original_response:205 yield ''.join(outputs)206 207 208chat_interface = gr.ChatInterface(209 fn=generate,210 chatbot=Chatbot(height=400),211 additional_inputs=[212 gr.Checkbox(213 label="Show original response",214 value=False,215 ),216 gr.Number(217 label="Seed",218 info="Random Seed for Kanji Generation (maybe some kind of accent ๐ค)",219 step=1,220 value=1026,221 ),222 gr.Textbox(223 label="System prompt", 224 value="",225 lines=4),226 gr.Slider(227 label="Max new tokens",228 minimum=1,229 maximum=MAX_MAX_NEW_TOKENS,230 step=1,231 value=DEFAULT_MAX_NEW_TOKENS,232 ),233 gr.Slider(234 label="Temperature",235 minimum=0.1,236 maximum=4.0,237 step=0.1,238 value=0.6,239 ),240 gr.Slider(241 label="Top-p (nucleus sampling)",242 minimum=0.05,243 maximum=1.0,244 step=0.05,245 value=0.9,246 ),247 gr.Slider(248 label="Top-k",249 minimum=1,250 maximum=1000,251 step=1,252 value=50,253 ),254 gr.Slider(255 label="Repetition penalty",256 minimum=1.0,257 maximum=2.0,258 step=0.05,259 value=1.2,260 ),261 ],262 stop_btn=None,263 examples=[264 ["Hello there! How are you doing?"],265 ["Can you explain briefly to me what is the Python programming language?"],266 ["Explain the plot of Cinderella in a sentence."],267 ["How many hours does it take a man to eat a Helicopter?"],268 ["Write a 100-word article on 'Benefits of Open-Source in AI research'"],269 ],270)271 272with gr.Blocks(css="style.css") as demo:273 gr.Markdown(DESCRIPTION)274 gr.DuplicateButton(value="Duplicate Space for private use", elem_id="duplicate-button")275 chat_interface.render()276 gr.Markdown(LICENSE)277 278if __name__ == "__main__":279 demo.queue(max_size=20).launch(server_name="0.0.0.0", share=False, show_api=False)280 