chatglm3-6b初始的demo网页回车键换行,shift/ctrl + 回车键没有作用,想要提交只能手动点击“submit”按钮。
个人觉得这样不方便,应该增加一个像通常的通讯软件可以用 shift+enter 实现提交功能。最好还能增加交换这两种按键的行为。
思路是用js实现按键监听,但是js是在gradio框架中添加的。这里有参考:
【Gradio】Building With Blocks 自定义您的演示与 CSS 和 JavaScript-CSDN博客 https://blog.csdn.net/cxyhjl/article/details/139729514
下面是实现的代码:
...
js = """
function keybinding() {
if (typeof window.enterToSubmit === 'undefined') {
window.enterToSubmit = true; // Initialize the global state
}
function handleKeydown(event) {
if (window.enterToSubmit) {
if (event.key === 'Enter') {
if (event.shiftKey) {
event.preventDefault();
const textarea = event.target;
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start) + '\\n' + textarea.value.substring(end);
textarea.selectionStart = textarea.selectionEnd = start + 1;
} else {
event.preventDefault();
document.getElementById('submit-button').click();
}
}
} else {
if (event.shiftKey && event.key === 'Enter') {
event.preventDefault();
document.getElementById('submit-button').click();
}
}
}
document.addEventListener('keydown', handleKeydown);
// Toggle the enterToSubmit state when the toggle button is clicked
document.getElementById('toggle-button').addEventListener('click', function() {
window.enterToSubmit = !window.enterToSubmit;
var toggleLabel = document.getElementById('toggle-label');
toggleLabel.innerHTML = window.enterToSubmit
? ' '.repeat(11)+'enter : submit<br>shift+enter : newline'
: ' '.repeat(11)+'enter : newline<br>shift+enter : submit';
const inputBox = document.querySelector('textarea');
inputBox.placeholder = "Input...\\n"+(window.enterToSubmit
? ' '.repeat(11)+'enter : submit\\nshift+enter : newline'
: ' '.repeat(11)+'enter : newline\\nshift+enter : submit')
+'\\nyou can toggle by clicking the "toggle enter" button in the bottom right corner';
});
}
"""
with gr.Blocks(js=js) as demo:
gr.HTML("""<h1 align="center">ChatGLM3-6B Gradio Simple Demo</h1>""")
chatbot = gr.Chatbot()
with gr.Row():
with gr.Column(scale=4):
with gr.Column(scale=12):
placeholder_text="Input...\n"
placeholder_text+=' '*11+'enter : newline\nshift+enter : submit\n'
placeholder_text+='you can toggle by clicking the "toggle enter" button in the bottom right corner'
user_input = gr.Textbox(show_label=False, placeholder=placeholder_text, lines=10, container=False)
with gr.Column(min_width=32, scale=1):
submitBtn = gr.Button("Submit",elem_id="submit-button")
with gr.Column(scale=1):
emptyBtn = gr.Button("Clear History")
max_length = gr.Slider(0, 32768, value=8192, step=1.0, label="Maximum length", interactive=True)
top_p = gr.Slider(0, 1, value=0.8, step=0.01, label="Top P", interactive=True)
temperature = gr.Slider(0.01, 1, value=0.6, step=0.01, label="Temperature", interactive=True)
with gr.Row():
toggleBtn = gr.Button("toggle enter", elem_id="toggle-button")
toggleLabel = gr.HTML("<div id='toggle-label'>"+' '*11+"enter : submit<br>shift+enter : newline</div>")
def user(query, history):
return "", history + [[parse_text(query), ""]]
submitBtn.click(user, [user_input, chatbot], [user_input, chatbot], queue=False).then(
predict, [chatbot, max_length, top_p, temperature], chatbot
)
emptyBtn.click(lambda: None, None, chatbot, queue=False)
demo.queue()
demo.launch(server_name="127.0.0.1", server_port=7870, root_path='/chatglm', inbrowser=True, share=True, show_error=True)
网页效果:
点击“toggle enter”按钮会切换按键行为,并且具体情况会显示在旁边的文本中,也显示在输入框空白时的placeholder文本中。
写代码过程中的几个小坑:
-
将with gr.Blocks() as demo改为with gr.Blocks(js=js) as demo来运行js字符串中的函数。js字符串中只有一个函数定义,且并不实际调用,是可行的。其他的一些情形试了不行。
-
按下shift+enter的默认行为不换行(gpt认为会换行,可能与设备有关),在event.shiftKey用了一些较为复杂的textarea.selectionStart之类代码。
-
toggleLabel.innerHTML 的赋值中<br>不能用’\n’,会无效。
-
inputBox.placeholder 的赋值中,空格不能用
,就用空格字符本身,回车不能用\n
或<br>
,要用\\n
。这里太奇怪了,与上面不一致,改了好久…
为了方面调试,写了一个对多行字符串每一行问候的简单脚本,附在这里:
import gradio as gr
def greet(names_str):
names = names_str.split('\n')
responses = [f'Hello {name}!' for name in names]
return '\n'.join(responses)
def user(query, history):
response = greet(query)
return "", history + [[query, response]]
js = """
function keybinding() {
if (typeof window.enterToSubmit === 'undefined') {
window.enterToSubmit = false; // Initialize the global state
}
function handleKeydown(event) {
if (window.enterToSubmit) {
if (event.key === 'Enter') {
if (event.shiftKey) {
event.preventDefault();
const textarea = event.target;
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start) + '\\n' + textarea.value.substring(end);
textarea.selectionStart = textarea.selectionEnd = start + 1;
} else {
event.preventDefault();
document.getElementById('submit-button').click();
}
}
} else {
if (event.shiftKey && event.key === 'Enter') {
event.preventDefault();
document.getElementById('submit-button').click();
}
}
}
document.addEventListener('keydown', handleKeydown);
// Toggle the enterToSubmit state when the toggle button is clicked
document.getElementById('toggle-button').addEventListener('click', function() {
window.enterToSubmit = !window.enterToSubmit;
var toggleLabel = document.getElementById('toggle-label');
toggleLabel.innerHTML = window.enterToSubmit
? ' '.repeat(11)+'enter : submit<br>shift+enter : newline'
: ' '.repeat(11)+'enter : newline<br>shift+enter : submit';
const inputBox = document.querySelector('textarea');
inputBox.placeholder = "Input...\\n"+(window.enterToSubmit
? ' '.repeat(11)+'enter : submit\\nshift+enter : newline'
: ' '.repeat(11)+'enter : newline\\nshift+enter : submit')
+'\\nyou can toggle by clicking the "toggle enter" button in the bottom right corner';
});
}
"""
with gr.Blocks(js=js) as demo:
gr.HTML("<h1 align='center'>Gradio Simple Greet</h1>")
chatbot = gr.Chatbot()
with gr.Row():
with gr.Column(scale=4):
with gr.Column(scale=12):
placeholder_text="Input...\n"
placeholder_text+=' '*11+'enter : newline\nshift+enter : submit\n'
placeholder_text+='you can toggle by clicking the "toggle enter" button in the bottom right corner'
user_input = gr.Textbox(show_label=False, placeholder=placeholder_text, lines=10, container=False)
with gr.Column(min_width=32, scale=1):
submitBtn = gr.Button("Submit",elem_id="submit-button")
with gr.Column(scale=1):
emptyBtn = gr.Button("Clear History")
max_length = gr.Slider(0, 32768, value=8192, step=1.0, label="Maximum length", interactive=True)
top_p = gr.Slider(0, 1, value=0.8, step=0.01, label="Top P", interactive=True)
temperature = gr.Slider(0.01, 1, value=0.6, step=0.01, label="Temperature", interactive=True)
with gr.Row():
toggleBtn = gr.Button("toggle enter", elem_id="toggle-button") #behavior
toggleLabel = gr.HTML("<div id='toggle-label'>"+' '*11+"enter : submit<br>shift+enter : newline</div>")
submitBtn.click(user, [user_input, chatbot], [user_input, chatbot], queue=False)
emptyBtn.click(lambda: None, None, chatbot, queue=False)
app, local_url, share_url = demo.launch()
__import__('webbrowser').open(local_url)