Skip to content

Commit 7cf1402

Browse files
authored
Merge pull request oobabooga#5716 from oobabooga/dev
Merge dev branch
2 parents 1934cb6 + 49b111e commit 7cf1402

File tree

9 files changed

+91
-57
lines changed

9 files changed

+91
-57
lines changed

extensions/openai/typing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@ class ChatCompletionRequestParams(BaseModel):
103103
instruction_template_str: str | None = Field(default=None, description="A Jinja2 instruction template. If set, will take precedence over everything else.")
104104

105105
character: str | None = Field(default=None, description="A character defined under text-generation-webui/characters. If not set, the default \"Assistant\" character will be used.")
106-
user_name: str | None = Field(default=None, description="Your name (the user). By default, it's \"You\".", alias="name1")
107106
bot_name: str | None = Field(default=None, description="Overwrites the value set by character field.", alias="name2")
108107
context: str | None = Field(default=None, description="Overwrites the value set by character field.")
109108
greeting: str | None = Field(default=None, description="Overwrites the value set by character field.")
109+
user_name: str | None = Field(default=None, description="Your name (the user). By default, it's \"You\".", alias="name1")
110+
user_bio: str | None = Field(default=None, description="The user description/personality.")
110111
chat_template_str: str | None = Field(default=None, description="Jinja2 template for chat.")
111112

112113
chat_instruct_command: str | None = None

modules/cache_utils.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,29 @@ def process_llamacpp_cache(model, new_sequence, past_sequence):
1919
past_sequence = torch.tensor(past_sequence)
2020

2121
prefix_length = find_prefix_length(past_sequence[:i1], new_sequence[:j1])
22-
sink_length = prefix_length
23-
if sink_length < shared.args.attention_sink_size:
24-
sink_length = shared.args.attention_sink_size
25-
22+
sink_length = max(prefix_length, shared.args.attention_sink_size)
2623
removed_length = i1 - sink_length
2724

25+
if removed_length <= 0:
26+
return past_sequence.tolist()
27+
2828
matching_prefix = past_sequence[:prefix_length]
2929
removed_chunk = past_sequence[sink_length:i1]
3030
overlapping_sequence = new_sequence[j1:j2 + 1]
3131
added_chunk = new_sequence[j2 + 1:]
3232

33-
# print(past_sequence)
34-
# print(new_sequence)
33+
# print(past_sequence.tolist())
34+
# print(new_sequence.tolist())
3535

3636
print()
3737
print('MATCHING PREFIX=', repr(shared.tokenizer.decode(matching_prefix)))
3838
print('ADDED CHUNK=', repr(shared.tokenizer.decode(added_chunk)))
3939
print('REMOVED CHUNK=', repr(shared.tokenizer.decode(removed_chunk)))
40+
print('REMOVED LENGTH=', removed_length)
4041
print()
4142

4243
# Remove interval [sink_length, sink_length + removed_length) from the context
43-
# Subtract removed_length from model.n_tokens
44+
# Update model.n_tokens
4445
model._ctx.kv_cache_seq_rm(0, sink_length, sink_length + removed_length)
4546
model._ctx.kv_cache_seq_shift(0, sink_length + removed_length, -1, -removed_length)
4647

modules/chat.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,16 @@ def generate_chat_prompt(user_input, state, **kwargs):
8686
if state['mode'] != 'instruct':
8787
chat_template_str = replace_character_names(chat_template_str, state['name1'], state['name2'])
8888

89-
chat_template = jinja_env.from_string(chat_template_str)
9089
instruction_template = jinja_env.from_string(state['instruction_template_str'])
91-
chat_renderer = partial(chat_template.render, add_generation_prompt=False, name1=state['name1'], name2=state['name2'])
9290
instruct_renderer = partial(instruction_template.render, add_generation_prompt=False)
91+
chat_template = jinja_env.from_string(chat_template_str)
92+
chat_renderer = partial(
93+
chat_template.render,
94+
add_generation_prompt=False,
95+
name1=state['name1'],
96+
name2=state['name2'],
97+
user_bio=replace_character_names(state['user_bio'], state['name1'], state['name2']),
98+
)
9399

94100
messages = []
95101

