quincyqiang commited on
Commit
1a4acb9
1 Parent(s): ca82b6e

update@css

Browse files
README.md CHANGED
@@ -47,3 +47,4 @@
47
  - webui参考:https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui
48
  - knowledge问答参考:https://github.com/imClumsyPanda/langchain-ChatGLM
49
  - LLM模型:https://github.com/THUDM/ChatGLM-6B
 
 
47
  - webui参考:https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui
48
  - knowledge问答参考:https://github.com/imClumsyPanda/langchain-ChatGLM
49
  - LLM模型:https://github.com/THUDM/ChatGLM-6B
50
+ - CSS:https://huggingface.co/spaces/JohnSmith9982/ChuanhuChatGPT
app_modules/overwrites.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ import logging
3
+
4
+ from llama_index import Prompt
5
+ from typing import List, Tuple
6
+ import mdtex2html
7
+
8
+ from app_modules.presets import *
9
+ from app_modules.utils import *
10
+
11
+ def compact_text_chunks(self, prompt: Prompt, text_chunks: List[str]) -> List[str]:
12
+ logging.debug("Compacting text chunks...🚀🚀🚀")
13
+ combined_str = [c.strip() for c in text_chunks if c.strip()]
14
+ combined_str = [f"[{index+1}] {c}" for index, c in enumerate(combined_str)]
15
+ combined_str = "\n\n".join(combined_str)
16
+ # resplit based on self.max_chunk_overlap
17
+ text_splitter = self.get_text_splitter_given_prompt(prompt, 1, padding=1)
18
+ return text_splitter.split_text(combined_str)
19
+
20
+
21
+ def postprocess(
22
+ self, y: List[Tuple[str | None, str | None]]
23
+ ) -> List[Tuple[str | None, str | None]]:
24
+ """
25
+ Parameters:
26
+ y: List of tuples representing the message and response pairs. Each message and response should be a string, which may be in Markdown format.
27
+ Returns:
28
+ List of tuples representing the message and response. Each message and response will be a string of HTML.
29
+ """
30
+ if y is None or y == []:
31
+ return []
32
+ temp = []
33
+ for x in y:
34
+ user, bot = x
35
+ if not detect_converted_mark(user):
36
+ user = convert_asis(user)
37
+ if not detect_converted_mark(bot):
38
+ bot = convert_mdtext(bot)
39
+ temp.append((user, bot))
40
+ return temp
41
+
42
+ with open("./assets/custom.js", "r", encoding="utf-8") as f, open("./assets/Kelpy-Codos.js", "r", encoding="utf-8") as f2:
43
+ customJS = f.read()
44
+ kelpyCodos = f2.read()
45
+
46
+ def reload_javascript():
47
+ print("Reloading javascript...")
48
+ js = f'<script>{customJS}</script><script>{kelpyCodos}</script>'
49
+ def template_response(*args, **kwargs):
50
+ res = GradioTemplateResponseOriginal(*args, **kwargs)
51
+ res.body = res.body.replace(b'</html>', f'{js}</html>'.encode("utf8"))
52
+ res.init_headers()
53
+ return res
54
+
55
+ gr.routes.templates.TemplateResponse = template_response
56
+
57
+ GradioTemplateResponseOriginal = gr.routes.templates.TemplateResponse
app_modules/presets.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+ import gradio as gr
3
+
4
+
5
+ title = """<h1 align="left" style="min-width:200px; margin-top:0;"> <img src="https://raw.githubusercontent.com/twitter/twemoji/master/assets/svg/1f432.svg" width="32px" style="display: inline"> Baize-7B </h1>"""
6
+ description_top = """\
7
+ <div align="left">
8
+ <p>
9
+ Disclaimer: The LLaMA model is a third-party version available on Hugging Face model hub. This demo should be used for research purposes only. Commercial use is strictly prohibited. The model output is not censored and the authors do not endorse the opinions in the generated content. Use at your own risk.
10
+ </p >
11
+ </div>
12
+ """
13
+ description = """\
14
+ <div align="center" style="margin:16px 0">
15
+ The demo is built on <a href="https://github.com/GaiZhenbiao/ChuanhuChatGPT">ChuanhuChatGPT</a>.
16
+ </div>
17
+ """
18
+ CONCURRENT_COUNT = 100
19
+
20
+
21
+ ALREADY_CONVERTED_MARK = "<!-- ALREADY CONVERTED BY PARSER. -->"
22
+
23
+ small_and_beautiful_theme = gr.themes.Soft(
24
+ primary_hue=gr.themes.Color(
25
+ c50="#02C160",
26
+ c100="rgba(2, 193, 96, 0.2)",
27
+ c200="#02C160",
28
+ c300="rgba(2, 193, 96, 0.32)",
29
+ c400="rgba(2, 193, 96, 0.32)",
30
+ c500="rgba(2, 193, 96, 1.0)",
31
+ c600="rgba(2, 193, 96, 1.0)",
32
+ c700="rgba(2, 193, 96, 0.32)",
33
+ c800="rgba(2, 193, 96, 0.32)",
34
+ c900="#02C160",
35
+ c950="#02C160",
36
+ ),
37
+ secondary_hue=gr.themes.Color(
38
+ c50="#576b95",
39
+ c100="#576b95",
40
+ c200="#576b95",
41
+ c300="#576b95",
42
+ c400="#576b95",
43
+ c500="#576b95",
44
+ c600="#576b95",
45
+ c700="#576b95",
46
+ c800="#576b95",
47
+ c900="#576b95",
48
+ c950="#576b95",
49
+ ),
50
+ neutral_hue=gr.themes.Color(
51
+ name="gray",
52
+ c50="#f9fafb",
53
+ c100="#f3f4f6",
54
+ c200="#e5e7eb",
55
+ c300="#d1d5db",
56
+ c400="#B2B2B2",
57
+ c500="#808080",
58
+ c600="#636363",
59
+ c700="#515151",
60
+ c800="#393939",
61
+ c900="#272727",
62
+ c950="#171717",
63
+ ),
64
+ radius_size=gr.themes.sizes.radius_sm,
65
+ ).set(
66
+ button_primary_background_fill="#06AE56",
67
+ button_primary_background_fill_dark="#06AE56",
68
+ button_primary_background_fill_hover="#07C863",
69
+ button_primary_border_color="#06AE56",
70
+ button_primary_border_color_dark="#06AE56",
71
+ button_primary_text_color="#FFFFFF",
72
+ button_primary_text_color_dark="#FFFFFF",
73
+ button_secondary_background_fill="#F2F2F2",
74
+ button_secondary_background_fill_dark="#2B2B2B",
75
+ button_secondary_text_color="#393939",
76
+ button_secondary_text_color_dark="#FFFFFF",
77
+ # background_fill_primary="#F7F7F7",
78
+ # background_fill_primary_dark="#1F1F1F",
79
+ block_title_text_color="*primary_500",
80
+ block_title_background_fill="*primary_100",
81
+ input_background_fill="#F6F6F6",
82
+ )
app_modules/utils.py ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding:utf-8 -*-
2
+ from __future__ import annotations
3
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple, Type
4
+ import logging
5
+ import json
6
+ import os
7
+ import datetime
8
+ import hashlib
9
+ import csv
10
+ import requests
11
+ import re
12
+ import html
13
+ import markdown2
14
+ import torch
15
+ import sys
16
+ import gc
17
+ from pygments.lexers import guess_lexer, ClassNotFound
18
+
19
+ import gradio as gr
20
+ from pypinyin import lazy_pinyin
21
+ import tiktoken
22
+ import mdtex2html
23
+ from markdown import markdown
24
+ from pygments import highlight
25
+ from pygments.lexers import guess_lexer, get_lexer_by_name
26
+ from pygments.formatters import HtmlFormatter
27
+ import transformers
28
+ from peft import PeftModel
29
+ from transformers import GenerationConfig, LlamaForCausalLM, LlamaTokenizer
30
+
31
+ from app_modules.presets import *
32
+
33
+ logging.basicConfig(
34
+ level=logging.INFO,
35
+ format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
36
+ )
37
+
38
+
39
+ def markdown_to_html_with_syntax_highlight(md_str):
40
+ def replacer(match):
41
+ lang = match.group(1) or "text"
42
+ code = match.group(2)
43
+ lang = lang.strip()
44
+ # print(1,lang)
45
+ if lang == "text":
46
+ lexer = guess_lexer(code)
47
+ lang = lexer.name
48
+ # print(2,lang)
49
+ try:
50
+ lexer = get_lexer_by_name(lang, stripall=True)
51
+ except ValueError:
52
+ lexer = get_lexer_by_name("python", stripall=True)
53
+ formatter = HtmlFormatter()
54
+ # print(3,lexer.name)
55
+ highlighted_code = highlight(code, lexer, formatter)
56
+
57
+ return f'<pre><code class="{lang}">{highlighted_code}</code></pre>'
58
+
59
+ code_block_pattern = r"```(\w+)?\n([\s\S]+?)\n```"
60
+ md_str = re.sub(code_block_pattern, replacer, md_str, flags=re.MULTILINE)
61
+
62
+ html_str = markdown(md_str)
63
+ return html_str
64
+
65
+
66
+ def normalize_markdown(md_text: str) -> str:
67
+ lines = md_text.split("\n")
68
+ normalized_lines = []
69
+ inside_list = False
70
+
71
+ for i, line in enumerate(lines):
72
+ if re.match(r"^(\d+\.|-|\*|\+)\s", line.strip()):
73
+ if not inside_list and i > 0 and lines[i - 1].strip() != "":
74
+ normalized_lines.append("")
75
+ inside_list = True
76
+ normalized_lines.append(line)
77
+ elif inside_list and line.strip() == "":
78
+ if i < len(lines) - 1 and not re.match(
79
+ r"^(\d+\.|-|\*|\+)\s", lines[i + 1].strip()
80
+ ):
81
+ normalized_lines.append(line)
82
+ continue
83
+ else:
84
+ inside_list = False
85
+ normalized_lines.append(line)
86
+
87
+ return "\n".join(normalized_lines)
88
+
89
+
90
+ def convert_mdtext(md_text):
91
+ code_block_pattern = re.compile(r"```(.*?)(?:```|$)", re.DOTALL)
92
+ inline_code_pattern = re.compile(r"`(.*?)`", re.DOTALL)
93
+ code_blocks = code_block_pattern.findall(md_text)
94
+ non_code_parts = code_block_pattern.split(md_text)[::2]
95
+
96
+ result = []
97
+ for non_code, code in zip(non_code_parts, code_blocks + [""]):
98
+ if non_code.strip():
99
+ non_code = normalize_markdown(non_code)
100
+ if inline_code_pattern.search(non_code):
101
+ result.append(markdown(non_code, extensions=["tables"]))
102
+ else:
103
+ result.append(mdtex2html.convert(non_code, extensions=["tables"]))
104
+ if code.strip():
105
+ # _, code = detect_language(code) # 暂时去除代码高亮功能,因为在大段代码的情况下会出现问题
106
+ # code = code.replace("\n\n", "\n") # 暂时去除代码中的空行,因为在大段代码的情况下会出现问题
107
+ code = f"\n```{code}\n\n```"
108
+ code = markdown_to_html_with_syntax_highlight(code)
109
+ result.append(code)
110
+ result = "".join(result)
111
+ result += ALREADY_CONVERTED_MARK
112
+ return result
113
+
114
+
115
+ def convert_asis(userinput):
116
+ return f"<p style=\"white-space:pre-wrap;\">{html.escape(userinput)}</p>" + ALREADY_CONVERTED_MARK
117
+
118
+
119
+ def detect_converted_mark(userinput):
120
+ if userinput.endswith(ALREADY_CONVERTED_MARK):
121
+ return True
122
+ else:
123
+ return False
124
+
125
+
126
+ def detect_language(code):
127
+ if code.startswith("\n"):
128
+ first_line = ""
129
+ else:
130
+ first_line = code.strip().split("\n", 1)[0]
131
+ language = first_line.lower() if first_line else ""
132
+ code_without_language = code[len(first_line):].lstrip() if first_line else code
133
+ return language, code_without_language
134
+
135
+
136
+ def convert_to_markdown(text):
137
+ text = text.replace("$", "&#36;")
138
+
139
+ def replace_leading_tabs_and_spaces(line):
140
+ new_line = []
141
+
142
+ for char in line:
143
+ if char == "\t":
144
+ new_line.append("&#9;")
145
+ elif char == " ":
146
+ new_line.append("&nbsp;")
147
+ else:
148
+ break
149
+ return "".join(new_line) + line[len(new_line):]
150
+
151
+ markdown_text = ""
152
+ lines = text.split("\n")
153
+ in_code_block = False
154
+
155
+ for line in lines:
156
+ if in_code_block is False and line.startswith("```"):
157
+ in_code_block = True
158
+ markdown_text += "```\n"
159
+ elif in_code_block is True and line.startswith("```"):
160
+ in_code_block = False
161
+ markdown_text += "```\n"
162
+ elif in_code_block:
163
+ markdown_text += f"{line}\n"
164
+ else:
165
+ line = replace_leading_tabs_and_spaces(line)
166
+ line = re.sub(r"^(#)", r"\\\1", line)
167
+ markdown_text += f"{line} \n"
168
+
169
+ return markdown_text
170
+
171
+
172
+ def add_language_tag(text):
173
+ def detect_language(code_block):
174
+ try:
175
+ lexer = guess_lexer(code_block)
176
+ return lexer.name.lower()
177
+ except ClassNotFound:
178
+ return ""
179
+
180
+ code_block_pattern = re.compile(r"(```)(\w*\n[^`]+```)", re.MULTILINE)
181
+
182
+ def replacement(match):
183
+ code_block = match.group(2)
184
+ if match.group(2).startswith("\n"):
185
+ language = detect_language(code_block)
186
+ if language:
187
+ return f"```{language}{code_block}```"
188
+ else:
189
+ return f"```\n{code_block}```"
190
+ else:
191
+ return match.group(1) + code_block + "```"
192
+
193
+ text2 = code_block_pattern.sub(replacement, text)
194
+ return text2
195
+
196
+
197
+ def delete_last_conversation(chatbot, history):
198
+ if len(chatbot) > 0:
199
+ chatbot.pop()
200
+
201
+ if len(history) > 0:
202
+ history.pop()
203
+
204
+ return (
205
+ chatbot,
206
+ history,
207
+ "Delete Done",
208
+ )
209
+
210
+
211
+ def reset_state():
212
+ return [], [], "Reset Done"
213
+
214
+
215
+ def reset_textbox():
216
+ return gr.update(value=""), ""
217
+
218
+
219
+ def cancel_outputing():
220
+ return "Stop Done"
221
+
222
+
223
+ def transfer_input(inputs):
224
+ # 一次性返回,降低延迟
225
+ textbox = reset_textbox()
226
+ return (
227
+ inputs,
228
+ gr.update(value=""),
229
+ gr.Button.update(visible=True),
230
+ )
231
+
232
+
233
+ class State:
234
+ interrupted = False
235
+
236
+ def interrupt(self):
237
+ self.interrupted = True
238
+
239
+ def recover(self):
240
+ self.interrupted = False
241
+
242
+
243
+ shared_state = State()
244
+
245
+
246
+ # Greedy Search
247
+ def greedy_search(input_ids: torch.Tensor,
248
+ model: torch.nn.Module,
249
+ tokenizer: transformers.PreTrainedTokenizer,
250
+ stop_words: list,
251
+ max_length: int,
252
+ temperature: float = 1.0,
253
+ top_p: float = 1.0,
254
+ top_k: int = 25) -> Iterator[str]:
255
+ generated_tokens = []
256
+ past_key_values = None
257
+ current_length = 1
258
+ for i in range(max_length):
259
+ with torch.no_grad():
260
+ if past_key_values is None:
261
+ outputs = model(input_ids)
262
+ else:
263
+ outputs = model(input_ids[:, -1:], past_key_values=past_key_values)
264
+ logits = outputs.logits[:, -1, :]
265
+ past_key_values = outputs.past_key_values
266
+
267
+ # apply temperature
268
+ logits /= temperature
269
+
270
+ probs = torch.softmax(logits, dim=-1)
271
+ # apply top_p
272
+ probs_sort, probs_idx = torch.sort(probs, dim=-1, descending=True)
273
+ probs_sum = torch.cumsum(probs_sort, dim=-1)
274
+ mask = probs_sum - probs_sort > top_p
275
+ probs_sort[mask] = 0.0
276
+
277
+ # apply top_k
278
+ # if top_k is not None:
279
+ # probs_sort1, _ = torch.topk(probs_sort, top_k)
280
+ # min_top_probs_sort = torch.min(probs_sort1, dim=-1, keepdim=True).values
281
+ # probs_sort = torch.where(probs_sort < min_top_probs_sort, torch.full_like(probs_sort, float(0.0)), probs_sort)
282
+
283
+ probs_sort.div_(probs_sort.sum(dim=-1, keepdim=True))
284
+ next_token = torch.multinomial(probs_sort, num_samples=1)
285
+ next_token = torch.gather(probs_idx, -1, next_token)
286
+
287
+ input_ids = torch.cat((input_ids, next_token), dim=-1)
288
+
289
+ generated_tokens.append(next_token[0].item())
290
+ text = tokenizer.decode(generated_tokens)
291
+
292
+ yield text
293
+ if any([x in text for x in stop_words]):
294
+ del past_key_values
295
+ del logits
296
+ del probs
297
+ del probs_sort
298
+ del probs_idx
299
+ del probs_sum
300
+ gc.collect()
301
+ return
302
+
303
+
304
+ def generate_prompt_with_history(text, history, tokenizer, max_length=2048):
305
+ 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!"
306
+ history = ["\n[|Human|]{}\n[|AI|]{}".format(x[0], x[1]) for x in history]
307
+ history.append("\n[|Human|]{}\n[|AI|]".format(text))
308
+ history_text = ""
309
+ flag = False
310
+ for x in history[::-1]:
311
+ if tokenizer(prompt + history_text + x, return_tensors="pt")['input_ids'].size(-1) <= max_length:
312
+ history_text = x + history_text
313
+ flag = True
314
+ else:
315
+ break
316
+ if flag:
317
+ return prompt + history_text, tokenizer(prompt + history_text, return_tensors="pt")
318
+ else:
319
+ return None
320
+
321
+
322
+ def is_stop_word_or_prefix(s: str, stop_words: list) -> bool:
323
+ for stop_word in stop_words:
324
+ if s.endswith(stop_word):
325
+ return True
326
+ for i in range(1, len(stop_word)):
327
+ if s.endswith(stop_word[:i]):
328
+ return True
329
+ return False
330
+
331
+
332
+ def load_tokenizer_and_model(base_model, adapter_model, load_8bit=False):
333
+ if torch.cuda.is_available():
334
+ device = "cuda"
335
+ else:
336
+ device = "cpu"
337
+
338
+ try:
339
+ if torch.backends.mps.is_available():
340
+ device = "mps"
341
+ except: # noqa: E722
342
+ pass
343
+ tokenizer = LlamaTokenizer.from_pretrained(base_model)
344
+ if device == "cuda":
345
+ model = LlamaForCausalLM.from_pretrained(
346
+ base_model,
347
+ load_in_8bit=load_8bit,
348
+ torch_dtype=torch.float16,
349
+ device_map="auto",
350
+ )
351
+ model = PeftModel.from_pretrained(
352
+ model,
353
+ adapter_model,
354
+ torch_dtype=torch.float16,
355
+ )
356
+ elif device == "mps":
357
+ model = LlamaForCausalLM.from_pretrained(
358
+ base_model,
359
+ device_map={"": device},
360
+ torch_dtype=torch.float16,
361
+ )
362
+ model = PeftModel.from_pretrained(
363
+ model,
364
+ adapter_model,
365
+ device_map={"": device},
366
+ torch_dtype=torch.float16,
367
+ )
368
+ else:
369
+ model = LlamaForCausalLM.from_pretrained(
370
+ base_model, device_map={"": device}, low_cpu_mem_usage=True
371
+ )
372
+ model = PeftModel.from_pretrained(
373
+ model,
374
+ adapter_model,
375
+ device_map={"": device},
376
+ )
377
+
378
+ if not load_8bit:
379
+ model.half() # seems to fix bugs for some users.
380
+
381
+ model.eval()
382
+ return tokenizer, model, device
assets/Kelpy-Codos.js ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ==UserScript==
2
+ // @name Kelpy Codos
3
+ // @namespace https://github.com/Keldos-Li/Kelpy-Codos
4
+ // @version 1.0.5
5
+ // @author Keldos; https://keldos.me/
6
+ // @description Add copy button to PRE tags before CODE tag, for Chuanhu ChatGPT especially.
7
+ // Based on Chuanhu ChatGPT version: ac04408 (2023-3-22)
8
+ // @license GPL-3.0
9
+ // @grant none
10
+ // ==/UserScript==
11
+
12
+ (function () {
13
+ 'use strict';
14
+
15
+ function addCopyButton(pre) {
16
+ var code = pre.querySelector('code');
17
+ if (!code) {
18
+ return; // 如果没有找到 <code> 元素,则不添加按钮
19
+ }
20
+ var firstChild = code.firstChild;
21
+ if (!firstChild) {
22
+ return; // 如果 <code> 元素没有子节点,则不添加按钮
23
+ }
24
+ var button = document.createElement('button');
25
+ button.textContent = '\uD83D\uDCCE'; // 使用 📎 符号作为“复制”按钮的文本
26
+ button.style.position = 'relative';
27
+ button.style.float = 'right';
28
+ button.style.fontSize = '1em'; // 可选:调整按钮大小
29
+ button.style.background = 'none'; // 可选:去掉背景颜色
30
+ button.style.border = 'none'; // 可选:去掉边框
31
+ button.style.cursor = 'pointer'; // 可选:显示指针样式
32
+ button.addEventListener('click', function () {
33
+ var range = document.createRange();
34
+ range.selectNodeContents(code);
35
+ range.setStartBefore(firstChild); // 将范围设置为第一个子节点之前
36
+ var selection = window.getSelection();
37
+ selection.removeAllRanges();
38
+ selection.addRange(range);
39
+
40
+ try {
41
+ var success = document.execCommand('copy');
42
+ if (success) {
43
+ button.textContent = '\u2714';
44
+ setTimeout(function () {
45
+ button.textContent = '\uD83D\uDCCE'; // 恢复按钮为“复制”
46
+ }, 2000);
47
+ } else {
48
+ button.textContent = '\u2716';
49
+ }
50
+ } catch (e) {
51
+ console.error(e);
52
+ button.textContent = '\u2716';
53
+ }
54
+
55
+ selection.removeAllRanges();
56
+ });
57
+ code.insertBefore(button, firstChild); // 将按钮插入到第一个子元素之前
58
+ }
59
+
60
+ function handleNewElements(mutationsList, observer) {
61
+ for (var mutation of mutationsList) {
62
+ if (mutation.type === 'childList') {
63
+ for (var node of mutation.addedNodes) {
64
+ if (node.nodeName === 'PRE') {
65
+ addCopyButton(node);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ var observer = new MutationObserver(handleNewElements);
73
+ observer.observe(document.documentElement, { childList: true, subtree: true });
74
+
75
+ document.querySelectorAll('pre').forEach(addCopyButton);
76
+ })();
assets/custom.css ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ --chatbot-color-light: #F3F3F3;
3
+ --chatbot-color-dark: #121111;
4
+ }
5
+
6
+ /* status_display */
7
+ #status_display {
8
+ display: flex;
9
+ min-height: 2.5em;
10
+ align-items: flex-end;
11
+ justify-content: flex-end;
12
+ }
13
+ #status_display p {
14
+ font-size: .85em;
15
+ font-family: monospace;
16
+ color: var(--body-text-color-subdued);
17
+ }
18
+
19
+
20
+
21
+ /* usage_display */
22
+ #usage_display {
23
+ height: 1em;
24
+ }
25
+ #usage_display p{
26
+ padding: 0 1em;
27
+ font-size: .85em;
28
+ font-family: monospace;
29
+ color: var(--body-text-color-subdued);
30
+ }
31
+ /* list */
32
+ ol:not(.options), ul:not(.options) {
33
+ padding-inline-start: 2em !important;
34
+ }
35
+
36
+ /* Thank @Keldos-Li for fixing it */
37
+ /* Light mode (default) */
38
+ #chuanhu_chatbot {
39
+ background-color: var(--chatbot-color-light) !important;
40
+ color: #000000 !important;
41
+ }
42
+ [data-testid = "bot"] {
43
+ background-color: #FFFFFF !important;
44
+ }
45
+ [data-testid = "user"] {
46
+ background-color: #95EC69 !important;
47
+ }
48
+
49
+ /* Dark mode */
50
+ .dark #chuanhu_chatbot {
51
+ background-color: var(--chatbot-color-dark) !important;
52
+ color: #FFFFFF !important;
53
+ }
54
+ .dark [data-testid = "bot"] {
55
+ background-color: #2C2C2C !important;
56
+ }
57
+ .dark [data-testid = "user"] {
58
+ background-color: #26B561 !important;
59
+ }
60
+
61
+ #chuanhu_chatbot {
62
+ height: 100%;
63
+ min-height: 400px;
64
+ }
65
+
66
+ [class *= "message"] {
67
+ border-radius: var(--radius-xl) !important;
68
+ border: none;
69
+ padding: var(--spacing-xl) !important;
70
+ font-size: var(--text-md) !important;
71
+ line-height: var(--line-md) !important;
72
+ min-height: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl));
73
+ min-width: calc(var(--text-md)*var(--line-md) + 2*var(--spacing-xl));
74
+ }
75
+ [data-testid = "bot"] {
76
+ max-width: 85%;
77
+ border-bottom-left-radius: 0 !important;
78
+ }
79
+ [data-testid = "user"] {
80
+ max-width: 85%;
81
+ width: auto !important;
82
+ border-bottom-right-radius: 0 !important;
83
+ }
84
+ /* Table */
85
+ table {
86
+ margin: 1em 0;
87
+ border-collapse: collapse;
88
+ empty-cells: show;
89
+ }
90
+ td,th {
91
+ border: 1.2px solid var(--border-color-primary) !important;
92
+ padding: 0.2em;
93
+ }
94
+ thead {
95
+ background-color: rgba(175,184,193,0.2);
96
+ }
97
+ thead th {
98
+ padding: .5em .2em;
99
+ }
100
+ /* Inline code */
101
+ code {
102
+ display: inline;
103
+ white-space: break-spaces;
104
+ border-radius: 6px;
105
+ margin: 0 2px 0 2px;
106
+ padding: .2em .4em .1em .4em;
107
+ background-color: rgba(175,184,193,0.2);
108
+ }
109
+ /* Code block */
110
+ pre code {
111
+ display: block;
112
+ overflow: auto;
113
+ white-space: pre;
114
+ background-color: hsla(0, 0%, 0%, 80%)!important;
115
+ border-radius: 10px;
116
+ padding: 1.4em 1.2em 0em 1.4em;
117
+ margin: 1.2em 2em 1.2em 0.5em;
118
+ color: #FFF;
119
+ box-shadow: 6px 6px 16px hsla(0, 0%, 0%, 0.2);
120
+ }
121
+ /* Hightlight */
122
+ .highlight .hll { background-color: #49483e }
123
+ .highlight .c { color: #75715e } /* Comment */
124
+ .highlight .err { color: #960050; background-color: #1e0010 } /* Error */
125
+ .highlight .k { color: #66d9ef } /* Keyword */
126
+ .highlight .l { color: #ae81ff } /* Literal */
127
+ .highlight .n { color: #f8f8f2 } /* Name */
128
+ .highlight .o { color: #f92672 } /* Operator */
129
+ .highlight .p { color: #f8f8f2 } /* Punctuation */
130
+ .highlight .ch { color: #75715e } /* Comment.Hashbang */
131
+ .highlight .cm { color: #75715e } /* Comment.Multiline */
132
+ .highlight .cp { color: #75715e } /* Comment.Preproc */
133
+ .highlight .cpf { color: #75715e } /* Comment.PreprocFile */
134
+ .highlight .c1 { color: #75715e } /* Comment.Single */
135
+ .highlight .cs { color: #75715e } /* Comment.Special */
136
+ .highlight .gd { color: #f92672 } /* Generic.Deleted */
137
+ .highlight .ge { font-style: italic } /* Generic.Emph */
138
+ .highlight .gi { color: #a6e22e } /* Generic.Inserted */
139
+ .highlight .gs { font-weight: bold } /* Generic.Strong */
140
+ .highlight .gu { color: #75715e } /* Generic.Subheading */
141
+ .highlight .kc { color: #66d9ef } /* Keyword.Constant */
142
+ .highlight .kd { color: #66d9ef } /* Keyword.Declaration */
143
+ .highlight .kn { color: #f92672 } /* Keyword.Namespace */
144
+ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
145
+ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */
146
+ .highlight .kt { color: #66d9ef } /* Keyword.Type */
147
+ .highlight .ld { color: #e6db74 } /* Literal.Date */
148
+ .highlight .m { color: #ae81ff } /* Literal.Number */
149
+ .highlight .s { color: #e6db74 } /* Literal.String */
150
+ .highlight .na { color: #a6e22e } /* Name.Attribute */
151
+ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */
152
+ .highlight .nc { color: #a6e22e } /* Name.Class */
153
+ .highlight .no { color: #66d9ef } /* Name.Constant */
154
+ .highlight .nd { color: #a6e22e } /* Name.Decorator */
155
+ .highlight .ni { color: #f8f8f2 } /* Name.Entity */
156
+ .highlight .ne { color: #a6e22e } /* Name.Exception */
157
+ .highlight .nf { color: #a6e22e } /* Name.Function */
158
+ .highlight .nl { color: #f8f8f2 } /* Name.Label */
159
+ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */
160
+ .highlight .nx { color: #a6e22e } /* Name.Other */
161
+ .highlight .py { color: #f8f8f2 } /* Name.Property */
162
+ .highlight .nt { color: #f92672 } /* Name.Tag */
163
+ .highlight .nv { color: #f8f8f2 } /* Name.Variable */
164
+ .highlight .ow { color: #f92672 } /* Operator.Word */
165
+ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */
166
+ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
167
+ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */
168
+ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
169
+ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
170
+ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
171
+ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */
172
+ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
173
+ .highlight .sc { color: #e6db74 } /* Literal.String.Char */
174
+ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */
175
+ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */
176
+ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */
177
+ .highlight .se { color: #ae81ff } /* Literal.String.Escape */
178
+ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
179
+ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */
180
+ .highlight .sx { color: #e6db74 } /* Literal.String.Other */
181
+ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */
182
+ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */
183
+ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
184
+ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
185
+ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */
186
+ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
187
+ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
188
+ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
189
+ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */
190
+ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */
assets/custom.js ADDED
@@ -0,0 +1 @@
 
 
1
+ // custom javascript here
assets/favicon.ico ADDED
main.py CHANGED
@@ -2,7 +2,7 @@ import os
2
  import shutil
3
 
4
  import gradio as gr
5
-
6
  from clc.langchain_application import LangChainApplication
7
 
8
  os.environ["CUDA_VISIBLE_DEVICES"] = '0'
@@ -93,9 +93,9 @@ def predict(input,
93
  search_text += web_content
94
  return '', history, history, search_text
95
 
96
-
97
- block = gr.Blocks()
98
- with block as demo:
99
  gr.Markdown("""<h1><center>Chinese-LangChain</center></h1>
100
  <center><font size=3>
101
  </center></font>
@@ -132,7 +132,10 @@ with block as demo:
132
  interactive=True)
133
  set_kg_btn = gr.Button("重新加载知识库")
134
 
135
- use_web = gr.Radio(["使用", "不使用"], label="web search", info="是否使用网络搜索,使用时确保网络通常")
 
 
 
136
 
137
  file = gr.File(label="将文件上传到知识库库,内容要尽量匹配",
138
  visible=True,
 
2
  import shutil
3
 
4
  import gradio as gr
5
+ from app_modules.presets import *
6
  from clc.langchain_application import LangChainApplication
7
 
8
  os.environ["CUDA_VISIBLE_DEVICES"] = '0'
 
93
  search_text += web_content
94
  return '', history, history, search_text
95
 
96
+ with open("assets/custom.css", "r", encoding="utf-8") as f:
97
+ customCSS = f.read()
98
+ with gr.Blocks(css=customCSS, theme=small_and_beautiful_theme) as demo:
99
  gr.Markdown("""<h1><center>Chinese-LangChain</center></h1>
100
  <center><font size=3>
101
  </center></font>
 
132
  interactive=True)
133
  set_kg_btn = gr.Button("重新加载知识库")
134
 
135
+ use_web = gr.Radio(["使用", "不使用"], label="web search",
136
+ info="是否使用网络搜索,使用时确保网络通常",
137
+ value="不使用"
138
+ )
139
 
140
  file = gr.File(label="将文件上传到知识库库,内容要尽量匹配",
141
  visible=True,