import os, copy os.environ["RWKV_JIT_ON"] = '1' os.environ["RWKV_CUDA_ON"] = '1' # if '1' then use CUDA kernel for seq mode (much faster) # make sure cuda dir is in the same level as modeling_rwkv.py from modeling_rwkv import RWKV import gc, re import gradio as gr import base64 from io import BytesIO import torch import torch.nn.functional as F from datetime import datetime from transformers import CLIPImageProcessor from huggingface_hub import hf_hub_download from pynvml import * nvmlInit() gpu_h = nvmlDeviceGetHandleByIndex(0) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") ctx_limit = 2500 gen_limit = 500 gen_limit_long = 800 ENABLE_VISUAL = False ########################## text rwkv ################################################################ from rwkv.utils import PIPELINE, PIPELINE_ARGS title_v6 = "RWKV-x060-World-3B-v2.1-20240417-ctx4096" model_path_v6 = hf_hub_download(repo_id="BlinkDL/rwkv-6-world", filename=f"{title_v6}.pth") # model_path_v6 = '/mnt/e/RWKV-Runner/models/rwkv-final-v6-2.1-3b' # conda activate torch2; cd /mnt/program/_RWKV_/_ref_/_gradio_/RWKV-Gradio-1; python app.py model_v6 = RWKV(model=model_path_v6, strategy='cuda fp16') pipeline_v6 = PIPELINE(model_v6, "rwkv_vocab_v20230424") args = model_v6.args eng_name = 'rwkv-x060-eng_single_round_qa-3B-20240516-ctx2048' chn_name = 'rwkv-x060-chn_single_round_qa-3B-20240516-ctx2048' # state_eng_raw = torch.load(f'/mnt/e/RWKV-Runner/models/{eng_name}.pth', map_location=torch.device('cpu')) # state_chn_raw = torch.load(f'/mnt/e/RWKV-Runner/models/{chn_name}.pth', map_location=torch.device('cpu')) eng_file = hf_hub_download(repo_id="BlinkDL/temp-latest-training-models", filename=f"{eng_name}.pth") chn_file = hf_hub_download(repo_id="BlinkDL/temp-latest-training-models", filename=f"{chn_name}.pth") state_eng_raw = torch.load(eng_file, map_location=torch.device('cpu')) state_chn_raw = torch.load(chn_file, map_location=torch.device('cpu')) state_eng = [None] * args.n_layer * 3 state_chn = [None] * args.n_layer * 3 for i in range(args.n_layer): dd = model_v6.strategy[i] dev = dd.device atype = dd.atype state_eng[i*3+0] = torch.zeros(args.n_embd, dtype=atype, requires_grad=False, device=dev).contiguous() state_chn[i*3+0] = torch.zeros(args.n_embd, dtype=atype, requires_grad=False, device=dev).contiguous() state_eng[i*3+1] = state_eng_raw[f'blocks.{i}.att.time_state'].transpose(1,2).to(dtype=torch.float, device=dev).requires_grad_(False).contiguous() state_chn[i*3+1] = state_chn_raw[f'blocks.{i}.att.time_state'].transpose(1,2).to(dtype=torch.float, device=dev).requires_grad_(False).contiguous() state_eng[i*3+2] = torch.zeros(args.n_embd, dtype=atype, requires_grad=False, device=dev).contiguous() state_chn[i*3+2] = torch.zeros(args.n_embd, dtype=atype, requires_grad=False, device=dev).contiguous() penalty_decay = 0.996 if ENABLE_VISUAL: title = "RWKV-5-World-1B5-v2-20231025-ctx4096" model_path = hf_hub_download(repo_id="BlinkDL/rwkv-5-world", filename=f"{title}.pth") model = RWKV(model=model_path, strategy='cuda fp16') pipeline = PIPELINE(model, "rwkv_vocab_v20230424") def generate_prompt(instruction, input=""): instruction = instruction.strip().replace('\r\n','\n').replace('\n\n','\n') input = input.strip().replace('\r\n','\n').replace('\n\n','\n') if input: return f"""Instruction: {instruction}\n\nInput: {input}\n\nResponse:""" else: return f"""User: hi\n\nAssistant: Hi. I am your assistant and I will provide expert full response in full details. Please feel free to ask any question and I will always answer it.\n\nUser: {instruction}\n\nAssistant:""" def qa_prompt(instruction): instruction = instruction.strip().replace('\r\n','\n') instruction = re.sub(r'\n+', '\n', instruction) return f"User: {instruction}\n\nAssistant:""" def evaluate( ctx, token_count=200, temperature=1.0, top_p=0.7, presencePenalty = 0.1, countPenalty = 0.1, ): args = PIPELINE_ARGS(temperature = max(0.2, float(temperature)), top_p = float(top_p), alpha_frequency = countPenalty, alpha_presence = presencePenalty, token_ban = [], # ban the generation of some tokens token_stop = [0]) # stop generation whenever you see any token here ctx = ctx.strip() all_tokens = [] out_last = 0 out_str = '' occurrence = {} state = None for i in range(int(token_count)): input_ids = pipeline_v6.encode(ctx)[-ctx_limit:] if i == 0 else [token] out, state = model_v6.forward(tokens=input_ids, state=state) for n in occurrence: out[n] -= (args.alpha_presence + occurrence[n] * args.alpha_frequency) token = pipeline_v6.sample_logits(out, temperature=args.temperature, top_p=args.top_p) if token in args.token_stop: break all_tokens += [token] for xxx in occurrence: occurrence[xxx] *= penalty_decay ttt = pipeline_v6.decode([token]) www = 1 if ttt in ' \t0123456789': www = 0 #elif ttt in '\r\n,.;?!"\':+-*/=#@$%^&_`~|<>\\()[]{},。;“”:?!()【】': # www = 0.5 if token not in occurrence: occurrence[token] = www else: occurrence[token] += www tmp = pipeline_v6.decode(all_tokens[out_last:]) if '\ufffd' not in tmp: out_str += tmp yield out_str.strip() out_last = i + 1 gpu_info = nvmlDeviceGetMemoryInfo(gpu_h) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f'{timestamp} - vram {gpu_info.total} used {gpu_info.used} free {gpu_info.free}') del out del state gc.collect() torch.cuda.empty_cache() yield out_str.strip() def evaluate_eng( ctx, token_count=200, temperature=1.0, top_p=0.7, presencePenalty = 0.1, countPenalty = 0.1, ): args = PIPELINE_ARGS(temperature = max(0.2, float(temperature)), top_p = float(top_p), alpha_frequency = countPenalty, alpha_presence = presencePenalty, token_ban = [], # ban the generation of some tokens token_stop = [0]) # stop generation whenever you see any token here ctx = qa_prompt(ctx) all_tokens = [] out_last = 0 out_str = '' occurrence = {} state = copy.deepcopy(state_eng) for i in range(int(token_count)): input_ids = pipeline_v6.encode(ctx)[-ctx_limit:] if i == 0 else [token] out, state = model_v6.forward(tokens=input_ids, state=state) for n in occurrence: out[n] -= (args.alpha_presence + occurrence[n] * args.alpha_frequency) token = pipeline_v6.sample_logits(out, temperature=args.temperature, top_p=args.top_p) if token in args.token_stop: break all_tokens += [token] for xxx in occurrence: occurrence[xxx] *= penalty_decay ttt = pipeline_v6.decode([token]) www = 1 if ttt in ' \t0123456789': www = 0 #elif ttt in '\r\n,.;?!"\':+-*/=#@$%^&_`~|<>\\()[]{},。;“”:?!()【】': # www = 0.5 if token not in occurrence: occurrence[token] = www else: occurrence[token] += www tmp = pipeline_v6.decode(all_tokens[out_last:]) if '\ufffd' not in tmp: out_str += tmp yield out_str.strip() out_last = i + 1 gpu_info = nvmlDeviceGetMemoryInfo(gpu_h) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f'{timestamp} - vram {gpu_info.total} used {gpu_info.used} free {gpu_info.free}') del out del state gc.collect() torch.cuda.empty_cache() yield out_str.strip() def evaluate_chn( ctx, token_count=200, temperature=1.0, top_p=0.7, presencePenalty = 0.1, countPenalty = 0.1, ): args = PIPELINE_ARGS(temperature = max(0.2, float(temperature)), top_p = float(top_p), alpha_frequency = countPenalty, alpha_presence = presencePenalty, token_ban = [], # ban the generation of some tokens token_stop = [0]) # stop generation whenever you see any token here ctx = qa_prompt(ctx) all_tokens = [] out_last = 0 out_str = '' occurrence = {} state = copy.deepcopy(state_chn) for i in range(int(token_count)): input_ids = pipeline_v6.encode(ctx)[-ctx_limit:] if i == 0 else [token] out, state = model_v6.forward(tokens=input_ids, state=state) for n in occurrence: out[n] -= (args.alpha_presence + occurrence[n] * args.alpha_frequency) token = pipeline_v6.sample_logits(out, temperature=args.temperature, top_p=args.top_p) if token in args.token_stop: break all_tokens += [token] for xxx in occurrence: occurrence[xxx] *= penalty_decay ttt = pipeline_v6.decode([token]) www = 1 if ttt in ' \t0123456789': www = 0 #elif ttt in '\r\n,.;?!"\':+-*/=#@$%^&_`~|<>\\()[]{},。;“”:?!()【】': # www = 0.5 if token not in occurrence: occurrence[token] = www else: occurrence[token] += www tmp = pipeline_v6.decode(all_tokens[out_last:]) if '\ufffd' not in tmp: out_str += tmp yield out_str.strip() out_last = i + 1 gpu_info = nvmlDeviceGetMemoryInfo(gpu_h) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f'{timestamp} - vram {gpu_info.total} used {gpu_info.used} free {gpu_info.free}') del out del state gc.collect() torch.cuda.empty_cache() yield out_str.strip() examples = [ ["Assistant: How can we craft an engaging story featuring vampires on Mars? Let's think step by step and provide an expert response.", gen_limit, 1, 0.3, 0.5, 0.5], ["Assistant: How can we persuade Elon Musk to follow you on Twitter? Let's think step by step and provide an expert response.", gen_limit, 1, 0.3, 0.5, 0.5], [generate_prompt("東京で訪れるべき素晴らしい場所とその紹介をいくつか挙げてください。"), gen_limit, 1, 0.3, 0.5, 0.5], [generate_prompt("Write a story using the following information.", "A man named Alex chops a tree down."), gen_limit, 1, 0.3, 0.5, 0.5], ["A few light taps upon the pane made her turn to the window. It had begun to snow again.", gen_limit, 1, 0.3, 0.5, 0.5], ['''Edward: I am Edward Elric from Fullmetal Alchemist.\n\nUser: Hello Edward. What have you been up to recently?\n\nEdward:''', gen_limit, 1, 0.3, 0.5, 0.5], [generate_prompt("Write a simple webpage. When a user clicks the button, it shows a random joke from a list of 4 jokes."), 500, 1, 0.3, 0.5, 0.5], ['''Japanese: 春の初め、桜の花が満開になる頃、小さな町の片隅にある古びた神社の境内は、特別な雰囲気に包まれていた。\n\nEnglish:''', gen_limit, 1, 0.3, 0.5, 0.5], ["En una pequeña aldea escondida entre las montañas de Andalucía, donde las calles aún conservaban el eco de antiguas leyendas, vivía un joven llamado Alejandro.", gen_limit, 1, 0.3, 0.5, 0.5], ["Dans le cœur battant de Paris, sous le ciel teinté d'un crépuscule d'or et de pourpre, se tenait une petite librairie oubliée par le temps.", gen_limit, 1, 0.3, 0.5, 0.5], ["في تطور مذهل وغير مسبوق، أعلنت السلطات المحلية في العاصمة عن اكتشاف أثري قد يغير مجرى التاريخ كما نعرفه.", gen_limit, 1, 0.3, 0.5, 0.5], ['''“当然可以,大宇宙不会因为这五公斤就不坍缩了。”关一帆说,他还有一个没说出来的想法:也许大宇宙真的会因为相差一个原子的质量而由封闭转为开放。大自然的精巧有时超出想象,比如生命的诞生,就需要各项宇宙参数在几亿亿分之一精度上的精确配合。但程心仍然可以留下她的生态球,因为在那无数文明创造的无数小宇宙中,肯定有相当一部分不响应回归运动的号召,所以,大宇宙最终被夺走的质量至少有几亿吨,甚至可能是几亿亿亿吨。\n但愿大宇宙能够忽略这个误差。\n程心和关一帆进入了飞船,智子最后也进来了。她早就不再穿那身华丽的和服了,她现在身着迷彩服,再次成为一名轻捷精悍的战士,她的身上佩带着许多武器和生存装备,最引人注目的是那把插在背后的武士刀。\n“放心,我在,你们就在!”智子对两位人类朋友说。\n聚变发动机启动了,推进器发出幽幽的蓝光,''', gen_limit, 1, 0.3, 0.5, 0.5], ] examples_eng = [ ["How can I craft an engaging story featuring vampires on Mars?", gen_limit_long, 1, 0.2, 0.3, 0.3], ["Compare the business models of Apple and Google.", gen_limit_long, 1, 0.2, 0.3, 0.3], ["In JSON format, list the top 5 tourist attractions in Paris.", gen_limit_long, 1, 0.2, 0.3, 0.3], ["Write an outline for a fantasy novel where dreams can alter reality.", gen_limit_long, 1, 0.2, 0.3, 0.3], ["Can fish get thirsty?", gen_limit_long, 1, 0.2, 0.3, 0.3], ["Write a Bash script to check disk usage and send alerts if it's too high.", gen_limit_long, 1, 0.2, 0.3, 0.3], ["Write a simple webpage. When a user clicks the button, it shows a random joke from a list of 4 jokes.", gen_limit_long, 1, 0.2, 0.3, 0.3], ] examples_chn = [ ["怎样写一个在火星上的吸血鬼的有趣故事?", gen_limit_long, 1, 0.2, 0.3, 0.3], ["比较苹果和谷歌的商业模式。", gen_limit_long, 1, 0.2, 0.3, 0.3], ["鱼会口渴吗?", gen_limit_long, 1, 0.2, 0.3, 0.3], ["以 JSON 格式列举北京的美食。", gen_limit_long, 1, 0.2, 0.3, 0.3], ["编写一个Bash脚本来检查磁盘使用情况,如果使用量过高则发送警报。", gen_limit_long, 1, 0.2, 0.3, 0.3], ["用HTML编写一个简单的网站。当用户点击按钮时,从4个笑话的列表中随机显示一个笑话。", gen_limit_long, 1, 0.2, 0.3, 0.3], ] if ENABLE_VISUAL: ########################## visual rwkv ################################################################ visual_title = 'ViusualRWKV-v5' rwkv_remote_path = "rwkv1b5-vitl336p14-577token_mix665k_rwkv.pth" vision_remote_path = "rwkv1b5-vitl336p14-577token_mix665k_visual.pth" vision_tower_name = 'openai/clip-vit-large-patch14-336' model_path = hf_hub_download(repo_id="howard-hou/visualrwkv-5", filename=rwkv_remote_path) visual_rwkv = RWKV(model=model_path, strategy='cuda fp16') ########################################################################## from modeling_vision import VisionEncoder, VisionEncoderConfig config = VisionEncoderConfig(n_embd=model.args.n_embd, vision_tower_name=vision_tower_name, grid_size=-1) visual_encoder = VisionEncoder(config) vision_local_path = hf_hub_download(repo_id="howard-hou/visualrwkv-5", filename=vision_remote_path) vision_state_dict = torch.load(vision_local_path, map_location='cpu') visual_encoder.load_state_dict(vision_state_dict) image_processor = CLIPImageProcessor.from_pretrained(vision_tower_name) visual_encoder = visual_encoder.to(device) ########################################################################## def visual_generate_prompt(instruction): instruction = instruction.strip().replace('\r\n','\n').replace('\n\n','\n') return f"\n{instruction}\n\nAssistant:" def generate( ctx, image_state, token_count=200, temperature=1.0, top_p=0.1, presencePenalty = 0.0, countPenalty = 1.0, ): args = PIPELINE_ARGS(temperature = 1.0, top_p = 0.1, alpha_frequency = 1.0, alpha_presence = 0.0, token_ban = [], # ban the generation of some tokens token_stop = [0, 261]) # stop generation whenever you see any token here ctx = ctx.strip() all_tokens = [] out_last = 0 out_str = '' occurrence = {} for i in range(int(token_count)): if i == 0: input_ids = pipeline.encode(ctx)[-ctx_limit:] out, state = visual_rwkv.forward(tokens=input_ids, state=image_state) else: input_ids = [token] out, state = visual_rwkv.forward(tokens=input_ids, state=state) for n in occurrence: out[n] -= (args.alpha_presence + occurrence[n] * args.alpha_frequency) token = pipeline.sample_logits(out, temperature=args.temperature, top_p=args.top_p) if token in args.token_stop: break all_tokens += [token] for xxx in occurrence: occurrence[xxx] *= 0.994 if token not in occurrence: occurrence[token] = 1 else: occurrence[token] += 1 tmp = pipeline.decode(all_tokens[out_last:]) if '\ufffd' not in tmp: out_str += tmp yield out_str.strip() out_last = i + 1 gpu_info = nvmlDeviceGetMemoryInfo(gpu_h) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f'{timestamp} - vram {gpu_info.total} used {gpu_info.used} free {gpu_info.free}') del out del state gc.collect() torch.cuda.empty_cache() yield out_str.strip() ########################################################################## cur_dir = os.path.dirname(os.path.abspath(__file__)) visual_examples = [ [ f"{cur_dir}/examples_pizza.jpg", "What are steps to cook it?" ], [ f"{cur_dir}/examples_bluejay.jpg", "what is the name of this bird?", ], [ f"{cur_dir}/examples_woman_and_dog.png", "describe this image", ], ] def pil_image_to_base64(pil_image): buffered = BytesIO() pil_image.save(buffered, format="JPEG") # You can change the format as needed (JPEG, PNG, etc.) # Encodes the image data into base64 format as a bytes object base64_image = base64.b64encode(buffered.getvalue()).decode('utf-8') return base64_image image_cache = {} ln0_weight = model.w['blocks.0.ln0.weight'].to(torch.float32).to(device) ln0_bias = model.w['blocks.0.ln0.bias'].to(torch.float32).to(device) def compute_image_state(image): base64_image = pil_image_to_base64(image) if base64_image in image_cache: image_state = image_cache[base64_image] else: image = image_processor(images=image.convert('RGB'), return_tensors='pt')['pixel_values'].to(device) image_features = visual_encoder.encode_images(image.unsqueeze(0)).squeeze(0) # [L, D] # apply layer norm to image feature, very important image_features = F.layer_norm(image_features, (image_features.shape[-1],), weight=ln0_weight, bias=ln0_bias) _, image_state = model.forward(embs=image_features, state=None) image_cache[base64_image] = image_state return image_state def chatbot(image, question): if image is None: yield "Please upload an image." return image_state = compute_image_state(image) input_text = visual_generate_prompt(question) for output in generate(input_text, image_state): yield output ################################################################################################################## with gr.Blocks(title=title_v6) as demo: gr.HTML(f"