mirror of
https://github.com/oobabooga/text-generation-webui.git
synced 2025-01-27 12:33:17 +01:00
Add a "copy" button below each message (#6654)
This commit is contained in:
parent
58342740a5
commit
a5d64b586d
@ -48,12 +48,14 @@
|
|||||||
.chat .user-message {
|
.chat .user-message {
|
||||||
background: #f4f4f4;
|
background: #f4f4f4;
|
||||||
padding: 1.5rem 1rem;
|
padding: 1.5rem 1rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat .assistant-message {
|
.chat .assistant-message {
|
||||||
padding: 1.5rem 1rem;
|
padding: 1.5rem 1rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
53
css/main.css
53
css/main.css
@ -1142,7 +1142,6 @@ div.svelte-362y77>*, div.svelte-362y77>.form>* {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dark svg {
|
.dark svg {
|
||||||
fill: white;
|
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1221,3 +1220,55 @@ div.svelte-362y77>*, div.svelte-362y77>.form>* {
|
|||||||
background: var(--light-theme-gray);
|
background: var(--light-theme-gray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------
|
||||||
|
Copy button for chat messages
|
||||||
|
---------------------------------------------- */
|
||||||
|
.message .text,
|
||||||
|
.message .text-you,
|
||||||
|
.message .text-bot,
|
||||||
|
.user-message .text,
|
||||||
|
.assistant-message .text {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message, .user-message, .assistant-message {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-button {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -23px;
|
||||||
|
left: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message:hover .copy-button,
|
||||||
|
.user-message:hover .copy-button,
|
||||||
|
.assistant-message:hover .copy-button {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-button svg {
|
||||||
|
stroke: rgb(156 163 175);
|
||||||
|
transition: stroke 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-button:hover svg {
|
||||||
|
stroke: rgb(107 114 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .copy-button svg {
|
||||||
|
stroke: rgb(156 163 175);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .copy-button:hover svg {
|
||||||
|
stroke: rgb(209 213 219);
|
||||||
|
}
|
||||||
|
@ -3,7 +3,7 @@ import io
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from modules import shared
|
from modules import shared, ui
|
||||||
from modules.logging_colors import logger
|
from modules.logging_colors import logger
|
||||||
|
|
||||||
original_open = open
|
original_open = open
|
||||||
@ -58,6 +58,7 @@ def my_open(*args, **kwargs):
|
|||||||
'\n <script src="file/js/morphdom/morphdom-umd.min.js"></script>'
|
'\n <script src="file/js/morphdom/morphdom-umd.min.js"></script>'
|
||||||
f'\n <link id="highlight-css" rel="stylesheet" href="file/css/highlightjs/{"github-dark" if shared.settings["dark_theme"] else "github"}.min.css">'
|
f'\n <link id="highlight-css" rel="stylesheet" href="file/css/highlightjs/{"github-dark" if shared.settings["dark_theme"] else "github"}.min.css">'
|
||||||
'\n <script>hljs.addPlugin(new CopyButtonPlugin());</script>'
|
'\n <script>hljs.addPlugin(new CopyButtonPlugin());</script>'
|
||||||
|
f'\n <script>{ui.global_scope_js}</script>'
|
||||||
'\n </head>'
|
'\n </head>'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -292,24 +292,34 @@ def get_image_cache(path):
|
|||||||
return image_cache[path][1]
|
return image_cache[path][1]
|
||||||
|
|
||||||
|
|
||||||
|
copy_svg = '''<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-copy"><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg>'''
|
||||||
|
copy_button = f'<button class="copy-button" onclick="copyToClipboard(this)">{copy_svg}</button>'
|
||||||
|
|
||||||
def generate_instruct_html(history):
|
def generate_instruct_html(history):
|
||||||
output = f'<style>{instruct_css}</style><div class="chat" id="chat"><div class="messages">'
|
output = f'<style>{instruct_css}</style><div class="chat" id="chat"><div class="messages">'
|
||||||
for i, _row in enumerate(history):
|
|
||||||
row = [convert_to_markdown_wrapped(entry, use_cache=i != len(history) - 1) for entry in _row]
|
|
||||||
|
|
||||||
if row[0]: # Don't display empty user messages
|
for i in range(len(history['visible'])):
|
||||||
|
row_visible = history['visible'][i]
|
||||||
|
row_internal = history['internal'][i]
|
||||||
|
converted_visible = [convert_to_markdown_wrapped(entry, use_cache=i != len(history['visible']) - 1) for entry in row_visible]
|
||||||
|
|
||||||
|
if converted_visible[0]: # Don't display empty user messages
|
||||||
output += (
|
output += (
|
||||||
f'<div class="user-message">'
|
f'<div class="user-message" '
|
||||||
|
f'data-raw="{html.escape(row_internal[0], quote=True)}">'
|
||||||
f'<div class="text">'
|
f'<div class="text">'
|
||||||
f'<div class="message-body">{row[0]}</div>'
|
f'<div class="message-body">{converted_visible[0]}</div>'
|
||||||
|
f'{copy_button}'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
)
|
)
|
||||||
|
|
||||||
output += (
|
output += (
|
||||||
f'<div class="assistant-message">'
|
f'<div class="assistant-message" '
|
||||||
|
f'data-raw="{html.escape(row_internal[1], quote=True)}">'
|
||||||
f'<div class="text">'
|
f'<div class="text">'
|
||||||
f'<div class="message-body">{row[1]}</div>'
|
f'<div class="message-body">{converted_visible[1]}</div>'
|
||||||
|
f'{copy_button}'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
)
|
)
|
||||||
@ -332,26 +342,32 @@ def generate_cai_chat_html(history, name1, name2, style, character, reset_cache=
|
|||||||
if Path("cache/pfp_me.png").exists() else ''
|
if Path("cache/pfp_me.png").exists() else ''
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, _row in enumerate(history):
|
for i in range(len(history['visible'])):
|
||||||
row = [convert_to_markdown_wrapped(entry, use_cache=i != len(history) - 1) for entry in _row]
|
row_visible = history['visible'][i]
|
||||||
|
row_internal = history['internal'][i]
|
||||||
|
converted_visible = [convert_to_markdown_wrapped(entry, use_cache=i != len(history['visible']) - 1) for entry in row_visible]
|
||||||
|
|
||||||
if row[0]: # Don't display empty user messages
|
if converted_visible[0]: # Don't display empty user messages
|
||||||
output += (
|
output += (
|
||||||
f'<div class="message">'
|
f'<div class="message" '
|
||||||
|
f'data-raw="{html.escape(row_internal[0], quote=True)}">'
|
||||||
f'<div class="circle-you">{img_me}</div>'
|
f'<div class="circle-you">{img_me}</div>'
|
||||||
f'<div class="text">'
|
f'<div class="text">'
|
||||||
f'<div class="username">{name1}</div>'
|
f'<div class="username">{name1}</div>'
|
||||||
f'<div class="message-body">{row[0]}</div>'
|
f'<div class="message-body">{converted_visible[0]}</div>'
|
||||||
|
f'{copy_button}'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
)
|
)
|
||||||
|
|
||||||
output += (
|
output += (
|
||||||
f'<div class="message">'
|
f'<div class="message" '
|
||||||
|
f'data-raw="{html.escape(row_internal[1], quote=True)}">'
|
||||||
f'<div class="circle-bot">{img_bot}</div>'
|
f'<div class="circle-bot">{img_bot}</div>'
|
||||||
f'<div class="text">'
|
f'<div class="text">'
|
||||||
f'<div class="username">{name2}</div>'
|
f'<div class="username">{name2}</div>'
|
||||||
f'<div class="message-body">{row[1]}</div>'
|
f'<div class="message-body">{converted_visible[1]}</div>'
|
||||||
|
f'{copy_button}'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
)
|
)
|
||||||
@ -363,22 +379,28 @@ def generate_cai_chat_html(history, name1, name2, style, character, reset_cache=
|
|||||||
def generate_chat_html(history, name1, name2, reset_cache=False):
|
def generate_chat_html(history, name1, name2, reset_cache=False):
|
||||||
output = f'<style>{chat_styles["wpp"]}</style><div class="chat" id="chat"><div class="messages">'
|
output = f'<style>{chat_styles["wpp"]}</style><div class="chat" id="chat"><div class="messages">'
|
||||||
|
|
||||||
for i, _row in enumerate(history):
|
for i in range(len(history['visible'])):
|
||||||
row = [convert_to_markdown_wrapped(entry, use_cache=i != len(history) - 1) for entry in _row]
|
row_visible = history['visible'][i]
|
||||||
|
row_internal = history['internal'][i]
|
||||||
|
converted_visible = [convert_to_markdown_wrapped(entry, use_cache=i != len(history['visible']) - 1) for entry in row_visible]
|
||||||
|
|
||||||
if row[0]: # Don't display empty user messages
|
if converted_visible[0]: # Don't display empty user messages
|
||||||
output += (
|
output += (
|
||||||
f'<div class="message">'
|
f'<div class="message" '
|
||||||
|
f'data-raw="{html.escape(row_internal[0], quote=True)}">'
|
||||||
f'<div class="text-you">'
|
f'<div class="text-you">'
|
||||||
f'<div class="message-body">{row[0]}</div>'
|
f'<div class="message-body">{converted_visible[0]}</div>'
|
||||||
|
f'{copy_button}'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
)
|
)
|
||||||
|
|
||||||
output += (
|
output += (
|
||||||
f'<div class="message">'
|
f'<div class="message" '
|
||||||
|
f'data-raw="{html.escape(row_internal[1], quote=True)}">'
|
||||||
f'<div class="text-bot">'
|
f'<div class="text-bot">'
|
||||||
f'<div class="message-body">{row[1]}</div>'
|
f'<div class="message-body">{converted_visible[1]}</div>'
|
||||||
|
f'{copy_button}'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
f'</div>'
|
f'</div>'
|
||||||
)
|
)
|
||||||
@ -389,8 +411,8 @@ def generate_chat_html(history, name1, name2, reset_cache=False):
|
|||||||
|
|
||||||
def chat_html_wrapper(history, name1, name2, mode, style, character, reset_cache=False):
|
def chat_html_wrapper(history, name1, name2, mode, style, character, reset_cache=False):
|
||||||
if mode == 'instruct':
|
if mode == 'instruct':
|
||||||
return generate_instruct_html(history['visible'])
|
return generate_instruct_html(history)
|
||||||
elif style == 'wpp':
|
elif style == 'wpp':
|
||||||
return generate_chat_html(history['visible'], name1, name2)
|
return generate_chat_html(history, name1, name2)
|
||||||
else:
|
else:
|
||||||
return generate_cai_chat_html(history['visible'], name1, name2, style, character, reset_cache)
|
return generate_cai_chat_html(history, name1, name2, style, character, reset_cache)
|
||||||
|
@ -19,6 +19,8 @@ with open(Path(__file__).resolve().parent / '../css/highlightjs/highlightjs-copy
|
|||||||
css += f.read()
|
css += f.read()
|
||||||
with open(Path(__file__).resolve().parent / '../js/main.js', 'r') as f:
|
with open(Path(__file__).resolve().parent / '../js/main.js', 'r') as f:
|
||||||
js = f.read()
|
js = f.read()
|
||||||
|
with open(Path(__file__).resolve().parent / '../js/global_scope_js.js', 'r') as f:
|
||||||
|
global_scope_js = f.read()
|
||||||
with open(Path(__file__).resolve().parent / '../js/save_files.js', 'r') as f:
|
with open(Path(__file__).resolve().parent / '../js/save_files.js', 'r') as f:
|
||||||
save_files_js = f.read()
|
save_files_js = f.read()
|
||||||
with open(Path(__file__).resolve().parent / '../js/switch_tabs.js', 'r') as f:
|
with open(Path(__file__).resolve().parent / '../js/switch_tabs.js', 'r') as f:
|
||||||
|
Loading…
Reference in New Issue
Block a user