update interface
Browse files- core/api/server.py +1 -1
- core/api/static/index.html +38 -0
core/api/server.py
CHANGED
|
@@ -200,7 +200,7 @@ if __name__ == "__main__":
|
|
| 200 |
import uvicorn
|
| 201 |
uvicorn.run(
|
| 202 |
"core.api.server:app",
|
| 203 |
-
host=os.getenv("API_HOST", "
|
| 204 |
port=int(os.getenv("API_PORT", "8000")),
|
| 205 |
reload=False,
|
| 206 |
)
|
|
|
|
| 200 |
import uvicorn
|
| 201 |
uvicorn.run(
|
| 202 |
"core.api.server:app",
|
| 203 |
+
host=os.getenv("API_HOST", "0.0.0.0"),
|
| 204 |
port=int(os.getenv("API_PORT", "8000")),
|
| 205 |
reload=False,
|
| 206 |
)
|
core/api/static/index.html
CHANGED
|
@@ -5,9 +5,20 @@
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>HUST RAG — Trợ lý Học vụ</title>
|
| 7 |
<meta name="description" content="Hệ thống hỏi đáp quy chế sinh viên Đại học Bách khoa Hà Nội">
|
|
|
|
| 8 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 9 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
| 10 |
<link rel="stylesheet" href="/static/style.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
</head>
|
| 12 |
<body>
|
| 13 |
<div id="app">
|
|
@@ -95,6 +106,21 @@
|
|
| 95 |
}
|
| 96 |
|
| 97 |
function renderMarkdown(text) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
let html = text
|
| 99 |
.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
|
| 100 |
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
@@ -109,6 +135,12 @@
|
|
| 109 |
.replace(/\n/g, '<br>');
|
| 110 |
|
| 111 |
html = html.replace(/((?:<li>.*?<\/li>\s*)+)/gs, '<ul>$1</ul>');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
return `<p>${html}</p>`.replace(/<p><\/p>/g, '');
|
| 113 |
}
|
| 114 |
|
|
@@ -190,6 +222,12 @@
|
|
| 190 |
|
| 191 |
if (fullText) {
|
| 192 |
contentEl.innerHTML = renderMarkdown(fullText);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
}
|
| 194 |
} catch (err) {
|
| 195 |
contentEl.innerHTML = '<span style="color: var(--red-accent)">Lỗi kết nối. Vui lòng thử lại.</span>';
|
|
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>HUST RAG — Trợ lý Học vụ</title>
|
| 7 |
<meta name="description" content="Hệ thống hỏi đáp quy chế sinh viên Đại học Bách khoa Hà Nội">
|
| 8 |
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎓</text></svg>">
|
| 9 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 10 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
| 11 |
<link rel="stylesheet" href="/static/style.css">
|
| 12 |
+
<script>
|
| 13 |
+
window.MathJax = {
|
| 14 |
+
tex: {
|
| 15 |
+
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
| 16 |
+
displayMath: [['$$', '$$'], ['\\[', '\\]']]
|
| 17 |
+
},
|
| 18 |
+
startup: { typeset: false } // We'll trigger it manually
|
| 19 |
+
};
|
| 20 |
+
</script>
|
| 21 |
+
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" async></script>
|
| 22 |
</head>
|
| 23 |
<body>
|
| 24 |
<div id="app">
|
|
|
|
| 106 |
}
|
| 107 |
|
| 108 |
function renderMarkdown(text) {
|
| 109 |
+
// 1. Loại bỏ thẻ <think> (Che giấu suy nghĩ của model)
|
| 110 |
+
text = text.replace(/<think>[\s\S]*?<\/think>\n?/g, '');
|
| 111 |
+
if (text.includes('<think>')) {
|
| 112 |
+
// Nếu thẻ think chưa được đóng (đang stream)
|
| 113 |
+
text = text.replace(/<think>[\s\S]*/g, '<span style="color: #666; font-style: italic;">[Đang suy nghĩ...]</span>');
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
// 2. Bảo vệ các công thức toán (MathJax) khỏi bị lỗi khi render Markdown
|
| 117 |
+
let mathBlocks = [];
|
| 118 |
+
text = text.replace(/\$\$([\s\S]*?)\$\$/g, function(match) {
|
| 119 |
+
mathBlocks.push(match);
|
| 120 |
+
return `__MATH_BLOCK_${mathBlocks.length - 1}__`;
|
| 121 |
+
});
|
| 122 |
+
|
| 123 |
+
// 3. Render Markdown cơ bản
|
| 124 |
let html = text
|
| 125 |
.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
|
| 126 |
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
|
|
| 135 |
.replace(/\n/g, '<br>');
|
| 136 |
|
| 137 |
html = html.replace(/((?:<li>.*?<\/li>\s*)+)/gs, '<ul>$1</ul>');
|
| 138 |
+
|
| 139 |
+
// Khôi phục lại công thức toán
|
| 140 |
+
for (let i = 0; i < mathBlocks.length; i++) {
|
| 141 |
+
html = html.replace(`__MATH_BLOCK_${i}__`, mathBlocks[i]);
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
return `<p>${html}</p>`.replace(/<p><\/p>/g, '');
|
| 145 |
}
|
| 146 |
|
|
|
|
| 222 |
|
| 223 |
if (fullText) {
|
| 224 |
contentEl.innerHTML = renderMarkdown(fullText);
|
| 225 |
+
// Chạy lại MathJax để render công thức Toán sau khi đã stream hoàn tất
|
| 226 |
+
if (window.MathJax && window.MathJax.typesetPromise) {
|
| 227 |
+
try {
|
| 228 |
+
await window.MathJax.typesetPromise([contentEl]);
|
| 229 |
+
} catch(err) {}
|
| 230 |
+
}
|
| 231 |
}
|
| 232 |
} catch (err) {
|
| 233 |
contentEl.innerHTML = '<span style="color: var(--red-accent)">Lỗi kết nối. Vui lòng thử lại.</span>';
|