@@ -99,7 +105,7 @@ def generate_chat_prompt(user_input, state, **kwargs):
99105
messages.append({"role": "system", "content": state['custom_system_message']})
100106
else:
101107
renderer = chat_renderer
102-
if state['context'].strip() != '':
108+
if state['context'].strip() != '' or state['user_bio'].strip() != '':
103109
context = replace_character_names(state['context'], state['name1'], state['name2'])
104110
messages.append({"role": "system", "content": context})
105111

@@ -140,6 +146,7 @@ def make_prompt(messages):
140146
command = state['chat-instruct_command']
141147
command = command.replace('<|character|>', state['name2'] if not impersonate else state['name1'])
142148
command = command.replace('<|prompt|>', prompt)
149+
command = replace_character_names(command, state['name1'], state['name2'])
143150

144151
if _continue:
145152
prefix = get_generation_prompt(renderer, impersonate=impersonate, strip_trailing_spaces=False)[0]

modules/html_generator.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import functools
12
import html
23
import os
34
import re
@@ -47,6 +48,7 @@ def replace_blockquote(m):
4748
return m.group().replace('\n', '\n> ').replace('\\begin{blockquote}', '').replace('\\end{blockquote}', '')
4849

4950

51+
@functools.lru_cache(maxsize=4096)
5052
def convert_to_markdown(string):
5153

5254
# Blockquote
@@ -99,6 +101,17 @@ def convert_to_markdown(string):
99101
return html_output
100102

101103

104+
def convert_to_markdown_wrapped(string, use_cache=True):
105+
'''
106+
Used to avoid caching convert_to_markdown calls during streaming.
107+
'''
108+
109+
if use_cache:
110+
return convert_to_markdown(string)
111+
112+
return convert_to_markdown.__wrapped__(string)
113+
114+
102115
def generate_basic_html(string):
103116
string = convert_to_markdown(string)
104117
string = f'<style>{readable_css}</style><div class="readable-container">{string}</div>'
@@ -194,7 +207,7 @@ def get_image_cache(path):
194207
def generate_instruct_html(history):
195208
output = f'<style>{instruct_css}</style><div class="chat" id="chat"><div class="messages">'
196209
for i, _row in enumerate(history):
197-
row = [convert_to_markdown(entry) for entry in _row]
210+
row = [convert_to_markdown_wrapped(entry, use_cache=i != len(history) - 1) for entry in _row]
198211

199212
if row[0]: # don't display empty user messages
200213
output += f"""
@@ -230,7 +243,7 @@ def generate_cai_chat_html(history, name1, name2, style, character, reset_cache=
230243
img_me = f'<img src="file/cache/pfp_me.png?{time.time() if reset_cache else ""}">' if Path("cache/pfp_me.png").exists() else ''
231244

232245
for i, _row in enumerate(history):
233-
row = [convert_to_markdown(entry) for entry in _row]
246+
row = [convert_to_markdown_wrapped(entry, use_cache=i != len(history) - 1) for entry in _row]
234247

235248
if row[0]: # don't display empty user messages
236249
output += f"""
@@ -273,7 +286,7 @@ def generate_chat_html(history, name1, name2, reset_cache=False):
273286
output = f'<style>{chat_styles["wpp"]}</style><div class="chat" id="chat"><div class="messages">'
274287

275288
for i, _row in enumerate(history):
276-
row = [convert_to_markdown(entry) for entry in _row]
289+
row = [convert_to_markdown_wrapped(entry, use_cache=i != len(history) - 1) for entry in _row]
277290

