TensorFlow.js端侧推理实战:WebGPU加速与Web Worker多线程优化
1. 为什么要把模型搬到用户设备上跑1.1 从一次线上事故说起去年我负责的一个图像分类功能上线用户上传照片后需要调用后端接口做识别。上线第三天监控告警就炸了——接口平均响应时间从 200ms 飙到 3.2s服务器 CPU 打满。排查下来发现某个渠道的用户集中上传了一批高分辨率图片每张图都要走一遍完整的预处理加推理流程后端根本扛不住这个并发量。那次事故之后我开始认真考虑一个问题为什么一定要把推理放在服务器上用户的手机、电脑本身就有算力浏览器里就能跑模型为什么不让它自己算这就是端侧推理的核心思路。把训练好的模型直接下发到用户设备在浏览器里完成推理服务器只负责分发模型文件和收集结果。这样做有几个直接的好处延迟低不用走网络往返推理结果几乎瞬时返回。用户上传一张图本地 50ms 出结果体验完全不一样。隐私好数据不出设备用户照片、文本、语音都在本地处理天然符合隐私保护的要求。成本省推理算力从服务器转移到用户设备后端只需要托管静态模型文件带宽和计算成本大幅下降。离线可用模型缓存之后断网也能用这对一些弱网场景特别有价值。当然端侧推理不是银弹。模型大小受限于网络传输复杂模型在低端设备上跑不动不同浏览器的兼容性也是坑。但对于中小型模型、对延迟敏感的场景它确实是一个值得认真考虑的方案。1.2 TensorFlow.js 到底解决了什么问题TensorFlow.js 是 Google 推出的 JavaScript 机器学习库它让开发者可以直接在浏览器或 Node.js 环境里定义、训练和运行模型。对于端侧推理这个场景它主要解决三件事第一模型格式转换。你在 Python 里用 Keras 或 TensorFlow 训练好的模型可以通过转换工具变成 TensorFlow.js 能识别的格式直接在前端加载。不用重写模型结构不用手动导出权重。第二硬件加速。TensorFlow.js 支持多种后端WebGL、WebGPU、WASM、CPU。它会自动选择当前环境可用的最优后端把矩阵运算交给 GPU 或 SIMD 指令集处理。WebGPU 是近两年最值得关注的后端在支持它的浏览器里推理速度比 WebGL 快 2 到 5 倍。第三完整的推理 API。加载模型、预处理输入、执行推理、解析输出这一整套流程都有对应的 API。你不需要懂底层张量运算也能把模型跑起来。我自己的体会是TensorFlow.js 最大的价值在于降低了端侧机器学习的门槛。以前要在浏览器里跑模型得自己写 WebGL shader或者用 Emscripten 编译 C 代码。现在只要会 JavaScript就能把训练好的模型部署到用户设备上。1.3 这篇文章适合谁看如果你符合下面任意一条这篇文章应该对你有用做过前端或全栈开发想把手里的机器学习模型搬到浏览器里跑后端推理成本太高想探索端侧推理的可行性对 WebGPU、Web Worker 这些技术感兴趣想知道它们在机器学习场景下怎么用正在做课程设计或个人项目需要一个能落地的端侧推理方案我会从模型转换开始一步步讲到 WebGPU 加速和 Web Worker 多线程中间会穿插我自己踩过的坑和实测数据。代码以 TensorFlow.js 为主但思路对其他端侧推理框架同样适用。2. 模型转换与加载从 Python 到浏览器2.1 模型格式的选择与转换流程TensorFlow.js 支持两种模型格式Layers 模型和Graph 模型。Layers 模型是用 TensorFlow.js 的 API 在 JavaScript 里直接定义的适合从零开始训练的场景。Graph 模型是从 Python 转换过来的适合把已有模型部署到前端。绝大多数情况下我们用的是 Graph 模型。转换流程分三步第一步在 Python 里保存模型。如果你用的是 Keras直接model.save(my_model.h5)或者用 SavedModel 格式保存。SavedModel 是推荐格式兼容性更好。第二步安装转换工具。在 Python 环境里执行pip install tensorflowjs第三步执行转换命令。假设你有一个 SavedModel 目录转换命令如下tensorflowjs_converter \ --input_formattf_saved_model \ --output_formattfjs_graph_model \ --signature_nameserving_default \ --saved_model_tagsserve \ /path/to/saved_model \ /path/to/output_web_model转换完成后输出目录里会有一个model.json文件和若干.bin权重文件。model.json描述了模型结构.bin文件存储权重数据。前端加载时只需要指定model.json的路径。注意转换时一定要确认输入输出的张量名称和形状。我遇到过好几次模型转换成功但推理结果不对的情况最后发现是输入层的名称和 Python 里不一致。建议转换后用tfjs的model.inputs和model.outputs打印一下确认无误再往下走。2.2 模型加载的两种方式与性能对比TensorFlow.js 加载模型有两种方式tf.loadLayersModel()和tf.loadGraphModel()。前者用于 Layers 模型后者用于 Graph 模型。从 Python 转换过来的模型一律用loadGraphModel。import * as tf from tensorflow/tfjs; async function loadModel() { const model await tf.loadGraphModel(/models/my_model/model.json); return model; }加载过程中浏览器会先请求model.json解析出权重文件列表然后并行下载所有.bin文件。模型越大加载时间越长。我实测过一个 5MB 左右的模型在 4G 网络下加载时间大约 1.5 秒WiFi 下 0.6 秒左右。这里有一个优化点模型分片。转换工具默认会把权重切成多个.bin文件每个文件大约 4MB。这样做的目的是利用浏览器的并行下载能力同时避免单个文件过大导致加载失败。你可以通过--weight_shard_size_bytes参数调整分片大小但一般保持默认就好。另一个优化点是缓存。TensorFlow.js 底层用的是 fetch API浏览器会自动缓存模型文件。第二次加载时如果缓存未过期直接从本地读取速度会快很多。你也可以用 Service Worker 做更精细的缓存控制把模型文件缓存到 Cache Storage 里实现离线加载。2.3 输入预处理的常见坑模型加载只是第一步真正容易出问题的是输入预处理。Python 里训练模型时输入数据通常经过了归一化、缩放、通道转换等处理。前端推理时必须做完全相同的预处理否则结果会差得离谱。以图像分类为例Python 里常见的预处理是img img / 255.0 img np.expand_dims(img, axis0)前端对应的处理是function preprocess(imageElement) { return tf.tidy(() { let tensor tf.browser.fromPixels(imageElement); tensor tensor.toFloat().div(tf.scalar(255.0)); tensor tensor.expandDims(0); return tensor; }); }看起来简单但有几个细节容易忽略通道顺序Python 里常用 RGB但有些模型用的是 BGR。TensorFlow.js 的fromPixels默认返回 RGB如果模型需要 BGR得手动转换。尺寸匹配模型输入尺寸是固定的比如 224x224。如果用户上传的图片尺寸不对需要先 resize。tf.image.resizeBilinear可以做双线性插值但要注意 resize 的方式要和 Python 里一致。数据类型Python 里可能是 float32前端默认也是 float32但如果你用了toInt()之类的操作可能会变成 int32导致推理报错。我踩过最坑的一次是Python 里用了cv2.imread读图默认是 BGR 顺序但前端fromPixels返回 RGB结果模型把红色和蓝色通道搞反了分类结果完全错误。排查了半天才定位到这个问题。所以预处理代码一定要和训练代码逐行对照。3. WebGPU 后端把推理速度再提一个档次3.1 WebGPU 与 WebGL 的差异TensorFlow.js 默认会尝试使用 WebGL 后端。WebGL 已经存在很多年了兼容性好但它的设计初衷是图形渲染不是通用计算。用它跑机器学习模型有几个天然的限制不支持计算着色器WebGL 的 fragment shader 虽然可以用来做矩阵运算但写法很绕效率也不是最优。内存管理粗糙WebGL 的纹理和缓冲区管理不够灵活大模型容易遇到内存瓶颈。不支持浮点纹理的某些操作一些精度要求高的运算在 WebGL 上会出问题。WebGPU 是新一代的图形和计算 API专门为通用计算做了优化。它支持计算着色器内存管理更精细能更好地利用 GPU 的并行能力。在 TensorFlow.js 里WebGPU 后端的推理速度通常比 WebGL 快 2 到 5 倍具体取决于模型结构和设备 GPU 性能。启用 WebGPU 后端很简单import * as tf from tensorflow/tfjs; import tensorflow/tfjs-backend-webgpu; async function init() { await tf.setBackend(webgpu); await tf.ready(); console.log(当前后端:, tf.getBackend()); }如果浏览器不支持 WebGPUsetBackend会失败你需要回退到 WebGLtry { await tf.setBackend(webgpu); } catch (e) { await tf.setBackend(webgl); } await tf.ready();3.2 实测数据与性能对比我在一台搭载 M1 芯片的 MacBook Air 上做了一个简单的对比测试模型是一个轻量级的图像分类网络输入 224x224x3输出 1000 类。测试结果如下后端首次推理耗时平均推理耗时100次内存占用CPU320ms280ms120MBWebGL45ms38ms210MBWebGPU18ms12ms180MB从数据可以看出WebGPU 的推理速度比 WebGL 快了大约 3 倍比 CPU 快了 20 多倍。内存占用方面WebGPU 比 WebGL 略低这是因为 WebGPU 的内存管理更高效。不过WebGPU 的首次推理耗时并不总是最低的。因为 WebGPU 需要编译着色器、初始化管线第一次推理会有额外的开销。如果你的场景是单次推理WebGL 可能反而更快。但如果是连续推理WebGPU 的优势会迅速体现出来。还有一个细节WebGPU 在移动端的支持还在完善中。截至我写这篇文章时Android 上的 Chrome 已经支持 WebGPU但 iOS 上的 Safari 还需要用户手动开启实验性功能。如果你的用户主要在移动端建议做好后端降级方案。3.3 后端选择的决策逻辑到底该用哪个后端我的建议是按下面的逻辑来决策先检测 WebGPU 是否可用。如果可用优先用 WebGPU。WebGPU 不可用时检测 WebGL。绝大多数现代浏览器都支持 WebGL这是最稳妥的 fallback。WebGL 也不可用时用 WASM。WASM 后端比纯 CPU 快但比 GPU 慢。适合对兼容性要求极高的场景。最后才用 CPU。CPU 后端只适合极小模型或调试场景。代码实现上可以写一个自动选择后端的函数async function selectBestBackend() { const backends [webgpu, webgl, wasm, cpu]; for (const backend of backends) { try { await tf.setBackend(backend); await tf.ready(); console.log(成功启用后端: ${backend}); return backend; } catch (e) { console.warn(后端 ${backend} 不可用尝试下一个); } } throw new Error(没有可用的后端); }这个函数会依次尝试每个后端直到找到一个可用的。实际项目中我还会加一个性能探测用一个小张量做一次矩阵乘法测量耗时如果某个后端耗时超过阈值就继续尝试下一个。4. Web Worker 多线程让推理不阻塞界面4.1 为什么需要 Web WorkerJavaScript 是单线程的。如果你在主线程里跑模型推理哪怕只花 50ms这 50ms 内页面是无法响应用户操作的。按钮点不动滚动卡顿动画掉帧。对于推理耗时较长的模型这种卡顿会非常明显。Web Worker 的作用是把计算任务放到后台线程执行主线程只负责界面渲染和用户交互。推理在 Worker 里跑主线程完全不受影响用户体验会好很多。TensorFlow.js 在 Web Worker 里的使用方式和主线程基本一致但有几个限制不能直接访问 DOMWorker 里没有document、window这些对象。图像数据需要通过ImageBitmap或ArrayBuffer传递。通信有开销主线程和 Worker 之间通过postMessage通信数据需要序列化和反序列化。大张量传输会有性能损耗。模型加载独立Worker 里需要单独加载模型不能共享主线程的模型实例。4.2 Worker 的创建与通信机制创建一个推理 Worker 的步骤如下第一步写 Worker 脚本。// inference.worker.js import * as tf from tensorflow/tfjs; import tensorflow/tfjs-backend-webgpu; let model null; async function loadModel() { await tf.setBackend(webgpu); await tf.ready(); model await tf.loadGraphModel(/models/my_model/model.json); self.postMessage({ type: model_loaded }); } async function runInference(imageData) { const tensor tf.tidy(() { let t tf.browser.fromPixels(imageData); t t.toFloat().div(tf.scalar(255.0)); t t.expandDims(0); return t; }); const output model.predict(tensor); const result await output.data(); tensor.dispose(); output.dispose(); return Array.from(result); } self.onmessage async (event) { const { type, payload } event.data; if (type load) { await loadModel(); } else if (type infer) { const result await runInference(payload); self.postMessage({ type: result, payload: result }); } };第二步在主线程里创建 Worker 并通信。const worker new Worker(inference.worker.js, { type: module }); worker.postMessage({ type: load }); worker.onmessage (event) { const { type, payload } event.data; if (type model_loaded) { console.log(模型加载完成); } else if (type result) { console.log(推理结果:, payload); } }; // 用户上传图片后 async function handleImageUpload(file) { const bitmap await createImageBitmap(file); worker.postMessage({ type: infer, payload: bitmap }, [bitmap]); }注意postMessage的第二个参数[bitmap]表示把bitmap的所有权转移给 Worker避免数据拷贝。这是Transferable Objects的用法对ImageBitmap、ArrayBuffer这类大数据特别有用。4.3 多 Worker 并行推理的实践单个 Worker 已经能解决界面卡顿的问题但如果你的场景需要同时处理多张图片单个 Worker 会成为瓶颈。这时候可以创建多个 Worker组成一个 Worker 池。class WorkerPool { constructor(size) { this.workers []; this.idleWorkers []; for (let i 0; i size; i) { const worker new Worker(inference.worker.js, { type: module }); worker.postMessage({ type: load }); this.workers.push(worker); this.idleWorkers.push(worker); } } async runInference(bitmap) { const worker await this.acquireWorker(); return new Promise((resolve) { worker.onmessage (event) { if (event.data.type result) { this.releaseWorker(worker); resolve(event.data.payload); } }; worker.postMessage({ type: infer, payload: bitmap }, [bitmap]); }); } acquireWorker() { if (this.idleWorkers.length 0) { return Promise.resolve(this.idleWorkers.pop()); } return new Promise((resolve) { const check () { if (this.idleWorkers.length 0) { resolve(this.idleWorkers.pop()); } else { setTimeout(check, 10); } }; check(); }); } releaseWorker(worker) { this.idleWorkers.push(worker); } }Worker 池的大小需要根据设备的核心数来定。navigator.hardwareConcurrency可以获取逻辑核心数一般取Math.min(4, navigator.hardwareConcurrency)比较合适。太多 Worker 会导致 GPU 资源竞争反而降低整体吞吐量。实测经验在 M1 MacBook Air 上2 个 Worker 的吞吐量比 1 个 Worker 提升了约 80%4 个 Worker 只比 2 个提升了 20%。所以不是越多越好2 到 4 个是比较合理的范围。5. 常见问题与排查技巧实录5.1 模型加载失败与跨域问题模型加载失败是最常见的问题之一。浏览器控制台通常会报Failed to fetch或CORS policy错误。原因通常是模型文件没有正确配置跨域头。解决方案分两种情况开发环境如果你用 webpack dev server 或 vite可以在配置里加代理把模型请求转发到后端。生产环境模型文件所在的服务器需要设置Access-Control-Allow-Origin头。如果模型放在 CDN 上CDN 的配置里也要加上这个头。还有一个容易忽略的点model.json里引用的权重文件路径是相对路径。如果你把模型放在子目录里确保model.json和.bin文件的相对位置正确。我遇到过把model.json单独拿出来放到另一个目录结果权重文件找不到的情况。5.2 推理结果与 Python 不一致的排查思路推理结果不一致通常有以下几个原因问题现象可能原因排查方法结果完全错误输入预处理不一致对比 Python 和前端的预处理代码逐行检查结果略有偏差数值精度差异检查是否用了 float16 或 int8 量化部分样本错误通道顺序或尺寸问题打印输入张量的形状和数值范围结果随机模型未正确加载检查模型加载是否完成权重是否完整我的排查流程是先在 Python 里跑一张测试图片保存输入张量和输出结果。然后在前端用同一张图片打印输入张量和输出结果逐层对比。如果输入张量就不一致问题在预处理如果输入一致但输出不一致问题在模型转换或推理过程。5.3 内存泄漏与性能下降TensorFlow.js 的张量是手动管理内存的。如果你创建了张量但没有释放内存会持续增长最终导致页面崩溃。// 错误写法张量未释放 function predict(image) { const tensor tf.browser.fromPixels(image); const output model.predict(tensor); return output.dataSync(); } // 正确写法用 tf.tidy 自动释放 function predict(image) { return tf.tidy(() { const tensor tf.browser.fromPixels(image); const output model.predict(tensor); return output.dataSync(); }); }tf.tidy会自动释放函数内部创建的所有张量除了返回值。如果返回值也是张量需要手动释放。另一个性能问题是频繁的后端切换。每次setBackend都会重新初始化后端开销很大。应该在应用启动时确定后端之后不再切换。5.4 移动端兼容性避坑指南移动端的坑比桌面端多得多。以下是我踩过的一些iOS Safari 的 WebGL 内存限制iOS 对 WebGL 的内存限制比较严格大模型容易导致页面崩溃。解决方案是减小模型体积或者用 WASM 后端。Android 碎片化不同厂商的 GPU 驱动质量参差不齐某些设备上 WebGL 推理会出错。建议加一个降级逻辑检测到推理异常时自动切换到 WASM。低端设备性能低端手机的 GPU 性能有限WebGPU 可能还不如 WASM。可以在启动时做一个简单的性能探测根据结果选择后端。async function detectPerformance() { const testTensor tf.randomNormal([256, 256]); const start performance.now(); for (let i 0; i 10; i) { tf.matMul(testTensor, testTensor).dispose(); } const elapsed performance.now() - start; testTensor.dispose(); return elapsed; }如果探测耗时超过 500ms说明当前后端性能不佳可以考虑降级。6. 端侧推理的边界与我的实践体会端侧推理不是万能的。模型大小、设备性能、浏览器兼容性这些都是实实在在的限制。我自己的经验是参数量在 10M 以下的模型端侧推理基本没问题10M 到 50M 的模型需要做量化压缩并且要针对低端设备做降级超过 50M 的模型现阶段还是老老实实放服务器上跑。量化是一个很实用的压缩手段。TensorFlow.js 支持 float16 和 int8 量化模型体积可以缩小到原来的 1/2 到 1/4推理速度也有提升。代价是精度会有轻微下降具体能不能接受得看你的业务场景。还有一个容易被忽略的点模型版本管理。端侧模型一旦下发到用户设备更新就是个麻烦事。用户可能缓存了旧版本模型你的新模型发布了但用户还在用旧的。解决方案是在model.json的 URL 里加版本号比如/models/v2/model.json每次更新模型时改版本号强制浏览器重新加载。最后说一个我最近在尝试的方向模型分片加载。把一个大模型拆成多个小模型按需加载。比如一个多任务模型用户只用到了其中一部分功能就只加载对应的子模型。这样可以进一步减少首次加载时间提升用户体验。这个方案还在验证阶段等有成熟结论了再单独写一篇分享。

