<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件]]></title><description><![CDATA[<h1>给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件</h1>
<blockquote>
<p dir="auto">起因：在 DGX Spark 上跑大模型时，想随时看清 CPU / GPU / 统一内存 / 磁盘 / 网络 / 推理吞吐的真实状态，<br />
以及推理引擎（推理服务）到底跑得怎么样。官方 Dashboard 看不了推理细节，<code>nvtop</code>/<code>btop</code> 又看不到<br />
LLM 侧的指标，索性自己写了一个。</p>
<p dir="auto"><strong>约束：零第三方依赖</strong>——后端只用 Python 标准库，前端单文件 HTML + 原生 JS，不引任何 CDN。<br />
拷过去 <code>python3 monitor.py</code> 就能跑。</p>
</blockquote>
<p dir="auto">[整体效果]<br />
<img src="https://upload.lcz.me/uploads/a1b671cd-5305-47b2-8dd7-b7066328dd52.png" alt="01-overview.png" class="img-markdown  img-fluid" /></p>
<hr />
<h2>目录</h2>
<ul>
<li><a href="#%E5%AE%83%E6%9C%89%E4%BB%80%E4%B9%88">它有什么</a></li>
<li><a href="#%E6%9E%B6%E6%9E%84">架构</a></li>
<li><a href="#%E5%80%BC%E5%BE%97%E6%8A%84%E7%9A%84-6-%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%BB%86%E8%8A%82">值得抄的 6 个实现细节</a></li>
<li><a href="#%E9%83%A8%E7%BD%B2">部署</a></li>
<li><a href="#%E8%B8%A9%E5%9D%91%E6%B8%85%E5%8D%95%E5%AE%9E%E6%88%98">踩坑清单</a></li>
<li><a href="#%E6%96%87%E4%BB%B6%E6%B8%85%E5%8D%95">文件清单</a></li>
<li><a href="#%E5%B7%B2%E7%9F%A5%E9%99%90%E5%88%B6">已知限制</a></li>
</ul>
<hr />
<h2>它有什么</h2>
<p dir="auto"><strong>17 个面板，全部可拖动、可缩放、可换位置</strong>，布局存在浏览器本地，导出一段 JSON 就能在别的机器上复现。</p>
<p dir="auto">顶部 9 张 KPI 卡带迷你走势线；中间 6 张曲线图支持鼠标悬停出十字线和数值气泡，Y 轴单位会在<br />
<code>B/s → KB/s → MB/s</code> 之间自动切换。</p>
<p dir="auto">[LLM 运维区]<br />
<img src="https://upload.lcz.me/uploads/2cf7d625-7a26-4790-a3e3-3970b0b23a61.png" alt="02-llm-ops.png" class="img-markdown  img-fluid" /></p>
<p dir="auto">上排是 <strong>推理引擎</strong>（running/waiting、解码速度、TTFT、TPOT、KV Cache 分池占用、MTP 接受率）、<br />
<strong>容器 llm</strong>（CPU / 内存 / net / block IO）、<strong>一键测速</strong>（发一次真实对话，按 <code>usage</code> 计数算吞吐）。</p>
<p dir="auto">下排是硬件明细：<strong>CPU 每核负载</strong>（20 核 GB10）、<strong>温度传感器 / 风扇</strong>（带过热状态染色）、<br />
<strong>磁盘 I/O</strong>、<strong>网络接口</strong>（含错误/丢包计数）。</p>
<p dir="auto">[硬件表格区]<br />
<img src="https://upload.lcz.me/uploads/62c02bb2-e047-42c3-ad28-0677168762d9.png" alt="03-tables.png" class="img-markdown  img-fluid" /></p>
<p dir="auto">再往下是 <strong>进程 Top</strong>、<strong>引擎指标明细表</strong>、<strong>当前生效配置</strong>（直接读容器里的环境变量，一眼看到<br />
<code>TF_SOLO_ROWS</code> / <code>TF_SPILL_GIB</code> 这些实际生效的参数）、<strong>容器日志尾部</strong>。</p>
<p dir="auto">[进程 / 引擎指标 / 生效配置]<br />
<img src="https://upload.lcz.me/uploads/0b2a027c-29c9-49e5-abf2-d57158e69130.png" alt="04-detail.png" class="img-markdown  img-fluid" /></p>
<h3>交互细节</h3>
<p dir="auto">鼠标悬停在曲线上，十字线定位到具体时刻，气泡给出该时刻的各序列数值：</p>
<p dir="auto">[悬停交互]<br />
<img src="https://upload.lcz.me/uploads/3d8987b0-c44e-45e6-b026-4c2124853be6.png" alt="05-hover.png" class="img-markdown  img-fluid" /></p>
<p dir="auto">拖卡片标题栏换位置，拖右下角的小三角改大小。布局可以导出成 JSON：</p>
<p dir="auto">[布局导出]<br />
<img src="https://upload.lcz.me/uploads/5cf8282b-ecaa-4e4e-8d37-364c739239f2.png" alt="06-layout.png" class="img-markdown  img-fluid" /></p>
<p dir="auto">复制这段 JSON，粘到另一台机器上点「应用」，就是一模一样的排布。</p>
<hr />
<h2>架构</h2>
<pre><code>monitor.py    ~34 KB   Python 3 标准库，无第三方依赖
  ├─ 采样线程   1 Hz 写环形缓冲（deque(maxlen=...)）
  ├─ HTTP 服务  ThreadingHTTPServer
  └─ API
      /api/snapshot   当前快照（含 host/cpu/memory/gpu/sensors/disk/network/processes/engine）
      /api/series     历史序列，?window=60|300|900|1800|3600
      /api/stats      snapshot + 容器 stats + uptime
      /api/config     容器镜像/状态/环境变量（docker inspect）
      /api/logs       容器日志尾部 ?tail=200
      /api/probe      发一次真实对话，测 TTFT / decode 速度
      /api/key        设置 API Key
      /api/healthz

index.html    ~49 KB   单文件：HTML + CSS + JS，无 CDN
</code></pre>
<p dir="auto"><strong>为什么服务端采样？</strong> 因为磁盘/网络的速率本质上就是「两次采样之间的差值」，没法在 HTTP 请求发生的<br />
那一刻凭空算出来。所以有一个后台线程固定 1 Hz 采样写进 <code>deque</code>，前端只是来取。</p>
<hr />
<h2>值得抄的 6 个实现细节</h2>
<h3>1. 速率只能用 delta 算，不能在请求时重新采样</h3>
<p dir="auto">这是最容易踩的坑。直觉写法是「收到请求 → 读一次 <code>/proc/diskstats</code> → 和上次比」，但**「上次」存在哪**<br />
是问题：如果请求比采样线程更频繁，就会拿两个几乎同时刻的采样点作差，差值被摊薄成一个极小的时间窗，<br />
算出来的速率要么是 0，要么抖得没法看。</p>
<p dir="auto">正确做法是：<strong>后台线程独占采样，HTTP 只返回缓存的结果</strong>。</p>
<pre><code class="language-python">def disk_info(prev, dt):
    """prev 是上一次采样的 /proc/diskstats 快照，dt 是两次采样之间的时间差。"""
    for name, v in cur.items():
        old = (prev or {}).get(name)
        if old and dt &gt; 0:
            d["read_bps"]  = round((v[2] - old[2]) * 512 / dt, 1)   # 扇区数 × 512 = 字节
            d["write_bps"] = round((v[6] - old[6]) * 512 / dt, 1)
            d["read_iops"] = round((v[0] - old[0]) / dt, 2)
</code></pre>
<p dir="auto">后台循环里 <code>dt</code> 用真实经过时间：</p>
<pre><code class="language-python">def sample_once():
    now = time.time()
    dt = max(0.5, now - STATE["prev"].get("ts", now - SAMPLE_INTERVAL))
    STATE["prev"]["ts"] = now
</code></pre>
<h3>2. 统一内存架构下，<code>nvidia-smi</code> 的显存字段是 <code>[N/A]</code></h3>
<p dir="auto">GB10 的 CPU 和 GPU 共享同一块内存（标称 128 GB，系统可见约 122 GiB），<br />
<code>nvidia-smi</code> 对显存总量/占用直接返回 <code>[N/A]</code>：</p>
<pre><code class="language-bash">$ nvidia-smi --query-gpu=memory.total,memory.used --format=csv
[N/A], [N/A]
</code></pre>
<p dir="auto">所以面板里的「统一内存」读的是 <code>/proc/meminfo</code>，而不是显存字段；GPU 面板只取利用率/温度/功耗。<br />
另外 <code>power.limit</code>、<code>fan.speed</code> 在这台机器上也是 <code>[N/A]</code>，别指望它们。</p>
<p dir="auto">顺带一个有用的取法：<strong>逐进程显存是可以拿到的</strong>（<code>--query-compute-apps</code>），把它求和就得到<br />
「模型常驻显存」：</p>
<pre><code class="language-python">rc, so, _se = run(["nvidia-smi", "--query-compute-apps=pid,used_gpu_memory,process_name",
                   "--format=csv,noheader,nounits"])
out["model_gpu_mib"] = round(sum(p["mem_mib"] for p in procs), 1)
</code></pre>
<h3>3. 用 12 栅格显式定位，而不是 <code>auto-fit</code></h3>
<p dir="auto">最初用 <code>grid-template-columns: repeat(auto-fit, minmax(330px, 1fr))</code>，结果卡片宽度随窗口变化，<br />
而且<strong>没法留空位、没法叠放</strong>。改成显式坐标后什么都解决了：</p>
<pre><code class="language-css">.grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));
      grid-auto-rows:44px;gap:10px}
