alexkueck commited on
Commit
bbb647c
·
1 Parent(s): 2230f76

Update utils.py

Browse files
Files changed (1) hide show
  1. utils.py +345 -0
utils.py CHANGED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from app_modules.presets import *
2
+
3
+ logging.basicConfig(
4
+ level=logging.INFO,
5
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
6
+ )
7
+
8
+
9
+ def markdown_to_html_with_syntax_highlight(md_str):
10
+ def replacer(match):
11
+ lang = match.group(1) or "text"
12
+ code = match.group(2)
13
+ lang = lang.strip()
14
+ #print(1,lang)
15
+ if lang=="text":
16
+ lexer = guess_lexer(code)
17
+ lang = lexer.name
18
+ #print(2,lang)
19
+ try:
20
+ lexer = get_lexer_by_name(lang, stripall=True)
21
+ except ValueError:
22
+ lexer = get_lexer_by_name("python", stripall=True)
23
+ formatter = HtmlFormatter()
24
+ #print(3,lexer.name)
25
+ highlighted_code = highlight(code, lexer, formatter)
26
+
27
+ return f'<pre><code class="{lang}">{highlighted_code}</code></pre>'
28
+
29
+ code_block_pattern = r"```(\w+)?\n([\s\S]+?)\n```"
30
+ md_str = re.sub(code_block_pattern, replacer, md_str, flags=re.MULTILINE)
31
+
32
+ html_str = markdown(md_str)
33
+ return html_str
34
+
35
+
36
+ def normalize_markdown(md_text: str) -> str:
37
+ lines = md_text.split("\n")
38
+ normalized_lines = []
39
+ inside_list = False
40
+
41
+ for i, line in enumerate(lines):
42
+ if re.match(r"^(\d+\.|-|\*|\+)\s", line.strip()):
43
+ if not inside_list and i > 0 and lines[i - 1].strip() != "":
44
+ normalized_lines.append("")
45
+ inside_list = True
46
+ normalized_lines.append(line)
47
+ elif inside_list and line.strip() == "":
48
+ if i < len(lines) - 1 and not re.match(
49
+ r"^(\d+\.|-|\*|\+)\s", lines[i + 1].strip()
50
+ ):
51
+ normalized_lines.append(line)
52
+ continue
53
+ else:
54
+ inside_list = False
55
+ normalized_lines.append(line)
56
+
57
+ return "\n".join(normalized_lines)
58
+
59
+
60
+ def convert_mdtext(md_text):
61
+ code_block_pattern = re.compile(r"```(.*?)(?:```|$)", re.DOTALL)
62
+ inline_code_pattern = re.compile(r"`(.*?)`", re.DOTALL)
63
+ code_blocks = code_block_pattern.findall(md_text)
64
+ non_code_parts = code_block_pattern.split(md_text)[::2]
65
+
66
+ result = []
67
+ for non_code, code in zip(non_code_parts, code_blocks + [""]):
68
+ if non_code.strip():
69
+ non_code = normalize_markdown(non_code)
70
+ if inline_code_pattern.search(non_code):
71
+ result.append(markdown(non_code, extensions=["tables"]))
72
+ else:
73
+ result.append(mdtex2html.convert(non_code, extensions=["tables"]))
74
+ if code.strip():
75
+ code = f"\n```{code}\n\n```"
76
+ code = markdown_to_html_with_syntax_highlight(code)
77
+ result.append(code)
78
+ result = "".join(result)
79
+ result += ALREADY_CONVERTED_MARK
80
+ return result
81
+
82
+ def convert_asis(userinput):
83
+ return f"<p style=\"white-space:pre-wrap;\">{html.escape(userinput)}</p>"+ALREADY_CONVERTED_MARK
84
+
85
+ def detect_converted_mark(userinput):
86
+ if userinput.endswith(ALREADY_CONVERTED_MARK):
87
+ return True
88
+ else:
89
+ return False
90
+
91
+
92
+
93
+ def detect_language(code):
94
+ if code.startswith("\n"):
95
+ first_line = ""
96
+ else:
97
+ first_line = code.strip().split("\n", 1)[0]
98
+ language = first_line.lower() if first_line else ""
99
+ code_without_language = code[len(first_line) :].lstrip() if first_line else code
100
+ return language, code_without_language
101
+
102
+ def convert_to_markdown(text):
103
+ text = text.replace("$","&#36;")
104
+ def replace_leading_tabs_and_spaces(line):
105
+ new_line = []
106
+
107
+ for char in line:
108
+ if char == "\t":
109
+ new_line.append("&#9;")
110
+ elif char == " ":
111
+ new_line.append("&nbsp;")
112
+ else:
113
+ break
114
+ return "".join(new_line) + line[len(new_line):]
115
+
116
+ markdown_text = ""
117
+ lines = text.split("\n")
118
+ in_code_block = False
119
+
120
+ for line in lines:
121
+ if in_code_block is False and line.startswith("```"):
122
+ in_code_block = True
123
+ markdown_text += f"{line}\n"
124
+ elif in_code_block is True and line.startswith("```"):
125
+ in_code_block = False
126
+ markdown_text += f"{line}\n"
127
+ elif in_code_block:
128
+ markdown_text += f"{line}\n"
129
+ else:
130
+ line = replace_leading_tabs_and_spaces(line)
131
+ line = re.sub(r"^(#)", r"\\\1", line)
132
+ markdown_text += f"{line} \n"
133
+
134
+ return markdown_text
135
+
136
+ def add_language_tag(text):
137
+ def detect_language(code_block):
138
+ try:
139
+ lexer = guess_lexer(code_block)
140
+ return lexer.name.lower()
141
+ except ClassNotFound:
142
+ return ""
143
+
144
+ code_block_pattern = re.compile(r"(```)(\w*\n[^`]+```)", re.MULTILINE)
145
+
146
+ def replacement(match):
147
+ code_block = match.group(2)
148
+ if match.group(2).startswith("\n"):
149
+ language = detect_language(code_block)
150
+ if language:
151
+ return f"```{language}{code_block}```"
152
+ else:
153
+ return f"```\n{code_block}```"
154
+ else:
155
+ return match.group(1) + code_block + "```"
156
+
157
+ text2 = code_block_pattern.sub(replacement, text)
158
+ return text2
159
+
160
+ def delete_last_conversation(chatbot, history):
161
+ if len(chatbot) > 0:
162
+ chatbot.pop()
163
+
164
+ if len(history) > 0:
165
+ history.pop()
166
+
167
+ return (
168
+ chatbot,
169
+ history,
170
+ "Delete Done",
171
+ )
172
+
173
+ def reset_state():
174
+ return [], [], "Reset Done"
175
+
176
+ def reset_textbox():
177
+ return gr.update(value=""),""
178
+
179
+ def cancel_outputing():
180
+ return "Stop Done"
181
+
182
+ def transfer_input(inputs):
183
+ # 一次性返回,降低延迟
184
+ textbox = reset_textbox()
185
+ return (
186
+ inputs,
187
+ gr.update(value=""),
188
+ gr.Button.update(visible=True),
189
+ )
190
+
191
+
192
+ class State:
193
+ interrupted = False
194
+
195
+ def interrupt(self):
196
+ self.interrupted = True
197
+
198
+ def recover(self):
199
+ self.interrupted = False
200
+ shared_state = State()
201
+
202
+
203
+
204
+
205
+
206
+ # Greedy Search
207
+ def greedy_search(input_ids: torch.Tensor,
208
+ model: torch.nn.Module,
209
+ tokenizer: transformers.PreTrainedTokenizer,
210
+ stop_words: list,
211
+ max_length: int,
212
+ temperature: float = 1.0,
213
+ top_p: float = 1.0,
214
+ top_k: int = 25) -> Iterator[str]:
215
+ generated_tokens = []
216
+ past_key_values = None
217
+ current_length = 1
218
+ for i in range(max_length):
219
+ with torch.no_grad():
220
+ if past_key_values is None:
221
+ outputs = model(input_ids)
222
+ else:
223
+ outputs = model(input_ids[:, -1:], past_key_values=past_key_values)
224
+ logits = outputs.logits[:, -1, :]
225
+ past_key_values = outputs.past_key_values
226
+
227
+ # apply temperature
228
+ logits /= temperature
229
+
230
+ probs = torch.softmax(logits, dim=-1)
231
+ # apply top_p
232
+ probs_sort, probs_idx = torch.sort(probs, dim=-1, descending=True)
233
+ probs_sum = torch.cumsum(probs_sort, dim=-1)
234
+ mask = probs_sum - probs_sort > top_p
235
+ probs_sort[mask] = 0.0
236
+
237
+ # apply top_k
238
+ #if top_k is not None:
239
+ # probs_sort1, _ = torch.topk(probs_sort, top_k)
240
+ # min_top_probs_sort = torch.min(probs_sort1, dim=-1, keepdim=True).values
241
+ # probs_sort = torch.where(probs_sort < min_top_probs_sort, torch.full_like(probs_sort, float(0.0)), probs_sort)
242
+
243
+ probs_sort.div_(probs_sort.sum(dim=-1, keepdim=True))
244
+ next_token = torch.multinomial(probs_sort, num_samples=1)
245
+ next_token = torch.gather(probs_idx, -1, next_token)
246
+
247
+ input_ids = torch.cat((input_ids, next_token), dim=-1)
248
+
249
+ generated_tokens.append(next_token[0].item())
250
+ text = tokenizer.decode(generated_tokens)
251
+
252
+ yield text
253
+ if any([x in text for x in stop_words]):
254
+ del past_key_values
255
+ del logits
256
+ del probs
257
+ del probs_sort
258
+ del probs_idx
259
+ del probs_sum
260
+ gc.collect()
261
+ return
262
+
263
+ def generate_prompt_with_history(text,history,tokenizer,max_length=2048):
264
+ prompt = "The following is a conversation between a human and an AI assistant named Baize (named after a mythical creature in Chinese folklore). Baize is an open-source AI assistant developed by UCSD and Sun Yat-Sen University. The human and the AI assistant take turns chatting. Human statements start with [|Human|] and AI assistant statements start with [|AI|]. The AI assistant always provides responses in as much detail as possible, and in Markdown format. The AI assistant always declines to engage with topics, questions and instructions related to unethical, controversial, or sensitive issues. Complete the transcript in exactly that format.\n[|Human|]Hello!\n[|AI|]Hi!"
265
+ history = ["\n[|Human|]{}\n[|AI|]{}".format(x[0],x[1]) for x in history]
266
+ history.append("\n[|Human|]{}\n[|AI|]".format(text))
267
+ history_text = ""
268
+ flag = False
269
+ for x in history[::-1]:
270
+ if tokenizer(prompt+history_text+x, return_tensors="pt")['input_ids'].size(-1) <= max_length:
271
+ history_text = x + history_text
272
+ flag = True
273
+ else:
274
+ break
275
+ if flag:
276
+ return prompt+history_text,tokenizer(prompt+history_text, return_tensors="pt")
277
+ else:
278
+ return None
279
+
280
+
281
+ def is_stop_word_or_prefix(s: str, stop_words: list) -> bool:
282
+ for stop_word in stop_words:
283
+ if s.endswith(stop_word):
284
+ return True
285
+ for i in range(1, len(stop_word)):
286
+ if s.endswith(stop_word[:i]):
287
+ return True
288
+ return False
289
+
290
+
291
+
292
+ def load_tokenizer_and_model(base_model,adapter_model=None,load_8bit=False):
293
+ if torch.cuda.is_available():
294
+ device = "cuda"
295
+ else:
296
+ device = "cpu"
297
+
298
+ try:
299
+ if torch.backends.mps.is_available():
300
+ device = "mps"
301
+ except: # noqa: E722
302
+ pass
303
+ tokenizer = LlamaTokenizer.from_pretrained(base_model)
304
+ if device == "cuda":
305
+ model = LlamaForCausalLM.from_pretrained(
306
+ base_model,
307
+ load_in_8bit=load_8bit,
308
+ torch_dtype=torch.float16,
309
+ device_map="auto",
310
+ )
311
+ if adapter_model is not None:
312
+ model = PeftModel.from_pretrained(
313
+ model,
314
+ adapter_model,
315
+ torch_dtype=torch.float16,
316
+ )
317
+ elif device == "mps":
318
+ model = LlamaForCausalLM.from_pretrained(
319
+ base_model,
320
+ device_map={"": device},
321
+ torch_dtype=torch.float16,
322
+ )
323
+ if adapter_model is not None:
324
+ model = PeftModel.from_pretrained(
325
+ model,
326
+ adapter_model,
327
+ device_map={"": device},
328
+ torch_dtype=torch.float16,
329
+ )
330
+ else:
331
+ model = LlamaForCausalLM.from_pretrained(
332
+ base_model, device_map={"": device}, low_cpu_mem_usage=True
333
+ )
334
+ if adapter_model is not None:
335
+ model = PeftModel.from_pretrained(
336
+ model,
337
+ adapter_model,
338
+ device_map={"": device},
339
+ )
340
+
341
+ if not load_8bit:
342
+ model.half() # seems to fix bugs for some users.
343
+
344
+ model.eval()
345
+ return tokenizer,model,device