相关新闻

OpenClaw(龙虾)AI 智能体安装教程:从 Node.js 环境到 TaoToken 统一 Key 接入

OpenClaw(龙虾)AI 智能体安装教程:从 Node.js 环境到 TaoToken 统一 Key 接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 22:02:37 阅读更多 →
面试题(上)| 主流网安厂商面试真题全收录:Web 漏洞 / 渗透实战 / 护网溯源全覆盖

面试题(上)| 主流网安厂商面试真题全收录:Web 漏洞 / 渗透实战 / 护网溯源全覆盖

目录 一、天融信 天融信-1 天融信-2 二、漏洞盒子 青藤云: 三、长亭 长亭-1 长亭-2 长亭-红队 四、安恒 1、基础漏洞 2、溯源和应急响应 五、未知厂商 六、青藤 七、奇安信 奇安信-1 奇安信-红队 八、360 360-1 360-2 360-3 九、极盾科技 十、国誉网安…

2026/10/4 19:52:45 阅读更多 →
DeepSeek    LeetCode 148. 排序链表 Python3实现

DeepSeek LeetCode 148. 排序链表 Python3实现

LeetCode 148. 排序链表 解法一:自顶向下归并排序(递归) 思路:用快慢指针找中点,将链表拆成两半,递归排序后合并。 # Definition for singly-linked list. # class ListNode: # def __init__(self, val…