.card{grid-column:span var(--w,3);grid-row:span var(--h,5)}
</code></pre>
<p dir="auto">每张卡片存 <code>{x, y, w, h}</code>（单位是栅格格数），JS 直接写：</p>
<pre><code class="language-js">el.style.gridColumn = (c.x + 1) + " / span " + c.w;
el.style.gridRow    = (c.y + 1) + " / span " + c.h;
</code></pre>
<p dir="auto">显式坐标才能表达「第二行右边留空」和「磁盘 I/O 叠在网络接口下面」这种排布——自动排布是做不到的。</p>
<h3>4. 卡片被压住时「就近挪开」，而不是跳到页面另一头</h3>
<p dir="auto">拖动时如果落点压住了别的卡片，需要把被压的挪走。朴素的实现是「从左上角扫描找第一个空位」，<br />
结果卡片会莫名其妙飞到页面最上面。这里改成<strong>收集所有空位，再按离原位的距离排序</strong>：</p>
<pre><code class="language-js">function findSpot(w, h, exceptId, prefer){
  const free = [];
  for (let y = 0; y &lt; 400; y++)
    for (let x = 0; x &lt;= GRID.cols - w; x++){
      const cand = {x, y, w, h};
      let ok = true;
      for (const [id, c] of Object.entries(state)){
        if (id === exceptId) continue;
        if (overlaps(cand, c)){ ok = false; break; }
      }
      if (ok) free.push({x, y});
    }
  if (!free.length) return {x: 0, y: 0};
  if (prefer)   // 就近安置：离原位越近越优先
    free.sort((a, b) =&gt; (Math.abs(a.x - prefer.x) + Math.abs(a.y - prefer.y))
                      - (Math.abs(b.x - prefer.x) + Math.abs(b.y - prefer.y)));
  return free[0];
}
</code></pre>
<h3>5. canvas 曲线：nice tick + 自动单位 + 悬停十字线</h3>
<p dir="auto">不用图表库，纯 canvas 画。三点值得注意：</p>
<p dir="auto"><strong>Y 轴刻度取「好看」的步长</strong>，否则会出现 <code>7.4993</code> 这种刻度：</p>
<pre><code class="language-js">niceStep(range){
  const raw = range / 4, mag = Math.pow(10, Math.floor(Math.log10(raw) || 0));
  const n = raw / mag;
  return (n &lt;= 1 ? 1 : n &lt;= 2 ? 2 : n &lt;= 2.5 ? 2.5 : n &lt;= 5 ? 5 : 10) * mag;
}
</code></pre>
<p dir="auto"><strong>单位自动切换</strong>：网络速率可能是 500 B/s 也可能是 200 MB/s，固定单位必然有一头显示成<br />
<code>0.00 MB/s</code> 或 <code>123456789 B/s</code>。所以按量级挑单位：</p>
<pre><code class="language-js">if (this.opts.autoUnit){
  const m = Math.max(Math.abs(vmin), Math.abs(vmax));
  if      (m &gt;= 1048576){ this._scale = 1048576; this._unit = "MB/s"; }
  else if (m &gt;= 1024)   { this._scale = 1024;    this._unit = "KB/s"; }
  else                 { this._scale = 1;       this._unit = "B/s"; }
}
</code></pre>
<p dir="auto"><strong>悬停十字线</strong>：鼠标位置换算成时间，吸附到最近的采样点：</p>
<pre><code class="language-js">onMove(e){
  const g = this._geo;
  const x = e.clientX - this.cv.getBoundingClientRect().left;
  this.hover = (x - g.padL) / g.pw;
  this.draw();                      // 重画时画十字线
  const t = g.t0 + (g.t1 - g.t0) * this.hover;
  for (const s of this.series){
    const p = this.nearest(s.data, t);   // 线性找最近点
    ...
  }
}
</code></pre>
<h3>6. 布局持久化 + JSON 导出/导入</h3>
<p dir="auto">位置存 <code>localStorage</code>，再提供导出/导入，这样「我摆好的版面」可以固化成一段文本：</p>
<pre><code class="language-js">const LAYOUT_KEY = "sparkmon_layout_v3";
function readLayout(){ return {layout: JSON.parse(JSON.stringify(state)), win: WIN}; }
function saveLayout(){ localStorage.setItem(LAYOUT_KEY, JSON.stringify(readLayout())); }
</code></pre>
<p dir="auto">导出的 JSON 长这样，一眼就能看出每张卡片的格子坐标：</p>
<pre><code class="language-json">{
  "layout": {
    "card-cpu":    { "x": 0,  "y": 0,  "w": 2, "h": 5 },
    "card-engine": { "x": 0,  "y": 5,  "w": 6, "h": 5 },
    "card-logs":   { "x": 0,  "y": 24, "w": 12, "h": 6 }
  },
  "win": 300
}
</code></pre>
<hr />
<h2>部署</h2>
<pre><code class="language-bash"># 1. 放到机器上
scp -r dgx-monitor &lt;user&gt;@&lt;SPARK_IP&gt;:~/

