Spaces:
Runtime error
Runtime error
from typing import Text, Any, Dict, Optional | |
import json | |
import copy | |
import tensorflow as tf | |
import tensorflow_text | |
from tensorflow.python.saved_model import tag_constants | |
from huggingface_hub import Repository | |
import gradio as gr | |
from pingpong import PingPong | |
from pingpong.gradio import GradioAlpacaChatPPManager | |
from pingpong.context import CtxLastWindowStrategy | |
local_path = "hf_model" | |
model_version = "v1687590401" | |
model_repo_id = "chansung/kerasnlp-gpt2-alpaca-pipeline" | |
model_repo_url = f"https://huggingface.co/{model_repo_id}" | |
def _clone_and_checkout(repo_url: str, local_path: str, version: str) -> Repository: | |
repository = Repository( | |
local_dir=local_path, clone_from=repo_url | |
) | |
repository.git_checkout(revision=version) | |
return repository | |
_ = _clone_and_checkout(model_repo_url, local_path, model_version) | |
model = tf.saved_model.load(local_path, tags=[tag_constants.SERVING]) | |
gpt_lm_predict_fn = model.signatures["serving_default"] | |
STYLE = """ | |
.custom-btn { | |
border: none !important; | |
background: none !important; | |
box-shadow: none !important; | |
display: block !important; | |
text-align: left !important; | |
} | |
.custom-btn:hover { | |
background: rgb(243 244 246) !important; | |
} | |
.custom-btn-highlight { | |
border: none !important; | |
background: rgb(243 244 246) !important; | |
box-shadow: none !important; | |
display: block !important; | |
text-align: left !important; | |
} | |
#prompt-txt > label > span { | |
display: none !important; | |
} | |
#prompt-txt > label > textarea { | |
border: transparent; | |
box-shadow: none; | |
} | |
#chatbot { | |
height: 800px; | |
overflow: auto; | |
box-shadow: none !important; | |
border: none !important; | |
} | |
#chatbot > .wrap { | |
max-height: 780px; | |
} | |
#chatbot + div { | |
border-radius: 35px !important; | |
width: 80% !important; | |
margin: auto !important; | |
} | |
#left-pane { | |
background-color: #f9fafb; | |
border-radius: 15px; | |
padding: 10px; | |
} | |
#left-top { | |
padding-left: 10px; | |
padding-right: 10px; | |
text-align: center; | |
font-weight: bold; | |
font-size: large; | |
} | |
#chat-history-accordion { | |
background: transparent; | |
border: 0.8px !important; | |
} | |
#right-pane { | |
margin-left: 20px; | |
margin-right: 70px; | |
} | |
#initial-popup { | |
z-index: 100; | |
position: absolute; | |
width: 50%; | |
top: 50%; | |
height: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
border-radius: 35px; | |
padding: 15px; | |
} | |
#initial-popup-title { | |
text-align: center; | |
font-size: 18px; | |
font-weight: bold; | |
} | |
#initial-popup-left-pane { | |
min-width: 150px !important; | |
} | |
#initial-popup-right-pane { | |
text-align: right; | |
} | |
.example-btn { | |
padding-top: 20px !important; | |
padding-bottom: 20px !important; | |
padding-left: 5px !important; | |
padding-right: 5px !important; | |
background: linear-gradient(to bottom right, #f7faff, #ffffff) !important; | |
box-shadow: none !important; | |
border-radius: 20px !important; | |
} | |
.example-btn:hover { | |
box-shadow: 0.3px 0.3px 0.3px gray !important; | |
} | |
#example-title { | |
margin-bottom: 15px; | |
} | |
#aux-btns-popup { | |
z-index: 200; | |
position: absolute !important; | |
bottom: 75px !important; | |
right: 15px !important; | |
} | |
#aux-btns-popup > div { | |
flex-wrap: nowrap; | |
width: auto; | |
margin: auto; | |
} | |
.aux-btn { | |
height: 30px !important; | |
flex-wrap: initial !important; | |
flex: none !important; | |
min-width: min(100px,100%) !important; | |
font-weight: unset !important; | |
font-size: 10pt !important; | |
background: linear-gradient(to bottom right, #f7faff, #ffffff) !important; | |
box-shadow: none !important; | |
border-radius: 20px !important; | |
} | |
.aux-btn:hover { | |
box-shadow: 0.3px 0.3px 0.3px gray !important; | |
} | |
""" | |
get_local_storage = """ | |
function() { | |
globalThis.setStorage = (key, value)=>{ | |
localStorage.setItem(key, JSON.stringify(value)); | |
} | |
globalThis.getStorage = (key, value)=>{ | |
return JSON.parse(localStorage.getItem(key)); | |
} | |
var local_data = getStorage('local_data'); | |
var history = []; | |
if(local_data) { | |
local_data[0].pingpongs.forEach(element =>{ | |
history.push([element.ping, element.pong]); | |
}); | |
} | |
else { | |
local_data = []; | |
for (let step = 0; step < 10; step++) { | |
local_data.push({'ctx': '', 'pingpongs':[]}); | |
} | |
setStorage('local_data', local_data); | |
} | |
if(history.length == 0) { | |
document.querySelector("#initial-popup").classList.remove('hide'); | |
} | |
return [history, local_data]; | |
} | |
""" | |
update_left_btns_state = """ | |
(v)=>{ | |
document.querySelector('.custom-btn-highlight').classList.add('custom-btn'); | |
document.querySelector('.custom-btn-highlight').classList.remove('custom-btn-highlight'); | |
const elements = document.querySelectorAll(".custom-btn"); | |
for(var i=0; i < elements.length; i++) { | |
const element = elements[i]; | |
if(element.textContent == v) { | |
console.log(v); | |
element.classList.add('custom-btn-highlight'); | |
element.classList.remove('custom-btn'); | |
break; | |
} | |
} | |
}""" | |
channels = [ | |
"1st Channel", | |
"2nd Channel", | |
"3rd Channel", | |
"4th Channel", | |
"5th Channel", | |
"6th Channel", | |
"7th Channel", | |
"8th Channel", | |
"9th Channel", | |
"10th Channel" | |
] | |
channel_btns = [] | |
examples = [ | |
"hello world", | |
"what's up?", | |
"this is GradioChat" | |
] | |
ex_btns = [] | |
def reset_chat(idx, ld): | |
res = [GradioAlpacaChatPPManager.from_json(json.dumps(ppm)) for ppm in ld] | |
res[idx].pingpongs = [] | |
return ( | |
"", | |
[], | |
str(res), | |
gr.update(visible=True), | |
gr.update(interactive=False), | |
) | |
def build_prompts(ppmanager): | |
dummy_ppm = copy.deepcopy(ppmanager) | |
dummy_ppm.ctx = """Below are a series of dialogues between human and an AI assistant. | |
The AI tries to answer the given instruction as in response. | |
The AI MUST not generate any text containing `### Response` or `### Instruction`. | |
The AI MUST be helpful, polite, honest, sophisticated, emotionally aware, and humble-but-knowledgeable. | |
The assistant MUST be happy to help with almost anything, and will do its best to understand exactly what is needed. | |
It also MUST avoid giving false or misleading information, and it caveats when it isn’t entirely sure about the right answer. | |
That said, the assistant is practical and really does its best, and doesn’t let caution get too much in the way of being useful. | |
""" | |
return CtxLastWindowStrategy(3)(dummy_ppm) | |
def add_pingpong(idx, ld, ping): | |
res = [GradioAlpacaChatPPManager.from_json(json.dumps(ppm)) for ppm in ld] | |
ppm = res[idx] | |
ppm.add_pingpong( | |
PingPong(ping, "") | |
) | |
prompt = tf.constant(build_prompts(ppm)) | |
max_length = tf.constant(512, dtype="int64") | |
print(f"Prompt:\n{prompt}") | |
result = gpt_lm_predict_fn( | |
prompt=prompt, | |
max_length=max_length, | |
)['result'].numpy().decode('UTF-8') | |
result = result.split("### Response:")[-1].strip() | |
ppm.add_pong(result) | |
print(f"res:\n{str(res)}") | |
return "", ppm.build_uis(), str(res) | |
def channel_num(btn_title): | |
choice = 0 | |
for idx, channel in enumerate(channels): | |
if channel == btn_title: | |
choice = idx | |
return choice | |
def set_chatbot(btn, ld): | |
choice = channel_num(btn) | |
res = [ | |
GradioAlpacaChatPPManager.from_json(json.dumps(ppm_str)) | |
for ppm_str in ld | |
] | |
empty = len(res[choice].pingpongs) == 0 | |
return ( | |
res[choice].build_uis(), | |
choice, | |
gr.update(visible=empty) | |
) | |
def set_example(btn): | |
return btn, gr.update(visible=False) | |
def set_popup_visibility(ld, example_block): | |
return example_block | |
with gr.Blocks(css=STYLE, elem_id='container-col') as demo: | |
idx = gr.State(0) | |
local_data = gr.JSON({},visible=False) | |
with gr.Row(): | |
with gr.Column(scale=1, min_width=180): | |
gr.Markdown("GradioChat", elem_id="left-top") | |
with gr.Column(elem_id="left-pane"): | |
with gr.Accordion("Histories", elem_id="chat-history-accordion"): | |
channel_btns.append(gr.Button(channels[0], elem_classes=["custom-btn-highlight"])) | |
for channel in channels[1:]: | |
channel_btns.append(gr.Button(channel, elem_classes=["custom-btn"])) | |
with gr.Column(scale=8, elem_id="right-pane"): | |
with gr.Column(elem_id="initial-popup", visible=False) as example_block: | |
with gr.Row(scale=1): | |
with gr.Column(elem_id="initial-popup-left-pane"): | |
gr.Markdown("GradioChat", elem_id="initial-popup-title") | |
gr.Markdown("Making the community's best AI chat models available to everyone.") | |
with gr.Column(elem_id="initial-popup-right-pane"): | |
gr.Markdown("Chat UI is now open sourced on Hugging Face Hub") | |
gr.Markdown("check out the [↗ repository](https://huggingface.co/spaces/chansung/test-multi-conv)") | |
with gr.Column(scale=1): | |
gr.Markdown("Examples") | |
with gr.Row() as text_block: | |
for example in examples: | |
ex_btns.append(gr.Button(example, elem_classes=["example-btn"])) | |
with gr.Column(elem_id="aux-btns-popup", visible=True): | |
with gr.Row(): | |
# stop = gr.Button("Stop", elem_classes=["aux-btn"]) | |
# regenerate = gr.Button("Regenerate", elem_classes=["aux-btn"]) | |
clean = gr.Button("Clean", elem_classes=["aux-btn"]) | |
chatbot = gr.Chatbot(elem_id='chatbot') | |
instruction_txtbox = gr.Textbox( | |
placeholder="Ask anything", label="", | |
elem_id="prompt-txt" | |
) | |
for btn in channel_btns: | |
btn.click( | |
set_chatbot, | |
[btn, local_data], | |
[chatbot, idx, example_block] | |
).then( | |
None, btn, None, | |
_js=update_left_btns_state | |
) | |
for btn in ex_btns: | |
btn.click( | |
set_example, | |
[btn], | |
[instruction_txtbox, example_block] | |
) | |
instruction_txtbox.submit( | |
lambda: gr.update(visible=False), | |
None, | |
example_block | |
).then( | |
add_pingpong, | |
[idx, local_data, instruction_txtbox], | |
[instruction_txtbox, chatbot, local_data] | |
).then( | |
None, local_data, None, | |
_js="(v)=>{ setStorage('local_data',v) }" | |
) | |
clean.click( | |
reset_chat, | |
[idx, local_data], | |
[instruction_txtbox, chatbot, local_data, example_block] | |
).then( | |
None, local_data, None, | |
_js="(v)=>{ setStorage('local_data',v) }" | |
) | |
demo.load( | |
None, | |
inputs=None, | |
outputs=[chatbot, local_data], | |
_js=get_local_storage, | |
) | |
demo.launch() |