2026/10/4 19:52:45 阅读更多 →

最新新闻

配置光猫的上网与IPTV通过LAN1口单线复用

配置光猫的上网与IPTV通过LAN1口单线复用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 22:02:09 阅读更多 →
STM32F745VG驱动MR25H40CDF MRAM:SPI配置与工业存储实战

STM32F745VG驱动MR25H40CDF MRAM:SPI配置与工业存储实战

1. 为什么工业现场还在用 MRAM,而不是继续堆 Flash如果你拆过工业网关、PLC 扩展模块或者电力监测终端,大概率会在板子上看到一颗 8 脚的小芯片,旁边紧挨着一颗 STM32 或者类似的 MCU。过去十年,这个位置基本被 SPI Flash 和 EEPR…

2026/10/5 22:02:09 阅读更多 →
STM32L496ZG 与 MR25H40CDF MRAM 高速存储方案实战

STM32L496ZG 与 MR25H40CDF MRAM 高速存储方案实战

1. 为什么偏偏是 MRAM 加 STM32L496ZG 这个组合搞嵌入式存储选型这些年,我经手的方案从 24C02 这种 I2C EEPROM 到 W25Q 系列 SPI Flash,再到铁电存储器 FRAM,几乎把能踩的坑都踩了一遍。直到项目里开始频繁出现“高频写入、掉电不能丢、还要…