# 2. 一键安装（注册 systemd 服务 + 自检）
cd dgx-monitor &amp;&amp; bash install.sh
</code></pre>
<p dir="auto"><code>install.sh</code> 做的事：把文件装到 <code>~/dgx/monitor/</code>、用 <code>sed</code> 替换 systemd 单元里的<br />
<code>User=</code> / <code>WorkingDirectory=</code> / <code>MONITOR_PORT=</code>、<code>daemon-reload</code>、<code>enable --now</code>，<br />
最后 curl 一下首页确认真的起来了。</p>
<p dir="auto">自检脚本检查这几项，任何一项不过会明确指出：</p>
<pre><code class="language-bash">$ bash verify.sh
  PASS  服务 spark-monitor active
  PASS  首页 200（48958 字节）
  PASS  API /api/stats 200
  PASS  新版前端已生效（找到栅格卡片）
  PASS  快照字段齐全（gpu/sensors/disk/network）
  PASS  /api/config 200
  PASS  /api/logs 200
  PASS  /api/healthz 200
  PASS  llm      :8888 /health ok
</code></pre>
<p dir="auto">也可以不用 systemd，直接前台跑：</p>
<pre><code class="language-bash">MONITOR_PORT=8890 python3 monitor.py
</code></pre>
<hr />
<h2>踩坑清单（实战）</h2>
<p dir="auto">这几条都是真踩过的，写出来省得别人再踩一遍。</p>
<p dir="auto"><strong>1. 一个没定义的函数，能让半张页面变成空白。</strong><br />
前端调了 <code>setBar()</code> 但从没定义过它，<code>ReferenceError</code> 直接把 <code>loadSnapshot()</code> 从中间打断，<br />
结果 GPU、传感器、磁盘、网络、进程、容器、引擎表<strong>全部没渲染</strong>，而页面看起来只是「没数据」。<br />
教训：前端的渲染要分段，别让一个异常连坐后面所有模块；排查时先看 console 报错。</p>
<p dir="auto"><strong>2. 同名函数声明会互相覆盖。</strong><br />
布局管理里有个 <code>function render()</code> 画栅格，数据渲染里也有 <code>function render(s)</code> 画面板——<br />
JS 里函数声明会被提升，<strong>后定义的那个赢</strong>，于是数据渲染被静默顶掉，页面全空但不报错。<br />
后来把布局那个改名 <code>paintLayout()</code> 才解决。</p>
<p dir="auto"><strong>3. 轮询打爆后端日志。</strong><br />
监控自己每秒去拉推理引擎的 <code>/metrics</code>，但没带 API Key，结果后端日志里刷了 1000 多条 401。<br />
加了 API Key 还不够，又加了<strong>失败退避</strong>：</p>
<pre><code class="language-python">if resp.status == 401:
    self._engine_blocked_until = now + 300.0    # 401 就安静 5 分钟
</code></pre>
<p dir="auto"><strong>4. 单位约定不一致，数值会离谱 1000 倍。</strong><br />
Prometheus 的 <code>time_to_first_token_seconds</code> 是秒，但另一套采集里换算成了毫秒，<br />
两边混用就会看到「TTFT 均值 105952.685 s」。<strong>贴指标前先确认单位</strong>，表头也要写清楚。</p>
<p dir="auto"><strong>5. Y 轴标签被裁掉。</strong><br />
<code>padL: 48</code> 放不下 <code>87.81 MB/s</code>，首字符被切掉变成 <code>7.81 MB/s</code>，看起来像数据错了。<br />
标签宽度要按「最长刻度 + 单位」算。</p>
<p dir="auto"><strong>6. <code>install.sh</code> 用 <code>enable --now</code> 不会重启已在跑的服务。</strong><br />
<code>enable --now</code> 对已运行的服务是 no-op，改完代码重新安装，线上跑的还是老版本。<br />
正确做法是 <code>systemctl --user enable</code> 之后显式 <code>restart</code>。</p>
<p dir="auto"><strong>7. systemd 单元里的 <code>User=</code> 是写死的。</strong><br />
别人拿去用就会因为用户名不同而起不来。安装脚本里用 <code>sed</code> 替换成当前用户。</p>
<hr />
<h2>文件清单</h2>
<pre><code>dgx-monitor/
├── monitor.py              后端（标准库，零依赖）      ~34 KB
├── index.html              前端（单文件，无 CDN）      ~49 KB
├── spark-monitor.service   systemd 单元模板
├── install.sh              一键安装
├── verify.sh               部署后自检
└── layout.test.js          布局引擎单元测试
</code></pre>
<p dir="auto"><code>layout.test.js</code> 是给布局逻辑写的单元测试（纯逻辑，Node 里跑，浏览器无关），<br />
校验默认版面不重叠、关键排位、碰撞推挤、就近安置、持久化往返：</p>
<pre><code class="language-bash">$ node layout.test.js
== 1. 默认版面（17 张卡片）自身不重叠 ==
  PASS  全部卡片互不重叠
  PASS  状态里有 17/17 张卡片
