prain: web UI with a model monitor
A clear chat page (markdown, code blocks with copy, stop, new chat, kept in the browser, drafts shown as such) and a monitor sidebar, a sheet on phones: tokens/s, a live map of the 30 x 128 experts (in VRAM, used now, copied in), VRAM hit rate, copies, context, prompt cache, GPU VRAM/load/temperature/power/fan. GET /status merges vLLM /metrics, amdgpu sysfs and the stats file, which now lists the experts in VRAM. /warm answers 202 when a warm-up starts. README: the int4 kernels, their A/B, 2048-token chunks as a trade, prompt logprobs limit.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
PAGE = (Path(__file__).parent.parent / "prain" / "web.html").read_text()
|
||||
|
||||
|
||||
@unittest.skipUnless(shutil.which("node"), "needs node")
|
||||
class Markdown(unittest.TestCase):
|
||||
"""The page's md() (model output -> innerHTML) run in node."""
|
||||
|
||||
def md(self, text):
|
||||
script = PAGE[PAGE.index("<script>") + 8:PAGE.index("/* ---------- thread")]
|
||||
script = script.split("/* ---------- markdown", 1)[1].split("*/", 1)[1]
|
||||
out = subprocess.run(["node", "-e", script + f"\nprocess.stdout.write(md({json.dumps(text)}))"],
|
||||
capture_output=True, text=True, check=True)
|
||||
return out.stdout
|
||||
|
||||
def test_html_in_model_output_is_text(self):
|
||||
html = self.md('<img src=x onerror="alert(1)"> **<b>hi</b>** `<i>` [x](javascript:alert(1))')
|
||||
self.assertNotIn("<img", html)
|
||||
self.assertNotIn("<b>", html)
|
||||
self.assertNotIn('href="javascript', html)
|
||||
self.assertIn("<img src=x onerror="alert(1)">", html)
|
||||
self.assertIn("<strong><b>hi</b></strong>", html)
|
||||
|
||||
def test_blocks(self):
|
||||
html = self.md("# Title\n\nSome *very* **bold** text with `code` and "
|
||||
"[a link](https://x.org/?a=1&b=2).\n\n```python\nif a < b:\n pass\n```\n"
|
||||
"3. three\n4. four\n\n- one\n more\n- two\n\n| a | b |\n|---|---|\n| 1 | 2 |\n"
|
||||
"\n> quoted\n\n---\nend")
|
||||
for part in ("<h3>Title</h3>", "<em>very</em>", "<strong>bold</strong>", "<code>code</code>",
|
||||
'<a href="https://x.org/?a=1&b=2" target="_blank" rel="noopener noreferrer">',
|
||||
'<span>python</span>', "<pre><code>if a < b:\n pass</code></pre>",
|
||||
'<ol start="3"><li>three</li><li>four</li></ol>',
|
||||
"<ul><li>one more</li><li>two</li></ul>",
|
||||
"<th>a</th><th>b</th></tr></thead><tbody><tr><td>1</td><td>2</td>",
|
||||
"<blockquote><p>quoted</p></blockquote>", "<hr>", "<p>end</p>"):
|
||||
self.assertIn(part, html)
|
||||
|
||||
def test_an_open_fence_while_streaming_is_code(self):
|
||||
self.assertIn("<pre><code>x = 1\n# not a heading</code></pre>",
|
||||
self.md("Here:\n```\nx = 1\n# not a heading"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user