Spaces:
Sleeping
Sleeping
Keldos
commited on
Commit
·
2a53137
1
Parent(s):
50dc299
feat: 使用mathjax渲染页面中的数学公式
Browse files- ChuanhuChatbot.py +1 -0
- assets/custom.js +103 -4
- assets/load-mathjax.js +20 -0
- modules/overwrites.py +4 -2
ChuanhuChatbot.py
CHANGED
@@ -100,6 +100,7 @@ with gr.Blocks(css=customCSS, theme=small_and_beautiful_theme) as demo:
|
|
100 |
)
|
101 |
single_turn_checkbox = gr.Checkbox(label=i18n("单轮对话"), value=False)
|
102 |
use_websearch_checkbox = gr.Checkbox(label=i18n("使用在线搜索"), value=False)
|
|
|
103 |
language_select_dropdown = gr.Dropdown(
|
104 |
label=i18n("选择回复语言(针对搜索&索引功能)"),
|
105 |
choices=REPLY_LANGUAGES,
|
|
|
100 |
)
|
101 |
single_turn_checkbox = gr.Checkbox(label=i18n("单轮对话"), value=False)
|
102 |
use_websearch_checkbox = gr.Checkbox(label=i18n("使用在线搜索"), value=False)
|
103 |
+
render_latex_checkbox = gr.Checkbox(label="渲染LaTeX公式", elem_id="render_latex_checkbox")
|
104 |
language_select_dropdown = gr.Dropdown(
|
105 |
label=i18n("选择回复语言(针对搜索&索引功能)"),
|
106 |
choices=REPLY_LANGUAGES,
|
assets/custom.js
CHANGED
@@ -14,6 +14,9 @@ var userInfoDiv = null;
|
|
14 |
var appTitleDiv = null;
|
15 |
var chatbot = null;
|
16 |
var apSwitch = null;
|
|
|
|
|
|
|
17 |
|
18 |
var ga = document.getElementsByTagName("gradio-app");
|
19 |
var targetNode = ga[0];
|
@@ -22,13 +25,14 @@ var isInIframe = (window.self !== window.top);
|
|
22 |
// gradio 页面加载好了么??? 我能动你的元素了么??
|
23 |
function gradioLoaded(mutations) {
|
24 |
for (var i = 0; i < mutations.length; i++) {
|
25 |
-
if (mutations[i].addedNodes.length) {
|
26 |
gradioContainer = document.querySelector(".gradio-container");
|
27 |
user_input_tb = document.getElementById('user_input_tb');
|
28 |
userInfoDiv = document.getElementById("user_info");
|
29 |
appTitleDiv = document.getElementById("app_title");
|
30 |
chatbot = document.querySelector('#chuanhu_chatbot');
|
31 |
apSwitch = document.querySelector('.apSwitch input[type="checkbox"]');
|
|
|
32 |
|
33 |
if (gradioContainer && apSwitch) { // gradioCainter 加载出来了没?
|
34 |
adjustDarkMode();
|
@@ -40,7 +44,11 @@ function gradioLoaded(mutations) {
|
|
40 |
setTimeout(showOrHideUserInfo(), 2000);
|
41 |
}
|
42 |
if (chatbot) { // chatbot 加载出来了没?
|
43 |
-
setChatbotHeight()
|
|
|
|
|
|
|
|
|
44 |
}
|
45 |
}
|
46 |
}
|
@@ -140,12 +148,12 @@ function showOrHideUserInfo() {
|
|
140 |
appTitleDiv.ontouchend = function () {
|
141 |
setTimeout(function () {
|
142 |
toggleUserInfoVisibility(true);
|
143 |
-
}, 3000);
|
144 |
};
|
145 |
userInfoDiv.ontouchend = function () {
|
146 |
setTimeout(function () {
|
147 |
toggleUserInfoVisibility(true);
|
148 |
-
}, 3000);
|
149 |
};
|
150 |
sendBtn.ontouchend = function () {
|
151 |
setTimeout(function () {
|
@@ -209,6 +217,97 @@ function setChatbotHeight() {
|
|
209 |
}
|
210 |
}
|
211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
// 监视页面内部 DOM 变动
|
213 |
var observer = new MutationObserver(function (mutations) {
|
214 |
gradioLoaded(mutations);
|
|
|
14 |
var appTitleDiv = null;
|
15 |
var chatbot = null;
|
16 |
var apSwitch = null;
|
17 |
+
var messageBotDivs = null;
|
18 |
+
var renderLatex = null;
|
19 |
+
var shouldRenderLatex = false;
|
20 |
|
21 |
var ga = document.getElementsByTagName("gradio-app");
|
22 |
var targetNode = ga[0];
|
|
|
25 |
// gradio 页面加载好了么??? 我能动你的元素了么??
|
26 |
function gradioLoaded(mutations) {
|
27 |
for (var i = 0; i < mutations.length; i++) {
|
28 |
+
if (mutations[i].addedNodes.length) {
|
29 |
gradioContainer = document.querySelector(".gradio-container");
|
30 |
user_input_tb = document.getElementById('user_input_tb');
|
31 |
userInfoDiv = document.getElementById("user_info");
|
32 |
appTitleDiv = document.getElementById("app_title");
|
33 |
chatbot = document.querySelector('#chuanhu_chatbot');
|
34 |
apSwitch = document.querySelector('.apSwitch input[type="checkbox"]');
|
35 |
+
renderLatex = document.querySelector("#render_latex_checkbox > label > input");
|
36 |
|
37 |
if (gradioContainer && apSwitch) { // gradioCainter 加载出来了没?
|
38 |
adjustDarkMode();
|
|
|
44 |
setTimeout(showOrHideUserInfo(), 2000);
|
45 |
}
|
46 |
if (chatbot) { // chatbot 加载出来了没?
|
47 |
+
setChatbotHeight();
|
48 |
+
}
|
49 |
+
if (renderLatex) { // renderLatex 加载出来了没?
|
50 |
+
shouldRenderLatex = renderLatex.checked;
|
51 |
+
updateMathJax();
|
52 |
}
|
53 |
}
|
54 |
}
|
|
|
148 |
appTitleDiv.ontouchend = function () {
|
149 |
setTimeout(function () {
|
150 |
toggleUserInfoVisibility(true);
|
151 |
+
}, 3000);
|
152 |
};
|
153 |
userInfoDiv.ontouchend = function () {
|
154 |
setTimeout(function () {
|
155 |
toggleUserInfoVisibility(true);
|
156 |
+
}, 3000);
|
157 |
};
|
158 |
sendBtn.ontouchend = function () {
|
159 |
setTimeout(function () {
|
|
|
217 |
}
|
218 |
}
|
219 |
|
220 |
+
var rendertime = 0; // for debugging
|
221 |
+
var mathjaxUpdated = false;
|
222 |
+
|
223 |
+
function renderMathJax() {
|
224 |
+
messageBotDivs = document.querySelectorAll('.message.bot');
|
225 |
+
for (var i = 0; i < messageBotDivs.length; i++) {
|
226 |
+
var mathJaxSpan = messageBotDivs[i].querySelector('.MathJax_Preview');
|
227 |
+
if (!mathJaxSpan && shouldRenderLatex && !mathjaxUpdated) {
|
228 |
+
MathJax.Hub.Queue(["Typeset", MathJax.Hub, messageBotDivs[i]]);
|
229 |
+
rendertime +=1; // for debugging
|
230 |
+
console.log("renderingMathJax", i)
|
231 |
+
}
|
232 |
+
}
|
233 |
+
mathjaxUpdated = true;
|
234 |
+
console.log("MathJaxTriedToRender!!!")
|
235 |
+
}
|
236 |
+
|
237 |
+
function removeMathjax() {
|
238 |
+
// var jax = MathJax.Hub.getAllJax();
|
239 |
+
// for (var i = 0; i < jax.length; i++) {
|
240 |
+
// // MathJax.typesetClear(jax[i]);
|
241 |
+
// jax[i].Text(newmath)
|
242 |
+
// jax[i].Reprocess()
|
243 |
+
// }
|
244 |
+
// 我真的不会了啊啊啊,mathjax并没有提供转换为原先文本的办法。
|
245 |
+
mathjaxUpdated = true;
|
246 |
+
console.log("MathJax removed!");
|
247 |
+
}
|
248 |
+
|
249 |
+
function updateMathJax() {
|
250 |
+
renderLatex.addEventListener("change", function() {
|
251 |
+
shouldRenderLatex = renderLatex.checked;
|
252 |
+
console.log(shouldRenderLatex)
|
253 |
+
if (!mathjaxUpdated) {
|
254 |
+
if (shouldRenderLatex) {
|
255 |
+
renderMathJax();
|
256 |
+
} else {
|
257 |
+
console.log("取消渲染!")
|
258 |
+
removeMathjax();
|
259 |
+
}
|
260 |
+
} else {
|
261 |
+
if (!shouldRenderLatex) {
|
262 |
+
mathjaxUpdated = false; // reset
|
263 |
+
}
|
264 |
+
}
|
265 |
+
});
|
266 |
+
if (shouldRenderLatex && !mathjaxUpdated) {
|
267 |
+
renderMathJax();
|
268 |
+
}
|
269 |
+
mathjaxUpdated = false;
|
270 |
+
}
|
271 |
+
|
272 |
+
let timeoutId;
|
273 |
+
let isThrottled = false;
|
274 |
+
// 监听所有元素中message的变化,用来查找需要渲染的mathjax
|
275 |
+
var mObserver = new MutationObserver(function (mutationsList, observer) {
|
276 |
+
if (shouldRenderLatex) {
|
277 |
+
for (var mutation of mutationsList) {
|
278 |
+
if (mutation.type === 'childList') {
|
279 |
+
for (var node of mutation.addedNodes) {
|
280 |
+
if (node.nodeType === 1 && node.classList.contains('message') && node.classList.contains('bot')) {
|
281 |
+
// console.log("added");
|
282 |
+
renderMathJax();
|
283 |
+
mathjaxUpdated = false;
|
284 |
+
}
|
285 |
+
}
|
286 |
+
for (var node of mutation.removedNodes) {
|
287 |
+
if (node.nodeType === 1 && node.classList.contains('message') && node.classList.contains('bot')) {
|
288 |
+
// console.log("removed");
|
289 |
+
renderMathJax();
|
290 |
+
mathjaxUpdated = false;
|
291 |
+
}
|
292 |
+
}
|
293 |
+
} else if (mutation.type === 'attributes') {
|
294 |
+
if (mutation.target.nodeType === 1 && mutation.target.classList.contains('message') && mutation.target.classList.contains('bot')) {
|
295 |
+
if (isThrottled) break; // 为了防止重复不断疯狂渲染,加上等待_(:з」∠)_
|
296 |
+
isThrottled = true;
|
297 |
+
clearTimeout(timeoutId);
|
298 |
+
timeoutId = setTimeout(() => {
|
299 |
+
isThrottled = false;
|
300 |
+
// console.log("changed");
|
301 |
+
renderMathJax();
|
302 |
+
mathjaxUpdated = false;
|
303 |
+
}, 500);
|
304 |
+
}
|
305 |
+
}
|
306 |
+
}
|
307 |
+
}
|
308 |
+
});
|
309 |
+
mObserver.observe(targetNode, { attributes: true, childList: true, subtree: true });
|
310 |
+
|
311 |
// 监视页面内部 DOM 变动
|
312 |
var observer = new MutationObserver(function (mutations) {
|
313 |
gradioLoaded(mutations);
|
assets/load-mathjax.js
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// window.MathJax = {
|
2 |
+
// tex: {
|
3 |
+
// inlineMath: [['$', '$'], ['\\(', '\\)']]
|
4 |
+
// },
|
5 |
+
// svg: {
|
6 |
+
// fontCache: 'global'
|
7 |
+
// }
|
8 |
+
// };
|
9 |
+
|
10 |
+
(function () {
|
11 |
+
var script = document.createElement('script');
|
12 |
+
script.src = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-MML-AM_CHTML";
|
13 |
+
script.async = true;
|
14 |
+
document.head.appendChild(script);
|
15 |
+
|
16 |
+
var config = document.createElement("script");
|
17 |
+
config.type = "text/x-mathjax-config";
|
18 |
+
config.text = "MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\\\(','\\\\)']],displayMath: [['$$','$$'], ['\\\\[','\\\\]']]}});";
|
19 |
+
document.head.appendChild(config);
|
20 |
+
})();
|
modules/overwrites.py
CHANGED
@@ -76,13 +76,15 @@ def postprocess_chat_messages(
|
|
76 |
else:
|
77 |
raise ValueError(f"Invalid message for Chatbot component: {chat_message}")
|
78 |
|
79 |
-
with open("./assets/custom.js", "r", encoding="utf-8") as f, open("./assets/Kelpy-Codos.js", "r", encoding="utf-8") as f2:
|
80 |
customJS = f.read()
|
81 |
kelpyCodos = f2.read()
|
|
|
|
|
82 |
|
83 |
def reload_javascript():
|
84 |
print("Reloading javascript...")
|
85 |
-
js = f'<script>{customJS}</script><script>{kelpyCodos}</script>'
|
86 |
def template_response(*args, **kwargs):
|
87 |
res = GradioTemplateResponseOriginal(*args, **kwargs)
|
88 |
res.body = res.body.replace(b'</html>', f'{js}</html>'.encode("utf8"))
|
|
|
76 |
else:
|
77 |
raise ValueError(f"Invalid message for Chatbot component: {chat_message}")
|
78 |
|
79 |
+
with open("./assets/custom.js", "r", encoding="utf-8") as f, open("./assets/Kelpy-Codos.js", "r", encoding="utf-8") as f2, open("./assets/load-mathjax.js", "r", encoding="utf-8") as f3:
|
80 |
customJS = f.read()
|
81 |
kelpyCodos = f2.read()
|
82 |
+
loadMathjax = f3.read()
|
83 |
+
|
84 |
|
85 |
def reload_javascript():
|
86 |
print("Reloading javascript...")
|
87 |
+
js = f'<script>{customJS}</script><script>{kelpyCodos}</script><script async>{loadMathjax}</script>'
|
88 |
def template_response(*args, **kwargs):
|
89 |
res = GradioTemplateResponseOriginal(*args, **kwargs)
|
90 |
res.body = res.body.replace(b'</html>', f'{js}</html>'.encode("utf8"))
|