...
== 5. findSpot 返回真正空的位子 ==
  PASS  空位 {"x":0,"y":30} 无冲突
  PASS  带 prefer 取位不更远：{"x":8,"y":30}（距离 21 ≤ 扫描序 29）
全部通过 ✅
</code></pre>
<h3>怎么拿到源码</h3>
<p dir="auto">源码就上面这 7 个文件，没有构建步骤、没有依赖清单，<strong>全量 84 KB</strong>。几种给法：</p>
<ul>
<li><strong>贴到 gist / 仓库</strong>：只有 7 个文件，直接建个仓库传上去最省事</li>
<li><strong>打包成 tar.gz</strong>：<code>tar czf dgx-monitor.tar.gz dgx-monitor/</code>，随帖附上</li>
<li><strong>从帖子直接抄</strong>：本文已经把最关键的 6 段实现贴出来了，照着写也能复现个七七八八</li>
</ul>
<p dir="auto">如果你想给别人的是「换个样式 / 换数据源」的版本，改 <code>index.html</code> 里的 <code>CHARTS</code> / <code>DEFAULT_LAYOUT</code><br />
两个常量就够了，数据源在 <code>monitor.py</code> 的 <code>sample_once()</code> 里。</p>
<h3>源码里的占位符</h3>
<p dir="auto">发布版把和具体环境绑定的部分换成了占位符，拿到后改这几处即可：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>占位符</th>
<th>在哪</th>
<th>改成</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>&lt;ENGINE_PREFIX&gt;</code></td>
<td><code>monitor.py</code>（Prometheus 指标前缀，约 20 处）</td>
<td>你引擎的前缀，例如 <code>vllm:</code></td>
</tr>
<tr>
<td><code>&lt;model-name&gt;</code></td>
<td><code>monitor.py</code></td>
<td>模型名；留空则自动从 <code>/v1/models</code> 发现</td>
</tr>
<tr>
<td><code>&lt;user&gt;</code></td>
<td><code>spark-monitor.service</code></td>
<td>不用手改，<code>install.sh</code> 会自动替换成当前用户名</td>
</tr>
</tbody>
</table>
<hr />
<h2>已知限制</h2>
<ul>
<li><strong>面板不绑定任何推理后端</strong>。引擎相关的部分靠读 <code>/metrics</code>（推理服务 / vLLM 都行），<br />
没起容器时那几块是空的，其余面板照常工作。</li>
<li><strong>API Key 只存在于内存或容器环境变量里</strong>，面板本身不落盘、不外传。</li>
<li><strong>布局存在浏览器 localStorage</strong>，换浏览器要靠「布局…」里的 JSON 搬运。</li>
<li><strong>采样精度受限于 1 Hz</strong>：突发写入（几百 MB 的 dd）能抓到，持续小流量会被平均掉。</li>
<li><strong>只做了 Linux/aarch64</strong>，其它平台的采集函数（<code>/proc</code>、<code>hwmon</code>）需要改。</li>
</ul>
<hr />
<p dir="auto"><em>本文配图与源码均已做脱敏处理：模型名、容器镜像 tag、引擎名、用户名、主机名、IP、API Key<br />
均已替换为占位符或打码；面板本身也从不显示 API Key 的值。</em><br />
<a href="https://upload.lcz.me/uploads/31d048f8-0c47-4746-b3b0-fa9d42453357.zip" rel="nofollow ugc">dgx-monitor-post.zip</a></p>
]]></description><link>https://lcz.me/topic/2848</link><generator>RSS for Node</generator><lastBuildDate>Mon, 09 Nov 2026 05:21:07 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/2848.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 05 Nov 2026 01:38:16 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件 on Sun, 08 Nov 2026 07:52:26 GMT]]></title><description><![CDATA[<p dir="auto"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 版主审定：本帖设为<strong>优秀</strong>，作者 <strong>+3 积分</strong>奖励，继续加油！</p>
<blockquote>
<p dir="auto">奖励凭证：优秀 +3 分 · 编号 e2848-1148-1</p>
</blockquote>
]]></description><link>https://lcz.me/post/31895</link><guid isPermaLink="true">https://lcz.me/post/31895</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Sun, 08 Nov 2026 07:52:26 GMT</pubDate></item><item><title><![CDATA[Reply to 给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件 on Fri, 06 Nov 2026 08:52:20 GMT]]></title><description><![CDATA[<p dir="auto">当然也有大些的价格要贵一些。好的100多。</p>
]]></description><link>https://lcz.me/post/31567</link><guid isPermaLink="true">https://lcz.me/post/31567</guid><dc:creator><![CDATA[williamlouis]]></dc:creator><pubDate>Fri, 06 Nov 2026 08:52:20 GMT</pubDate></item><item><title><![CDATA[Reply to 给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件 on Fri, 06 Nov 2026 08:51:19 GMT]]></title><description><![CDATA[<p dir="auto">我有帖子。抓包 在 Linux重写下就可以。难度不大。<br />
拼夕夕 45元一个。</p>
]]></description><link>https://lcz.me/post/31566</link><guid isPermaLink="true">https://lcz.me/post/31566</guid><dc:creator><![CDATA[williamlouis]]></dc:creator><pubDate>Fri, 06 Nov 2026 08:51:19 GMT</pubDate></item><item><title><![CDATA[Reply to 给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件 on Fri, 06 Nov 2026 08:09:43 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/williamlouis" aria-label="Profile: williamlouis">@<bdi>williamlouis</bdi></a> 目前设备是DGX SPARK 不知道如何加这个副屏，而且还得学习一下副屏的调试。</p>
]]></description><link>https://lcz.me/post/31564</link><guid isPermaLink="true">https://lcz.me/post/31564</guid><dc:creator><![CDATA[juntucoo]]></dc:creator><pubDate>Fri, 06 Nov 2026 08:09:43 GMT</pubDate></item><item><title><![CDATA[Reply to 给 DGX Spark 写了个零依赖实时监控面板：1 个 Python 文件 + 1 个 HTML 文件 on Thu, 05 Nov 2026 07:24:46 GMT]]></title><description><![CDATA[<p dir="auto">我的建议是安装一个副屏。大模型主机不需远程访问主机。让它24小时工作即可。有没有故障扫一样副屏就知道了。副屏的功耗一般是3W左右。可以忽略不计。</p>
]]></description><link>https://lcz.me/post/31289</link><guid isPermaLink="true">https://lcz.me/post/31289</guid><dc:creator><![CDATA[williamlouis]]></dc:creator><pubDate>Thu, 05 Nov 2026 07:24:46 GMT</pubDate></item></channel></rss>