278291
if row[0]: # don't display empty user messages
279292
output += f"""

modules/shared.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@
5757
'stream': True,
5858
'character': 'Assistant',
5959
'name1': 'You',
60+
'user_bio': '',
6061
'custom_system_message': '',
6162
'instruction_template_str': "{%- set ns = namespace(found=false) -%}\n{%- for message in messages -%}\n {%- if message['role'] == 'system' -%}\n {%- set ns.found = true -%}\n {%- endif -%}\n{%- endfor -%}\n{%- if not ns.found -%}\n {{- '' + 'Below is an instruction that describes a task. Write a response that appropriately completes the request.' + '\\n\\n' -}}\n{%- endif %}\n{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {{- '' + message['content'] + '\\n\\n' -}}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{-'### Instruction:\\n' + message['content'] + '\\n\\n'-}}\n {%- else -%}\n {{-'### Response:\\n' + message['content'] + '\\n\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}\n{%- if add_generation_prompt -%}\n {{-'### Response:\\n'-}}\n{%- endif -%}",
62-
'chat_template_str': "{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {{- message['content'] + '\\n\\n' -}}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{- name1 + ': ' + message['content'] + '\\n'-}}\n {%- else -%}\n {{- name2 + ': ' + message['content'] + '\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}",
63+
'chat_template_str': "{%- for message in messages %}\n {%- if message['role'] == 'system' -%}\n {%- if message['content'] -%}\n {{- message['content'] + '\\n\\n' -}}\n {%- endif -%}\n {%- if user_bio -%}\n {{- user_bio + '\\n\\n' -}}\n {%- endif -%}\n {%- else -%}\n {%- if message['role'] == 'user' -%}\n {{- name1 + ': ' + message['content'] + '\\n'-}}\n {%- else -%}\n {{- name2 + ': ' + message['content'] + '\\n' -}}\n {%- endif -%}\n {%- endif -%}\n{%- endfor -%}",
6364
'chat-instruct_command': 'Continue the chat dialogue below. Write a single reply for the character "<|character|>".\n\n<|prompt|>',
6465
'autoload_model': False,
6566
'gallery-items_per_page': 50,

modules/ui.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
border_color_primary='#c5c5d2',
3636
button_large_padding='6px 12px',
3737
body_text_color_subdued='#484848',
38-
background_fill_secondary='#eaeaea'
38+
background_fill_secondary='#eaeaea',
39+
background_fill_primary='#fafafa',
3940
)
4041

4142
if Path("notification.mp3").exists():
@@ -170,6 +171,7 @@ def list_interface_input_elements():
170171
'character_menu',
171172
'history',
172173
'name1',
174+
'user_bio',
173175
'name2',
174176
'greeting',
175177
'context',
@@ -220,7 +222,7 @@ def apply_interface_values(state, use_persistent=False):
220222

221223
def save_settings(state, preset, extensions_list, show_controls, theme_state):
222224
output = copy.deepcopy(shared.settings)
223-
exclude = ['name2', 'greeting', 'context', 'turn_template']
225+
exclude = ['name2', 'greeting', 'context', 'turn_template', 'truncation_length']
224226
for k in state:
225227
if k in shared.settings and k not in exclude:
226228
output[k] = state[k]

modules/ui_chat.py

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,50 @@ def create_ui():
9494

9595
def create_chat_settings_ui():
9696
mu = shared.args.multi_user
97-
with gr.Tab('Character'):
97+
with gr.Tab('Chat'):
9898
with gr.Row():
9999
with gr.Column(scale=8):
100-
with gr.Row():
101-
shared.gradio['character_menu'] = gr.Dropdown(value=None, choices=utils.get_available_characters(), label='Character', elem_id='character-menu', info='Used in chat and chat-instruct modes.', elem_classes='slim-dropdown')
102-
ui.create_refresh_button(shared.gradio['character_menu'], lambda: None, lambda: {'choices': utils.get_available_characters()}, 'refresh-button', interactive=not mu)
103-
shared.gradio['save_character'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
104-
shared.gradio['delete_character'] = gr.Button('🗑️', elem_classes='refresh-button', interactive=not mu)
100+
with gr.Tab("Character"):
101+
with gr.Row():
102+
shared.gradio['character_menu'] = gr.Dropdown(value=None, choices=utils.get_available_characters(), label='Character', elem_id='character-menu', info='Used in chat and chat-instruct modes.', elem_classes='slim-dropdown')
103+
ui.create_refresh_button(shared.gradio['character_menu'], lambda: None, lambda: {'choices': utils.get_available_characters()}, 'refresh-button', interactive=not mu)
104+
shared.gradio['save_character'] = gr.Button('💾', elem_classes='refresh-button', interactive=not mu)
105+
shared.gradio['delete_character'] = gr.Button('🗑️', elem_classes='refresh-button', interactive=not mu)
106+
107+
shared.gradio['name2'] = gr.Textbox(value='', lines=1, label='Character\'s name')
108+
shared.gradio['context'] = gr.Textbox(value='', lines=10, label='Context', elem_classes=['add_scrollbar'])
109+
shared.gradio['greeting'] = gr.Textbox(value='', lines=5, label='Greeting', elem_classes=['add_scrollbar'])
110+
111+
with gr.Tab("User"):
112+
shared.gradio['name1'] = gr.Textbox(value=shared.settings['name1'], lines=1, label='Name')
113+
shared.gradio['user_bio'] = gr.Textbox(value=shared.settings['user_bio'], lines=10, label='Description', info='Here you can optionally write a description of yourself.', placeholder='{{user}}\'s personality: ...', elem_classes=['add_scrollbar'])
114+
115+
with gr.Tab('Chat history'):
116+
with gr.Row():
117+
with gr.Column():
118+
shared.gradio['save_chat_history'] = gr.Button(value='Save history')
119+
120+
with gr.Column():
121+
shared.gradio['load_chat_history'] = gr.File(type='binary', file_types=['.json', '.txt'], label='Upload History JSON')
122+
123+
with gr.Tab('Upload character'):
124+
with gr.Tab('YAML or JSON'):
125+
with gr.Row():
126+
shared.gradio['upload_json'] = gr.File(type='binary', file_types=['.json', '.yaml'], label='JSON or YAML File', interactive=not mu)
127+
shared.gradio['upload_img_bot'] = gr.Image(type='pil', label='Profile Picture (optional)', interactive=not mu)
128+
129+
shared.gradio['Submit character'] = gr.Button(value='Submit', interactive=False)
130+
131+
with gr.Tab('TavernAI PNG'):
132+
with gr.Row():
133+
with gr.Column():
134+
shared.gradio['upload_img_tavern'] = gr.Image(type='pil', label='TavernAI PNG File', elem_id='upload_img_tavern', interactive=not mu)
135+
shared.gradio['tavern_json'] = gr.State()
136+
with gr.Column():
137+
shared.gradio['tavern_name'] = gr.Textbox(value='', lines=1, label='Name', interactive=False)
138+
shared.gradio['tavern_desc'] = gr.Textbox(value='', lines=4, max_lines=4, label='Description', interactive=False)
105139

106-
shared.gradio['name1'] = gr.Textbox(value=shared.settings['name1'], lines=1, label='Your name')
107-
shared.gradio['name2'] = gr.Textbox(value='', lines=1, label='Character\'s name')
108-
shared.gradio['context'] = gr.Textbox(value='', lines=10, label='Context', elem_classes=['add_scrollbar'])
109-
shared.gradio['greeting'] = gr.Textbox(value='', lines=5, label='Greeting', elem_classes=['add_scrollbar'])
140+
shared.gradio['Submit tavern character'] = gr.Button(value='Submit', interactive=False)
110141

111142
with gr.Column(scale=1):
112143
shared.gradio['character_picture'] = gr.Image(label='Character picture', type='pil', interactive=not mu)
@@ -137,33 +168,6 @@ def create_chat_settings_ui():
137168
with gr.Column():
138169
shared.gradio['chat_template_str'] = gr.Textbox(value=shared.settings['chat_template_str'], label='Chat template', lines=22, elem_classes=['add_scrollbar', 'monospace'])
139170

140-
with gr.Tab('Chat history'):
141-
with gr.Row():
142-
with gr.Column():
143-
shared.gradio['save_chat_history'] = gr.Button(value='Save history')
144-
145-
with gr.Column():
146-
shared.gradio['load_chat_history'] = gr.File(type='binary', file_types=['.json', '.txt'], label='Upload History JSON')
147-
148-
with gr.Tab('Upload character'):
149-
with gr.Tab('YAML or JSON'):
150-
with gr.Row():
151-
shared.gradio['upload_json'] = gr.File(type='binary', file_types=['.json', '.yaml'], label='JSON or YAML File', interactive=not mu)
152-
shared.gradio['upload_img_bot'] = gr.Image(type='pil', label='Profile Picture (optional)', interactive=not mu)
153-
154-
shared.gradio['Submit character'] = gr.Button(value='Submit', interactive=False)
155-
156-
with gr.Tab('TavernAI PNG'):
157-
with gr.Row():
158-
with gr.Column():
159-
shared.gradio['upload_img_tavern'] = gr.Image(type='pil', label='TavernAI PNG File', elem_id='upload_img_tavern', interactive=not mu)
160-
shared.gradio['tavern_json'] = gr.State()
161-
with gr.Column():
162-
shared.gradio['tavern_name'] = gr.Textbox(value='', lines=1, label='Name', interactive=False)
163-
shared.gradio['tavern_desc'] = gr.Textbox(value='', lines=4, max_lines=4, label='Description', interactive=False)
164-
165-
shared.gradio['Submit tavern character'] = gr.Button(value='Submit', interactive=False)
166-
167171

168172
def create_event_handlers():
169173

modules/ui_model_menu.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def create_ui():
9090
shared.gradio['quant_type'] = gr.Dropdown(label="quant_type", choices=["nf4", "fp4"], value=shared.args.quant_type)
9191

9292
shared.gradio['hqq_backend'] = gr.Dropdown(label="hqq_backend", choices=["PYTORCH", "PYTORCH_COMPILE", "ATEN"], value=shared.args.hqq_backend)
93-
shared.gradio['n_gpu_layers'] = gr.Slider(label="n-gpu-layers", minimum=0, maximum=256, value=shared.args.n_gpu_layers)
93+
shared.gradio['n_gpu_layers'] = gr.Slider(label="n-gpu-layers", minimum=0, maximum=256, value=shared.args.n_gpu_layers, info='Must be set to more than 0 for your GPU to be used.')
9494
shared.gradio['n_ctx'] = gr.Slider(minimum=0, maximum=shared.settings['truncation_length_max'], step=256, label="n_ctx", value=shared.args.n_ctx, info='Context length. Try lowering this if you run out of memory while loading the model.')
9595
shared.gradio['tensor_split'] = gr.Textbox(label='tensor_split', info='List of proportions to split the model across multiple GPUs. Example: 18,17')
9696
shared.gradio['n_batch'] = gr.Slider(label="n_batch", minimum=1, maximum=2048, step=1, value=shared.args.n_batch)
@@ -118,7 +118,7 @@ def create_ui():
118118
shared.gradio['auto_devices'] = gr.Checkbox(label="auto-devices", value=shared.args.auto_devices)
119119
shared.gradio['tensorcores'] = gr.Checkbox(label="tensorcores", value=shared.args.tensorcores, info='NVIDIA only: use llama-cpp-python compiled with tensor cores support. This increases performance on RTX cards.')
120120
shared.gradio['streaming_llm'] = gr.Checkbox(label="streaming_llm", value=shared.args.streaming_llm, info='(experimental) Activate StreamingLLM to avoid re-evaluating the entire prompt when old messages are removed.')
121-
shared.gradio['attention_sink_size'] = gr.Number(label="attention_sink_size", value=shared.args.attention_sink_size, info='StreamingLLM: number of sink tokens. Only used if the trimmed prompt doesn\'t share a prefix with the old prompt.')
121+
shared.gradio['attention_sink_size'] = gr.Number(label="attention_sink_size", value=shared.args.attention_sink_size, precision=0, info='StreamingLLM: number of sink tokens. Only used if the trimmed prompt doesn\'t share a prefix with the old prompt.')
122122
shared.gradio['cpu'] = gr.Checkbox(label="cpu", value=shared.args.cpu, info='llama.cpp: Use llama-cpp-python compiled without GPU acceleration. Transformers: use PyTorch in CPU mode.')
123123
shared.gradio['row_split'] = gr.Checkbox(label="row_split", value=shared.args.row_split, info='Split the model by rows across GPUs. This may improve multi-gpu performance.')
124124
shared.gradio['no_offload_kqv'] = gr.Checkbox(label="no_offload_kqv", value=shared.args.no_offload_kqv, info='Do not offload the K, Q, V to the GPU. This saves VRAM but reduces the performance.')

0 commit comments

Comments
 (0)