2026/10/5 22:01:08 阅读更多 →
工业嵌入式存储方案:SPI MRAM与8位MCU的实战配置与掉电保护

工业嵌入式存储方案:SPI MRAM与8位MCU的实战配置与掉电保护

嵌入式存储方案里,SPI接口的MRAM和8位MCU的组合,算是工业场景里一个相当务实的搭配。MR25H40CDF这颗4Mb的磁性随机存储器,配合PIC18F96J94这颗带自编程能力的8位微控制器,能解决不少传统方案里掉电丢数据、写入寿命不够、写入速度…

2026/10/5 22:01:08 阅读更多 →
STM32L496ZG驱动MR25H40CDF:MRAM嵌入式存储实战

STM32L496ZG驱动MR25H40CDF:MRAM嵌入式存储实战

1. 为什么 MRAM 在嵌入式存储里越来越受关注搞过工业设备或者数据采集终端的朋友应该都有体会,选存储芯片这件事,看着简单,实际上坑特别多。EEPROM 写入慢、寿命有限;NOR Flash 擦除块大、写入前必须擦除;FRAM 速度快但…

2026/10/5 22:00:06 阅读更多 →
软考-系统架构师论文(一)

软考-系统架构师论文(一)

一、论文考试规则考试规则:120 分钟,4 道题目选 1 道写;总分 75,≥45 分及格;全文一般要求2000 字左右 摘要 300 字,机考(打字)二、核心考察目标不是作文,考架构落地经验…

2026/10/5 21:58:05 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →