包含关键字 typecho 的文章

上文: https://www.v2ex.com/t/1186774

一、24 日周六上午我下班之前把所有交接资料整理好,并且打印了一张交接确认表压在了工位键盘下面,然后全程录像,打完最后一个卡离开了公司。

二、25 日周日我通过 EMS 邮寄《被迫解除劳动合同关系通知书》给公司,同时邮箱把交接资料通过邮箱发到了公司管理者的邮箱。以及钉钉微信也发了《被迫解除劳动合同关系通知书》 pdf 版本,同时要求公司 3 日之内结清我 12 月,1 月的工资。公司的管理者(魏总)说他不是真正的老板,他也被欠工资了,他会把我发的消息全部转达给两个股东,同时发来了一张他拉了两个股东的群的截图。

三、我搞到了公司两个股东的电话,发去短信,要求两个股东在 3 日内结清我的工资,否则我后续将去仲裁,可能产生连带责任。
周二,其中一位占股 60%的股东 A 打来电话,开头就问我是不是**(我家乡)的人,说他祖籍也是那里的,然后就开始用方言和我聊,我就说我入职时间短,工资数额不大,如果能把工资给我结清,我可以不去仲裁。他说他去和公司商量一下。同日晚上,股东 A 打来电话,就说 29 日会给我结 12 月份的工资,2 月底再给我结 1 月的工资,但是要我 29 号去线下走手续(我猜测他可能要那个魏总搞一些不平等的协议让我签?然后才给我钱?)。
我马上说不行,我说你要给我结清,我已经解除和公司的劳动关系了,他马上暴跳如雷,说他已经帮我去跟公司沟通了,公司有公司的流程,不行就让我去仲裁,让我一年拿不到钱。我说你确定你说的话属实,我可以暂停我的仲裁流程,他说他确定。然后就开始给我打感情牌,说都是老乡,以后可能还是朋友,什么什么诸如之类的,意思就是让我接受他的方案。

四、目前公司的人基本都在走离职(小公司 10 人左右),而且还有还几个已经离职了被迫签了 2.15 日再结清工资的协议。据也在离职的财务说(公司目前账上连 1W 块钱都没有,而且公司最近在申请变换名字以及股权变更)(这个是大前提)。现在那几个在走离职的员工,都是被拖欠了 11 月份半个月+12 月+1 月的工资。社保听说周一给他们交上了,但是我的依旧没有交。那几个员工最近都在问我仲裁流程走到哪了,我没有透漏和我股东联系上的这件事,就说还在准备。他们都是在走正常的自主离职流程。

目前仲裁我只提交了预申请,劳动监察大队的人今天加我微信,我把那个魏总的联系方式给了他,按他的说法来说他能帮我要到的概率不大,因为之前这个公司也有人找过他。那个魏总永远都只有一套说辞,他不是真正的老板,他也是个打工的。实际上公司都是他在管理。
现在我就在等 29 日看看到底会过去签什么,如果有一些奇怪的协议,我可能就不签了,直接走仲裁了。最近几天搞这个搞得心力交瘁,有没有有经验的 v 友有更好的建议?
ps:那个魏总把我挂群里了,这个图还是财务转发给我的哈哈

基于YOLOv8的工业织物瑕疵检测识别|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!

源码包含:完整YOLOv8训练代码+数据集(带标注)+权重文件+直接可允许检测的yolo检测程序+直接部署教程/训练教程

基本功能演示

https://www.bilibili.com/video/BV1G1r6BuEga/

源码在哔哩哔哩视频简介处。

项目摘要

在纺织制造与高端材料加工过程中,织物表面瑕疵直接影响产品质量等级与出厂合格率。尤其对于 C1 类高精细织物(如粘胶纤维、丝绸等),其表面纹理极弱、结构特征不明显,传统基于规则或人工经验的检测方法在复杂光照与高速产线条件下,往往难以实现稳定、精准的瑕疵识别。

本项目基于 YOLOv8 目标检测模型,构建了一套 工业织物瑕疵智能检测与识别系统,面向弱纹理背景下的织物表面缺陷场景,实现对 洞(Hole)异物(Foreign Object)油斑(Oil Stain)织线错误(Weaving Defect) 四类典型工业瑕疵的自动检测与定位。系统集成 PyQt5 图形化界面,支持图片、文件夹、视频及摄像头等多种输入方式,便于在实验环境与实际产线场景中使用。

项目提供 完整可运行源码、标准化标注数据集、训练权重文件以及详细的训练与部署说明,实现从模型训练到检测应用的完整闭环,适用于工业视觉检测研究、质量控制系统原型开发及相关课程与毕业设计。

前言

随着制造业向高端化与智能化方向持续升级,基于计算机视觉的自动缺陷检测已成为工业质量控制中的核心技术之一。相比具有明显纹理与结构特征的金属或印刷表面,高精细织物表面往往呈现弱纹理、低对比度、特征细微等特点,对检测算法的特征提取能力与鲁棒性提出了更高要求。

在实际生产中,洞、油斑或织线错误等缺陷尺寸较小、形态多变,且在不同光照条件下视觉特征差异明显,传统机器视觉方法依赖人工设定阈值与规则,泛化能力有限。而深度学习目标检测模型,尤其是以 YOLO 系列为代表的端到端检测框架,在复杂背景与小目标检测任务中展现出显著优势。

YOLOv8 在网络结构设计、特征融合与训练策略方面进行了多项优化,在保证检测精度的同时兼顾推理速度与工程可部署性,非常适合工业产线实时或准实时检测需求。本项目结合真实工业织物瑕疵数据,对 YOLOv8 在弱纹理缺陷检测场景下的应用进行系统化实践,为工业视觉检测提供可复现的工程参考。

一、软件核心功能介绍及效果演示

1. 多类别工业织物瑕疵检测

系统基于 YOLOv8 目标检测模型,实现对工业织物表面多种缺陷的自动识别与定位,支持以下四类瑕疵:

  • Hole(洞)
  • Foreign Object(异物)
  • Oil Stain(油斑)
  • Weaving Defect(织线错误)

检测结果以边界框形式叠加显示在原始图像或视频画面上,并同步标注瑕疵类别与置信度,便于质量检测人员快速判断缺陷类型与位置。


2. 多输入源缺陷检测模式

系统支持多种输入方式,满足不同应用阶段的检测需求:

  • 单张图片检测:用于样本分析与算法验证
  • 图片文件夹批量检测:适用于离线质量抽检
  • 视频文件检测:模拟连续产线检测过程
  • 实时摄像头检测:满足工业现场在线检测需求

所有检测模式均可通过图形界面一键切换,无需修改代码。


3. PyQt5 工业视觉检测界面

项目基于 PyQt5 构建桌面端可视化界面,主要功能包括:

  • 模型权重加载与管理
  • 检测模式与输入源选择
  • 实时检测画面显示
  • 缺陷识别结果与运行状态提示

该界面降低了模型使用门槛,使算法工程人员与现场技术人员均可快速完成检测任务。


4. 完整训练流程与工程复现能力

项目提供完整的 YOLOv8 训练与推理流程,包含:

  • 标准 YOLO 格式的工业织物瑕疵数据集
  • 类别配置文件与训练参数示例
  • 模型训练、验证与测试脚本
  • 训练完成的权重文件与推理程序

用户可基于现有数据进行二次训练或扩展新瑕疵类别,具备良好的工程扩展性与研究价值。


5. 实际检测效果说明

在弱纹理、高相似度背景的工业织物图像中,系统能够稳定检测不同类型的细微瑕疵,对小尺寸缺陷与低对比度异常具有较好的识别能力,适用于织物质量检测、生产过程监控及缺陷数据统计分析等工业应用场景。

二、软件效果演示

为了直观展示本系统基于 YOLOv8 模型的检测能力,我们设计了多种操作场景,涵盖静态图片、批量图片、视频以及实时摄像头流的检测演示。

(1)单图片检测演示

用户点击“选择图片”,即可加载本地图像并执行检测:

image-20260113004758526


(2)多文件夹图片检测演示

用户可选择包含多张图像的文件夹,系统会批量检测并生成结果图。

image-20260113004907933


(3)视频检测演示

支持上传视频文件,系统会逐帧处理并生成目标检测结果,可选保存输出视频:

image-20260113004922807


(4)摄像头检测演示

实时检测是系统中的核心应用之一,系统可直接调用摄像头进行检测。由于原理和视频检测相同,就不重复演示了。

image-20260113004937406


(5)保存图片与视频检测结果

用户可通过按钮勾选是否保存检测结果,所有检测图像自动加框标注并保存至指定文件夹,支持后续数据分析与复审。

image-20260113004954026

三、模型的训练、评估与推理

YOLOv8是Ultralytics公司发布的新一代目标检测模型,采用更轻量的架构、更先进的损失函数(如CIoU、TaskAlignedAssigner)与Anchor-Free策略,在COCO等数据集上表现优异。
其核心优势如下:

  • 高速推理,适合实时检测任务
  • 支持Anchor-Free检测
  • 支持可扩展的Backbone和Neck结构
  • 原生支持ONNX导出与部署

3.1 YOLOv8的基本原理

YOLOv8 是 Ultralytics 发布的新一代实时目标检测模型,具备如下优势:

  • 速度快:推理速度提升明显;
  • 准确率高:支持 Anchor-Free 架构;
  • 支持分类/检测/分割/姿态多任务
  • 本项目使用 YOLOv8 的 Detection 分支,训练时每类表情均标注为独立目标。

YOLOv8 由Ultralytics 于 2023 年 1 月 10 日发布,在准确性和速度方面具有尖端性能。在以往YOLO 版本的基础上,YOLOv8 引入了新的功能和优化,使其成为广泛应用中各种物体检测任务的理想选择。

image-20250526165954475

YOLOv8原理图如下:

image-20250526170118103

3.2 数据集准备与训练

采用 YOLO 格式的数据集结构如下:

dataset/
├── images/
│   ├── train/
│   └── val/
├── labels/
│   ├── train/
│   └── val/

每张图像有对应的 .txt 文件,内容格式为:

4 0.5096721233576642 0.352838390077821 0.3947600423357664 0.31825755058365757

分类包括(可自定义):

、

image-20260113005044200

3.3. 训练结果评估

训练完成后,将在 runs/detect/train 目录生成结果文件,包括:

  • results.png:损失曲线和 mAP 曲线;
  • weights/best.pt:最佳模型权重;
  • confusion_matrix.png:混淆矩阵分析图。
若 mAP@0.5 达到 90% 以上,即可用于部署。

在深度学习领域,我们通常通过观察损失函数下降的曲线来评估模型的训练状态。YOLOv8训练过程中,主要包含三种损失:定位损失(box_loss)、分类损失(cls_loss)和动态特征损失(dfl_loss)。训练完成后,相关的训练记录和结果文件会保存在runs/目录下,具体内容如下:

image-20260113005059867

3.4检测结果识别

使用 PyTorch 推理接口加载模型:

import cv2
from ultralytics import YOLO
import torch
from torch.serialization import safe_globals
from ultralytics.nn.tasks import DetectionModel

# 加入可信模型结构
safe_globals().add(DetectionModel)

# 加载模型并推理
model = YOLO('runs/detect/train/weights/best.pt')
results = model('test.jpg', save=True, conf=0.25)

# 获取保存后的图像路径
# 默认保存到 runs/detect/predict/ 目录
save_path = results[0].save_dir / results[0].path.name

# 使用 OpenCV 加载并显示图像
img = cv2.imread(str(save_path))
cv2.imshow('Detection Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

预测结果包含类别、置信度、边框坐标等信息。

image-20260113005141716

四.YOLOV8+YOLOUI完整源码打包

本文涉及到的完整全部程序文件:包括python源码、数据集、训练代码、UI文件、测试图片视频等(见下图),获取方式见【4.2 完整源码下载】:

4.1 项目开箱即用

作者已将整个工程打包。包含已训练完成的权重,读者可不用自行训练直接运行检测。

运行项目只需输入下面命令。

python main.py

读者也可自行配置训练集,或使用打包好的数据集直接训练。

自行训练项目只需输入下面命令。

yolo detect train data=datasets/expression/loopy.yaml model=yolov8n.yaml pretrained=yolov8n.pt epochs=100 batch=16 lr0=0.001

4.2 完整源码

至项目实录视频下方获取:https://www.bilibili.com/video/BV1G1r6BuEga/

image-20250801135823301

包含:

📦完整项目源码

📦 预训练模型权重

🗂️ 数据集地址(含标注脚本)

总结

本文围绕 基于 YOLOv8 的工业织物瑕疵检测识别系统,从数据集特点、模型选型到系统工程实现进行了系统性阐述。项目针对 C1 类高精细、弱纹理织物表面这一工业视觉中的典型难点场景,实现了对 洞、异物、油斑及织线错误 等多类微小缺陷的自动检测与精准定位,有效提升了织物质量检测的稳定性与一致性。

在工程实践层面,项目不仅验证了 YOLOv8 在弱纹理缺陷检测任务中的适用性,还通过 PyQt5 图形化界面将算法能力转化为可直接使用的检测工具,支持多输入源与完整训练流程,具备良好的可复现性与可扩展性。整体方案可作为工业视觉检测、制造业质量控制系统原型以及相关教学与科研实验的参考实现,为推动传统织物检测向智能化、自动化方向升级提供了可落地的技术路径。

作为一个管理着十几个域名的独立开发者,我深知域名过期与 SSL 证书过期带来的麻烦。

为此开发了这个一站式监控平台 ( https://domainwatcher.org) ,核心功能:

  • 域名到期监控:自研 WHOIS/RDAP 解析引擎,支持数百个后缀。
  • SSL 证书监控:支持 SSL 证书到期与有效性监控。
  • 多种通知渠道:支持在 WHOIS 、SSL 即将到期与发生变更时发送提醒邮件,后续将支持各类通知服务与自定义 Webhook 。
  • 日历深度集成:提供 iCalendar 订阅,支持各平台、各类日历软件订阅。

欢迎各位老司机试用,评论区留下的建议我都会看,持续更新迭代,后续也可以提供私有化部署服务。

送码福利:准备了 20 个兑换码,可直接激活 1 年的日历订阅服务。

前言

作为一名深耕鸿蒙原生生态的独立开发者,我开发的 《会议随记 Pro》 刚刚完成了 v1.0 到 v1.1 的迭代。

如果说 v1.0 是为了验证极致单机录音与项目管理这一核心 MVP(最小可行性产品),那么 v1.1 则是为了让这个第二大脑具备走向全球的底气。

在 v1.1 版本中,我们不仅重构了 UI 布局,更引入了完整的多语言支持(简体中文/English)。这看似只是简单翻译,实则是对应用底层架构的一次重要升维。

今天,我想跳出单纯的功能介绍,以开发者的视角,和大家聊聊这次更新背后的技术思考,特别是在纯血鸿蒙 HarmonyOS NEXT 中,如何优雅地实现原生国际化?

一、v1.1 版本更新概览

在进入硬核技术环节之前,先快速同步一下本次 v1.1 版本的核心变化。

1. 国际化支持(Multi-language Support)

这是本次更新的重头戏。应用不再局限于中文环境,新增了完整的英文(English) 界面支持。

  • 无感切换:应用会自动读取系统的语言设置,适配中文或英文。
  • 全域覆盖:从首页的 Dashboard,到深层的会议设置、隐私协议,甚至是自动生成的演示数据,全部实现了本地化。

2. 视觉与布局重构(Compact UI)

针对商务人士“信息密度”的高要求,我们优化了会议详情页的布局:

  • 紧凑型卡片:将原先松散的信息聚合为卡片,减少滑动距离。
  • 信息层级优化:强化了“时间轴笔记”与“待办事项”的视觉权重,让复盘更高效。

3. 体验微调

  • 修复了部分场景下长文本截断的问题。
  • 优化了 Emoji 选择器的交互手感。

二、鸿蒙原生国际化(i18n)深度解析

对于许多从 Web 前端或 Android 转战鸿蒙的开发者来说,国际化(Internationalization,简称 i18n)往往被误解为“简单的字符串替换”。

但在 HarmonyOS NEXT 的声明式开发体系(ArkUI)中,国际化是一套完整的资源管理机制(Resource Management)。它不仅仅是翻译文字,还包括了对不同国家/地区的度量衡、日期格式、甚至阅读习惯(LTR/RTL)的适配。

1. 核心理念:资源限定词(Qualifiers)与目录优先级

鸿蒙操作系统的资源加载机制非常智能。它不像传统 Web 开发那样需要你写一堆 if (lang === 'en') 的判断逻辑。鸿蒙采用的是“基于目录结构的资源匹配策略”

你的应用是一个巨大的仓库,仓库里有很多个房间(目录)。

  • 有一个房间叫 base/element,这里放着“默认物资”。
  • 有一个房间叫 en_US/element,这里放着“给美国英语用户准备的物资”。
  • 有一个房间叫 zh_CN/element,这里放着“给中国大陆用户准备的物资”。

当用户打开 App 时,系统会先看用户的手机设置。如果用户设置的是英文,系统就会优先去 en_US 房间找;如果找不到,才会去 base 房间找兜底数据。

这种机制最大的好处是:代码逻辑与资源数据彻底解耦。你的 ArkTS 代码中永远只需要引用一个 ID,具体显示什么内容,完全由系统在运行时动态决定。

2. 工程结构实战

在《会议随记 Pro》中,我们严格遵循了鸿蒙的官方推荐结构。

resources 目录下,文件结构如下:

resources
├── base
│   ├── element
│   │   ├── string.json      // 默认字符串(通常是兜底语言,如中文)
│   │   └── color.json       // 颜色资源
│   └── media                // 通用图片
├── en_US  (限定词目录:英文-美国)
│   └── element
│       └── string.json      // 英文翻译
└── zh_CN  (限定词目录:中文-中国)
    └── element
        └── string.json      // 中文特有优化

关键点解析:

  • string.json:这是存储键值对的核心文件。所有的文案都必须提取到这里,严禁在代码中写死字符串(Hardcode)。
  • 匹配规则:当系统语言为 en-US 时,优先级为 en_US > en (如果存在) > base

三、从 0 到 1 实现多语言的代码实战

接下来,我将通过《会议随记 Pro》中的真实代码片段,演示如何在 ArkTS 中实现这一机制。

场景一:基础静态文本的替换

这是最常见的场景,比如标题、按钮文字。

步骤 1:定义资源 (JSON)

首先,我们在 base/element/string.json 中定义 Key:

{
  "string": [
    {
      "name": "emoji_selector_title",
      "value": "会议标记"
    },
    {
      "name": "btn_confirm",
      "value": "确认"
    }
  ]
}

然后,在 en_US/element/string.json 中定义相同的 Key,但 Value 不同:

{
  "string": [
    {
      "name": "emoji_selector_title",
      "value": "Meeting Markers"
    },
    {
      "name": "btn_confirm",
      "value": "Confirm"
    }
  ]
}

步骤 2:在 UI 中使用 ($r 语法)

在 ArkTS 组件中,我们不再写字符串字面量,而是使用 $r() 函数。

$r 是 Resource 的缩写,它的参数格式是 'app.type.name'

// 修改前 (Hardcode - 反面教材)
Text('会议标记')
  .fontSize(14)

// 修改后 (i18n - 最佳实践)
Text($r('app.string.emoji_selector_title'))
  .fontSize(14)

技术原理

$r 返回的并不是一个 string 类型,而是一个 Resource 对象。ArkUI 的组件(如 Text, Button)内部已经做好了适配,当它们接收到 Resource 对象时,会在渲染的一瞬间,去 Resource Manager 查找当前语言对应的文本。这意味着,如果用户在运行过程中切了系统语言,应用不需要重启,界面会自动刷新!


场景二:带参数的动态文本格式化

在会议列表中,我们经常需要显示“已选 3 项”或者“第 5 个文件”。这种包含数字或变量的文本,怎么翻译?

英语和中文的语序不同,简单的字符串拼接("已选 " + count)在多语言中是行不通的。

解决方案:占位符

我们利用标准化的格式化占位符:

  • %d:整数
  • %s:字符串
  • %f:浮点数

资源定义 (string.json):

// base
{ "name": "selected_count_fmt", "value": "已选 %d 项" }

// en_US
{ "name": "selected_count_fmt", "value": "%d items selected" }

代码调用:

$r 函数支持传入第二个、第三个参数作为变量。

@Component
struct SelectionBar {
  @Prop count: number;

  build() {
    // 自动将 this.count 填入 %d 的位置
    // 中文显示:已选 5 项
    // 英文显示:5 items selected
    Text($r('app.string.selected_count_fmt', this.count))
      .fontSize(12)
  }
}

这种方式完美解决了语序问题,是开发者的必备技能。

场景三:高阶难点——逻辑层(非UI)的资源获取

这是我在开发 v1.1 时遇到的最大坑,也是本文最想分享的干货

在 UI 组件(build 函数内),我们可以直接用 $r。但是,在 逻辑代码 或者 数据层 中,我们无法直接使用 $r

遇到的问题:

在《会议随记 Pro》的 TagSelector(标签选择器)组件中,我们需要一个推荐标签池。

// 错误做法
// 如果这样写,数组里存的是 Resource 对象,而不是字符串
// 后续进行 includes() 判断或存入数据库时会由类型错误
const TAGS = [ $r('app.string.tag_urgent'), $r('app.string.tag_todo') ];

我们需要在代码运行的时候,把资源 ID 同步转换 为真实的字符串(String)。

解决方案:ResourceManager

我们需要手动调用鸿蒙的资源管理器。这通常在组件的 aboutToAppear 生命周期中进行。

1. 定义资源数组(只存 ID):

const TAG_RES_IDS: Resource[] = [
  $r('app.string.tag_review'),
  $r('app.string.tag_weekly'),
  $r('app.string.tag_urgent')
];

2. 在逻辑中加载字符串:

@Component
export struct TagSelector {
  @State recommendTags: string[] = [];

  aboutToAppear() {
    // 获取当前上下文
    const context = getContext(this);
    // 获取资源管理器
    const manager = context.resourceManager;

    // 遍历资源 ID,同步获取对应的字符串
    this.recommendTags = TAG_RES_IDS.map(res => {
      try {
        // getStringSync 是 API 12 的核心方法,同步读取
        return manager.getStringSync(res.id);
      } catch (e) {
        return ''; // 兜底防止崩溃
      }
    });
  }
  
  // 现在 recommendTags 里存的就是 ["评审", "周会"] 或 ["Review", "Weekly"]
  // 可以放心地进行逻辑判断了
}

深度解读:

resourceManager.getStringSync(res.id) 是连接“资源世界”和“代码世界”的桥梁。它允许我们在非 UI 渲染阶段(如数据初始化、数据库存储前预处理、日志记录)获取到用户当前所见到的真实文本。

这在生成演示数据时尤为重要。在 v1.1 的更新中,我们的 DemoDataManager 会在生成模拟数据前检测系统语言,如果是英文环境,就利用这套机制加载英文的模拟会议标题和内容,让新用户的开箱体验没有任何割裂感。


四、国际化开发的心得与避坑指南

在完成这次重构后,我有几点心得想分享给各位开发者:

1. 尽早开始,不要拖延

不要觉得我的 App 刚起步,先写死中文没事。后期提取字符串是一项极其枯燥且容易出错的体力活。从第一行代码开始,就坚持使用 $r。哪怕你暂时只有中文,也请把它放在 string.json 里。

2. 语义化命名 Key

Key 的命名决定了可维护性。

  • 错误: text1, button_red (不知所云)
  • 正确:meeting_detail_title, btn_delete_confirm (模块_功能_位置)

    建议按照 页面_组件_语义 的格式来命名。

3. 注意长度适配 (UI Adaptation)

同一个词,英文往往比中文长。

  • 中文:“编辑” (2个字符)
  • 英文:“Edit” (4个字符)
  • 中文:“会议录音实时转写” (9个字符)
  • 英文:“Real-time meeting audio transcription” (30+字符)

在 v1.1 的 UI 重构中,我们将许多固定宽度的 RowButton 改为了 Flex 布局或使用了 layoutWeight,并设置了 textOverflow: Ellipsis(省略号),就是为了防止英文文案撑爆界面。

4. 敏感数据的本地化

我们在 v1.1 中加入了 mic_reason(麦克风权限理由)和 media_reason(媒体库权限理由)的翻译。这在应用上架审核时非常重要。如果用户的系统是英文,但弹出的权限请求框是中文,会被视为体验不合格甚至导致拒审。

总结

《会议随记 Pro》的 v1.1 更新,表面看是多了个语言选项,实则是应用架构的一次成熟度跃升。

通过 HarmonyOS NEXT 强大的资源管理系统,我们用一套代码完美适配了多种文化环境。

这不仅拓展了潜在的用户群体,更重要的是,它体现了我们对每一位用户,无论他使用何种语言——的尊重。

我一直用 Bark ,很喜欢:省心、稳定,作者也一直在更新。PushGo 这个坑某种程度上就是从 Bark 开始的,先向作者致敬🫡。

后来我自己维护的东西越来越多:服务器、CI 、脚本任务、家里设备……推送一开始还能靠“多发点提醒”解决,但很快就会变成另一种麻烦:消息很难整理。同一件事会从不同来源冒出来(监控、脚本、日志、告警),通知列表里一堆“碎片”,你要自己在脑子里拼图:到底发生了什么、现在处于什么状态、是偶发还是持续、有没有恢复。

所以我干脆自己写了个 PushGo ,目前它的定位很明确:先把“收消息 + 更好整理”做好。后面再慢慢往更通用、更可扩展的方向演进。

PushGo 的思路

PushGo 的思路和 Bark 不太一样,更像 MQTT / Ntfy 那套:频道 + 订阅( pub/sub )

你创建频道、订阅频道,消息按主题走,路由和转发会灵活很多;未来不管是扩展更多推送渠道,还是把消息类型做得更丰富,这种结构都更顺手。

  • 目前已经完成 iOS / watchOS / macOS + Android ( FCM )平台适配,全部原生开发,apple 平台使用 Swift ,Android 平台使用 Kotlin
  • WNS 和自有推送渠道正在路上,国内无法访问 FCM 的问题,自有渠道上线后就会得到解决
  • 公共网关已部署,并且支持自部署网关
  • 消息正文支持文本和部分 markdown 标签,可以渲染轻量级表格
  • 消息支持 AES-GCM 加密,网关不保留任何与解密有关的数据
  • 永久完全免费,不管客户端还是网关,纯公益运营

未来方向

  • 客户端会持续推进更多平台支持,并不仅限于高性能设备,比如目前我自己就在做一个带屏的 ESP32 设备

  • 目前客户端还很简单,也存在很多不足,尤其是 UI ,因为我自己实在没有这方面的天赋,所以 UI 只能尽量贴合系统原生,未来会持续改进优化,不断改进功能和体验,如果你有任何产品问题和建议,也可以加入 TG 群一起探讨,如果有小伙伴愿意提供 ui 设计方面的支持,欢迎 TG 私聊,感谢

  • 服务端未来会加入 MQTT 等协议支持,不仅支持消息接入,也会提供第三方注册为客户端接收消息

  • 我后面有一个比较明确的长期方向:参考 IoT 里的 物模型 概念,把一些东西(服务器、任务、设备)抽象成“模型”,用属性持续更新状态,然后在 App 端围绕这些状态做聚合展示、规则处理、报警/联动等。从消息接收器转身为综合消息枢纽,不过这个变化很大,未来尚不确定是基于 PushGo 演进,或者另开新坑

目前进度 & 参与测试

目前网关 + iOS / watchOS / macOS + Android ( FCM )都已经有初版了,也部署了公共网关,正式版预计将在一个月左右到来。

作为免费运营的公益项目,欢迎大家参与共建,为 App 和网关的持续迭代建言献策,我不希望闭门造车,大家的需求才是最重要的演进方向

截图

截图被第三方图床压缩过了,惨不忍睹,大家随便看看就好

明朝那些事儿有声书 - 周建龙版 - 总共 938 个音频。

一直在 B 站听,但是经常性被删视频,导致无法连续。所以网上找了音频和开源做了一个网页。

地址:https://ming.creepylink.org/

截图

明朝那些事儿有声书

介绍

《明朝那些事儿》有声书的网页播放器,支持在线播放、列表切换与进度记忆,适合连续收听与快速回听。

功能

  • 播放控制:播放/暂停、上一集、下一集
  • 播放列表:查看全部章节并点击跳转播放
  • 进度控制:点击进度条快速跳转
  • 断点续播:自动保存上次收听集数与播放进度
  • 收藏标记:可对当前集进行收藏/取消

使用

  1. 打开页面后,播放器会自动加载音频列表。
  2. 点击播放按钮开始收听,或在列表中点击任意章节直接播放。
  3. 通过进度条点击可跳转到指定时间点。
  4. 关闭页面后再次打开,会从上次的集数与进度继续播放。

使用的开源代码地址: https://github.com/jasonbai008

你有没有遇到过,在使用pandas的时候批处理任务跑完了,

del df

执行了,甚至还使用了

import gc; gc.collect()

但是进程内存确没有减少。

我们首先就会想到这可能是"pandas 有内存泄漏",其实这不一定就是泄漏。可能是引用、分配器的正常行为。而且在pandas 3.0 之后这类情况更多了,因为Copy-on-Write 改变了数据共享的方式,Arrow 支持的 dtype 让内存行为变得更难预测。

RSS 不是"正在使用的内存"

很多人把 RSS 当成实际内存占用来看,这是问题的根源。

RSS 是操作系统报告的常驻内存大小,而Python 对象实际需要多少内存是另一回事。分配器为了提高效率会预留一大块内存池(arena)以备后用。删掉一个 DataFrame,Python 层面的对象确实释放了但 RSS 不一定下降,因为分配器(Python 的、NumPy 的、Arrow 的、libc 的)只是把这块内存标记为"可重用",并没有还给操作系统。

这就解释了一个常见现象:监控面板上看着像在泄漏,但程序跑得好好的,吞吐量很稳定。内存在进程内部被重复利用,RSS 高位运行其实是正常的。

Copy-on-Write 带来的认知陷阱

pandas 3.0 默认启用了 Copy-on-Write。从用户角度看索引操作和很多方法都"像是"返回了副本,不用再担心意外修改原数据。听起来很好,但这里有个容易忽略的点:CoW 改善的是行为安全性,跟内存什么时候释放没有直接关系。

底层实现上,CoW 会让多个 DataFrame 或 Series 共享同一块数据缓冲区,直到某个对象发生写操作才触发真正的复制。换句话说,你以为创建了好几个独立的副本,实际上它们可能都指向同一块内存。只要任意一个派生对象还活着,这块内存就不会被释放。

哪删掉了"主" DataFrame?没用的,如果某个 Series 切片还在作用域里那一大块缓冲区照样活得好好的。

最常见的"假泄漏":视图比主对象活得久

 import pandas as pd  
   
 df = pd.DataFrame({"a": range(10_000_000), "b": range(10_000_000)})  
 view = df[["a"]]          # looks small, but can keep df's blocks alive  
 del df                    # you expect memory drop  
 # view still references the underlying data, so buffers can remain

这是实际使用的时候碰到最多的情况。一个看起来人畜无害的 view,实际上在底层持有整个大表的数据块引用。你删掉了 df,但 view 没删内存就这么留着了。

那些不是"副本"的"副本"

即便不考虑 CoW,pandas 本身就有很多这类行为:操作返回的对象可能共享底层数据块,或者内部维护着某些引用。而Python 变量只是冰山一角。闭包、缓存字典、全局变量、异步任务,这些任何一个都可能悄悄地让对象存活下去。

几个高频踩坑场景:

把中间结果存进列表"方便调试":

 snapshots = []  
 for chunk in chunks:  
     df = transform(chunk)  
     snapshots.append(df)     # you keep every chunk alive

每个 chunk 都活着,内存持续增长。

按用户 ID 或任务 ID 缓存结果,开发阶段觉得挺聪明,上了生产变成了内存博物馆——只进不出。

还有一种是 GroupBy 加上一长串 apply 链式调用,中间产生大量临时对象,GC 来不及回收,尤其在循环里更明显。

Arrow buffers:快是真快,粘也是真粘

pandas 3.0 默认启用了专用的 string dtype,装了 PyArrow 的话字符串列会用 Arrow 作为底层存储。性能和内存效率都有提升,但代价是内存行为变得更复杂。

Arrow 有自己的缓冲区管理和内存池机制。你可能会看到这种诡异的现象:

pyarrow.total_allocated_bytes()

显示 Arrow 那边已经释放得差不多了,但

psutil.Process().memory_info().rss

却一直往上涨。

这不一定是泄漏,更可能是内存池化加上碎片化加上延迟释放的综合效果。

双缓冲区

从 Parquet 读数据是很常见的操作。先读成 Arrow Table,再转成 pandas DataFrame,如果两个对象都留在作用域里,等于同一份数据在内存中存了两遍。

 import pyarrow.parquet as pq  
   
 table = pq.read_table("big.parquet")  
 df = table.to_pandas()     # now you may hold Arrow buffers + pandas objects  
 # If table stays referenced, memory won't drop as you expect

解决方法也很简单,转换完就 del 掉源对象。

排查检查清单

与其凭直觉猜测,不如系统地排查。

第一步,确认到底是持续增长还是一次性的高水位。同一个进程里把任务跑两遍,如果第一遍 RSS 上升、第二遍稳定,那多半是分配器在重用内存,不是泄漏。如果 RSS 随着工作量线性增长,那确实有东西在不断积累——可能是真正的泄漏,也可能是某个无限增长的缓存。

第二步,关注对象引用而不是内存数字。用

gc.get_objects()

采样观察对象数量变化趋势,用

tracemalloc

追踪 Python 层面的分配模式,用

objgraph

找出哪些类型在增长、被谁持有。

第三步,区分 Python 堆和原生缓冲区。Python 分配可以用 tracemalloc 和 pympler 看,进程 RSS 用 psutil,Arrow 的内存用

pyarrow.total_allocated_bytes()

。如果 Python 层面很平稳但 RSS 在涨,问题多半出在原生内存池或碎片上。

第四步,排查意外引用。DataFrame 或 Series 有没有被存进全局变量、类属性或者某个缓存字典?有没有往列表里追加数据忘了清理?lambda 或回调函数有没有闭包了 df?有没有返回的对象内部持有大对象的引用?

第五步,实在搞不定就用进程隔离。跑 Arrow/Parquet 密集型任务时,把工作放到 worker 进程里,定期回收 worker(比如每处理 N 个文件就重启一次),让操作系统来当垃圾收集器。

总结

pandas 的"内存泄漏"多数时候是下面几种情况:视图或切片持有大缓冲区的引用导致无法释放;Copy-on-Write 机制让数据共享的时间比预想的长;Arrow 或其他原生分配器即使对象释放后仍保留内存池;缓存、列表、闭包、长期任务导致对象被意外持有。

真正有效的应对方式不是

gc.collect()

,而是:缩短对象生命周期,避免无意间保留引用,测量正确的指标,必要时用进程回收来兜底。

https://avoid.overfit.cn/post/44a0a3f2e4544cbe9307e9afe262779b

by Nikulsinh Rajput

原型就是帮你把产品思路变直观的纽带——能让团队一眼看明白产品要做什么、怎么交互,省得反复沟通磨嘴皮。而原型工具,更是产品经理每天工作都离不开的“吃饭家伙”。下面整理了10款常用原型工具,覆盖各种使用场景,帮你快速挑到适合自己的那一款。

  1. UXbot
    UXbot从产品需求、流程规划,到原型制作、界面设计、预览分享、Web前端代码生成,一套流程全搞定。UXbot主要依赖自然语言需求,让你只需要输入一个简短的需求,就能在几十秒内就可以直接生成可视化PRD文档、交互说明等核心产品资产,以及网站、APP、平板端等多场景的可交互的高保真原型设计。关键是界面做得干净直观,新手也能快速上手。内置AI助手和专业编辑器,页面元素大小、颜色、图片、排版等都能按照自己的需求进行修改。彻底打破设计与文档割裂的传统壁垒。大幅降低重复性工作内耗。
    素材模板也很丰富,电商、社交、教育、金融、旅游等行业都有覆盖,不管你要做哪类产品的原型,UXbot都支持。
    image.png
  2. Axure RP
    这是原型设计圈的老牌子工具了,专门用来做网站和APP的高保真原型,能直接导出HTML、Javascript、CSS格式的文件,和开发对接起来很顺畅。动态面板功能特别强,能实现复杂的交互逻辑,适合资深产品经理做大型项目的精细原型。
    不过它的缺点也很明显,学习门槛高,新手得花不少功夫才能摸透它的复杂功能和操作逻辑。而且它是离线工具,原型预览、分享都不太方便,在国内用的时候偶尔会卡顿,对团队快速协作不太友好。
    image.png
  3. Invision
    核心优势就是协作共享,是个云端原型平台,能打破产品、设计、开发之间的沟通壁垒,大家可以在同一个平台上配合工作。还支持导入Sketch、Adobe XD这些设计工具的文件,方便整合不同渠道的设计资源。
    美中不足的是,整个界面都是英文的,对不熟悉英文的国内用户不太友好,而且访问速度时快时慢,偶尔会影响使用体验。
    image.png
  4. Proto.io
    这款工具主打交互动效,不用写代码,设计师只要拖拖拽拽,添加交互动作和动画,就能做出还原度很高的复杂交互原型。但它在界面设计和布局方面的功能比较弱,如果项目需要精细打磨界面视觉效果,用它就不太合适了。
    image.png
  5. Sketch
    专门用来做APP和网页界面设计,不过只有苹果电脑能用。支持共享样式和符号功能,团队合作时能轻松保持设计风格统一。第三方插件特别多,能根据自己的需求扩展功能,满足不同的设计场景。
    image.png
  6. Justinmind
    擅长做复杂的高保真原型,能实现条件逻辑、数据驱动交互这些复杂的交互效果。还自带用户测试和模拟功能,方便收集反馈优化方案,尤其适合做企业级应用和复杂系统的原型。
    缺点是界面逻辑太绕,得花不少时间学操作方法,入门级用户不建议优先选。
    image.png
  7. Atomic
    基于CSS的组件化原型工具,最大的好处是组件能反复用,内置了丰富的原子组件库,能快速搭好原型、提高效率。
    不过它更偏向开发者使用,产品经理或设计师用的话,得有一定的技术基础才行。
    image.png
  8. Figma
    近几年特别火的在线原型和UI设计工具,高保真视觉设计能力很强。支持多人同时编辑同一个原型,远程团队协作用它特别合适。插件库也很丰富,能灵活拓展功能,满足更多需求。
    image.png
  9. Marvel APP
    一款轻量化的原型工具,能导入Photoshop、Sketch的设计文件,不用写代码就能做出原型应用。
    但功能比较基础,搞不定复杂的交互逻辑,适合简单项目快速验证想法。
    image.png
  10. Bubble
    这是个可视化编程平台,不懂技术的人也能做出复杂的网页应用原型,不用写一行代码就能实现核心功能。
    美中不足的是,一些高级交互和功能得靠插件才能实现,自主拓展的空间有限。
    image.png

总结
以上10款原型工具各有侧重,不管是做低保真、高保真原型,还是个人用、团队协作,都能找到对应的工具。产品经理选的时候,要结合项目复杂程度、团队技术水平和预算来综合考虑。选对工具不仅能提高工作效率,还能把设计思路、交互逻辑讲清楚,让产品设计和开发推进得更顺利。

很久以前,就想写一篇关于SDL与DevSecOps的文章,但疏于实践一直未能动笔。想写的原因很简单,因为总是听到有人说SDL落后、DevSecOps相关技术更高超。一提到研发安全建设,不分研发模式都在赶时髦一样地说DevSecOps。从我的观察来看,不结合研发模式来做研发安全,都是不成功的。

在数字化浪潮的推动下,一些公司已经完全步入DevOps模式,有的则出现瀑布、敏捷或DevOps并存,且后者是居多的。所以如何在多种研发模式下进行有效的研发安全建设,成为一个必须解决的难题。经过近十年的实践,终于在探索解法上有一点点收获与经验,于是有了“深耕研发安全”这一系列文章。

本文是第二篇,主要介绍从纯安全的视角出发,紧密围绕漏洞及治理,结合对成本的考虑,去定位研发过程中的漏洞生产源,从而找出最佳的研发安全工作切入点。

01 漏洞通常是企业入口

下面最左边那张图,是近十年提交到CNVD的漏洞趋势统计,平均每年有1.7w个漏洞被发现并提交。然而这只不过是冰山一角,国内外还有很多类似的平台在收集漏洞,全世界也还有很多漏洞并未被提交到这些平台。所以说,每年发现的漏洞数是非常大的。

图片

其次,在国家级或者各行业的实战攻防演习中,攻击队通常会用互联网业务系统漏洞进行打点,从而突破边界进入内网发起攻击。这些web漏洞、软件供应链漏洞都属于软件安全质量范畴,足以见得漏洞对于企业安全来说是多么重要。

第三是国家对于漏洞的重视程度也在逐渐提高和明确。随着对网络安全的重视,各行业对漏洞都有一些明确的要求,比如上面右图这种漏洞管理的规范,甚至还专门建设漏洞管理平台来收集。

综上三方面想说明:软件的漏洞,特别值得我们去关注和花心思治理。

02 什么称之为安全漏洞

前面一直在提漏洞,那什么是漏洞?见过很多漏洞定义和分类方法,此处想从研发过程来看,包括软件和协议方面的,几乎可以被全部囊括在内。

图片

换而言之,这些漏洞都可以在研发过程中被发现,然后有机会得到治理。

03 怎么切入做研发安全

在软件质量领域,有一个先驱者叫琼斯,在他的报告中提出以下三张图及对应着三个观点。从安全角度来看,依旧是适用的:

  • 85%的缺陷都是在开发人员编码时引入;
  • 目前大多数缺陷都是在测试阶段被发现;
  • 缺陷的修复工作越往后成本就会越大。

图片

(图片创意来自互联网)

于是得出一个结论:要切入开发流程,尽早地去做研发安全。然而现在又有人提出一个无处不移的概念,其实这也是相对的,在每个阶段开展安全活动都比较重要。

04 研发过程漏洞生产源

上面提到,在编码阶段引入了85%的漏洞,那剩余的15%在哪儿?如果对漏洞按照开发阶段进行分类,不难发现还有两个主要来源:

图片

第一个是还没开始写代码,即在设计阶段做技术架构选型与设计时,不遵守安全设计原则或未充分考虑安全性,就可能引入漏洞。如:

  • 使用存在已知漏洞、潜在后门的开源软件/组件:Java程序中使用旧版本的fastjson、使用被投毒的xz操作系统opensuse等;
  • 软件内部设计存在安全缺陷:应用层服务间相互调用,缺少网关统一管控、无认证机制等。

第二就是写完代码并提交,此时还是可能引入漏洞。在部署和发布阶段,PAAS层软件未做安全性配置,就可能带来安全隐患。如非必要使用root权限启动服务、不设置账密、使用默认账密等。

所以说,从安全的角度来看研发,至少要关注架构、编码和配置三方面的问题。

本文首发于微信公众号:我的安全视界观

一、 引言:AI 代理(Agent)时代的“分水岭”

2026 年 1 月底,GitHub 见证了一个开源神话的诞生。一个名为 Clawdbot 的项目在短短数周内疯狂斩获近 5 万颗星,其增长曲线几乎呈垂直上升态势。这种“霸榜”级的热度,直接引发了技术圈抢购 Mac Mini 的热潮,大家纷纷试图搭建属于自己的“私人 JARVIS”。

Clawdbot 的爆发标志着我们正式从“对话式 AI”跨入“执行式 AI”时代。它不再仅仅是提供建议,而是能够全天候(24/7)工作,像一名真正的“AI 员工”一样代表用户直接操作电脑并执行任务。


二、 什么是 Clawdbot?——你的本地“数字管家”

Clawdbot 是一个开源的 AI 编排框架,其核心理念是将强大的大语言模型(LLM)能力转化为实际的系统操作力。

⚠️ 重要澄清:它不是 Claude Code
在深入了解之前,必须澄清一个普遍的误区:Clawdbot 并非 Anthropic 官方发布的 Claude Code。它是一个独立的开源应用程序(Container),你可以将它视为一个“超级外壳”,它在底层调用 Claude Code、Gemini 或 GPT 等大模型来驱动你的电脑。

它具有以下五个跨时代的特质:

  • 本地运行 + 全系统权限:它安装在你的本地设备或 VPS 上,拥有对终端(Terminal)、文件系统和应用程序的深度访问权。
  • 远程指挥:通过连接 Telegram、WhatsApp 或 Slack,你可以从手机端随时随地给远在家里的 AI 发送指令并获取结果。
  • “主动性”范式转变:不同于等待提问的 ChatGPT,Clawdbot 是主动服务的,它会根据对你的了解主动寻找任务并向你汇报。
  • 持久记忆:它能跨越对话记住你的偏好、项目历史和习惯,实现真正的个性化助理体验。
  • 自我进化与社区生态:除了能自主编写代码进行功能扩展,它还拥有一个日益壮大的技能数据库(Skills Database)。你可以像下载插件一样,直接下载社区开发者构建好的“技能包”,瞬间赋予它管理服务器或分析股票的新能力。

三、 极客们在用它玩什么?

Clawdbot 的真正魅力在于它打破了数字世界的壁垒,让自动化变得无所不在:

  • 极速处理行政琐事:有用户利用它在 10 分钟内完成了拖延了 18 个月的复杂行政申报表格。
  • 全自动新闻简报:它可以编写一个定时任务(Cron job),每天早上自动搜索互联网上的特定新闻(如 AI 新闻),汇总摘要并发送到你的 Slack 频道。
  • 自动记账:戴着眼镜拍一张收据的照片通过 WhatsApp 发送,它会自动识别金额、分类费用并添加到预算表中。
  • 日程管理:拍一张活动传单,它会自动识别时间地点并直接添加到你的日历中。
  • 系统安全自愈:用户可以让它审查服务器配置,它不仅能发现漏洞(如不安全的 SSH 设置),还能直接执行加固操作。

四、 隐形销金窟与社交“噩梦”

这种全能代理的背后,隐藏着不仅是技术风险,更是现实生活的代价:

  • 后台自动烧钱机制:这是新手最容易踩的坑。Clawdbot 支持 Cron Jobs(定时任务),这意味着它不仅在你提问时工作,还会全天候在后台“四处查看”是否有任务可做(例如扫描文件、检查网页)。这种主动寻找任务的过程可能会在用户不知情的情况下消耗数百万 Token。有用户报告称,仅在一天之内就产生了数百美元的 API 账单。
  • 文件丢失与系统损坏:它可以访问终端、读写文件和安装软件,理论上它可以做你在电脑上能做的任何事。这导致它可能意外删除重要文件、修改系统设置,甚至彻底搞砸你的操作系统。
  • “社交死”级幻觉:作为一个非确定性系统,AI 可能会产生幻觉,例如错误地决定给你的前任发送短信或邮件,造成严重的社交灾难。
  • 开放端口的网络风险:Clawdbot 具有开放端口(Open Ports),这意味着如果配置不当或将其置于未配置的反向代理后,互联网上的任何人都有可能通过身份验证绕过漏洞访问它,导致 API 密钥或隐私聊天记录泄露。

五、 如何在“狂野西部”自保?

目前 Clawdbot 还处于快速迭代的早期阶段,为了安全地享受便利,建议采取以下防护措施:

  • 物理隔离运行:绝不要在存储核心敏感数据的主力机上运行,建议使用专门的备用电脑(如 Mac Mini)或隔离的 VPS 服务器。

  • 严防端口暴露:如果必须开启远程访问,务必应用严格的 IP 白名单措施限制暴露端口的访问,并确保反向代理配置正确,以防身份验证被绕过。
  • 启用沙盒隔离:在配置中启用 Docker 沙盒模式,将 AI 的操作锁定在受限的容器内,防止其破坏宿主机系统。
  • 监控 Token 消耗:定期运行 /status 命令或检查网关面板以监控使用情况。避免设置过于频繁的 heartbeat(心跳)频率,建议将任务模式设置为 next-heartbeat 而非 now 以节省流量。

六、 结语:我们离 Siri 的终极形态还有多远?

Clawdbot 的爆火让我们看到了 AI 助理的未来——它不再是一个简单的对话框,而是一个拥有行动力的数字代理人。它展现了将我们从繁琐重复工作中解放出来的真实可能性。

虽然它目前还像是一个充满野性的极客工具,需要用户具备高度的安全意识,但其代表的 Agent 趋势已不可阻挡。如果你已经准备好迎接这位 24 小时待命的“数字员工”,现在就是开始探索的最佳时机。

本文由mdnice多平台发布

揭秘Stable Diffusion背后:VAE中KL正则化损失的数学本质与工程实现

注1:本文系"每天一个多模态知识点"专栏文章。本专栏致力于对多模态大模型/CV领域的高频高难面试题进行深度拆解。本期攻克的难题是:Stable Diffusion中VAE的KL正则化损失
注2:本文Markdown源码可提供下载,详情见文末
关注"每天一个多模态知识点"公众号,每天一个知识点的深度解析!

面试原题复现

【面试问题】

请详细解释Stable Diffusion中VAE的KL正则化损失:

  1. 从数学角度:给出KL散度的定义、VAE中KL项的具体表达式,并手写推导高斯分布的KL散度闭式解
  2. 从信息论角度:解释KL散度的物理含义,以及它在ELBO(证据下界)中的作用
  3. 从工程实践角度:Stable Diffusion中KL项的权重系数为何设置得如此小?这会带来什么问题?如何解决?
  4. 手撕代码:用PyTorch实现VAE的KL Loss计算函数,包括重参数化采样
  5. 进阶追问:KL散度不是真正的距离,其非对称性在VAE中的具体表现是什么?

关键回答(The Hook)

KL正则化损失是VAE训练中的"信息约束器"。从信息论角度看,它衡量的是使用编码器输出的后验分布 $q_\phi(z|x)$ 来近似先验分布 $p(z)$ 时所产生的信息损失。在ELBO框架下,它与重建损失形成对抗-协作的平衡机制:重建损失要求保留输入的所有信息,而KL损失则迫使编码器仅保留最本质的信息,从而实现信息的自动压缩与筛选。Stable Diffusion中采用极小权重(约1e-6)的KL正则化,是因为在图像生成任务中,重建质量优先于潜在空间的完美对齐,并通过Rescaling技术解决由此产生的数值稳定性问题。

图1:VAE整体架构示意图。编码器将输入x映射到潜在空间分布q(z|x),通过重参数化技巧采样得到z,再由解码器重建x。KL正则化约束q(z|x)逼近先验p(z)。


深度原理解析(The Meat)

一、KL散度的数学定义与物理含义

1.1 基本定义

对于两个离散概率分布 $P$ 和 $Q$,KL散度(Kullback-Leibler Divergence)定义为:

$$D_{KL}(P || Q) = \sum_{x \in \mathcal{X}} P(x) \log \frac{P(x)}{Q(x)}$$

对于连续分布:

$$D_{KL}(P || Q) = \int_{-\infty}^{\infty} p(x) \log \frac{p(x)}{q(x)} dx$$

关键性质:$D_{KL}(P || Q) \geq 0$,当且仅当 $P = Q$ 时取等号。这被称为Gibbs不等式

面试追问点:为什么KL散度不是距离?因为它不满足对称性,即 $D_{KL}(P || Q) \neq D_{KL}(Q || P)$。

1.2 信息论解释:信息的额外成本

KL散度从信息论角度可以理解为:当真实分布为P,但我们使用分布Q来编码数据时,每个样本平均需要多付出的比特数

从香农熵的角度:

$$D_{KL}(P || Q) = \mathbb{E}_{x \sim P}[-\log Q(x)] - \mathbb{E}_{x \sim P}[-\log P(x)] = H(P, Q) - H(P)$$

其中:

  • $H(P) = -\sum P(x) \log P(x)$ 是分布P的熵(不确定性)
  • $H(P, Q) = -\sum P(x) \log Q(x)$ 是交叉熵(用Q编码P的期望编码长度)

物理直觉:如果Q很好地近似P,那么用Q编码P几乎不会产生额外代价;如果Q偏离P太远,就会产生巨大的"信息损失"。

在VAE中:

  • $P = p(z) = \mathcal{N}(0, I)$ 是先验分布(标准正态)
  • $Q = q_\phi(z|x)$ 是编码器输出的后验分布

KL散度约束编码器不要"太聪明"——即不要为每个输入学习一个完全不同的分布,而是要尽量保持接近标准正态分布。

图2:VAE编码器-解码器详细结构。编码器输出均值μ和方差σ²,采样得到潜在变量z,解码器重建输入。KL项约束z的分布接近标准正态。


二、ELBO与KL散度的关系

2.1 从对数似然到ELBO

VAE的核心是最大化边缘似然 $\log p_\theta(x)$,但积分不可解:

$$\log p_\theta(x) = \log \int p_\theta(x, z) dz$$

引入辅助分布 $q_\phi(z|x)$ (变分近似后验),利用Jensen不等式:

$$\log p_\theta(x) = \log \mathbb{E}_{z \sim q_\phi(z|x)}\left[\frac{p_\theta(x, z)}{q_\phi(z|x)}\right] \geq \mathbb{E}_{z \sim q_\phi(z|x)}\left[\log \frac{p_\theta(x, z)}{q_\phi(z|x)}\right]$$

这个下界就是ELBO(Evidence Lower Bound):

$$\text{ELBO}(\theta, \phi) = \mathbb{E}_{z \sim q_\phi(z|x)}[\log p_\theta(x, z) - \log q_\phi(z|x)]$$

2.2 ELBO的分解

将联合概率 $p_\theta(x, z) = p_\theta(x|z)p(z)$ 代入:

$$\text{ELBO} = \mathbb{E}_{z \sim q_\phi(z|x)}[\log p_\theta(x|z) + \log p(z) - \log q_\phi(z|x)]$$

$$= \underbrace{\mathbb{E}_{z \sim q_\phi(z|x)}[\log p_\theta(x|z)]}_{\text{重建项}} + \underbrace{\mathbb{E}_{z \sim q_\phi(z|x)}[\log p(z) - \log q_\phi(z|x)]}_{-D_{KL}(q_\phi(z|x) || p(z))}$$

$$= \mathbb{E}_{z \sim q_\phi(z|x)}[\log p_\theta(x|z)] - D_{KL}(q_\phi(z|x) || p(z))$$

因此,最大化ELBO等价于:

  1. 最大化重建项:让解码器能从z准确重建x
  2. 最小化KL散度:让编码器输出分布 $q_\phi(z|x)$ 接近先验 $p(z)$
2.3 几何解释:信息瓶颈

ELBO可以重新写为:

$$\log p_\theta(x) = \text{ELBO} + D_{KL}(q_\phi(z|x) || p_\theta(z|x))$$

其中 $p_\theta(z|x)$ 是真实后验(不可计算的)。这说明:

  • 当ELBO最大化时,$D_{KL}(q_\phi(z|x) || p_\theta(z|x))$ 最小化
  • 这意味着 $q_\phi(z|x)$ (编码器近似) 越来越接近 $p_\theta(z|x)$ (真实后验)

KL正则化在中间起到了"挤压"作用:

  • 没有KL项:编码器可能将不同输入编码到完全无关的分布(潜在空间离散、不连续)
  • 有KL项:编码器被迫将所有输入编码到接近 $\mathcal{N}(0, I)$ 的区域(潜在空间平滑、连续)

图3:潜在空间的可视化。理想情况下,不同语义属性(微笑、肤色等)在潜在空间中形成连续的流形结构。KL正则化有助于保持这种平滑性。


三、高斯分布KL散度的闭式解推导

这是面试中最常要求手推的部分!

3.1 问题设定

设:

  • 编码器输出: $q_\phi(z|x) = \mathcal{N}(z; \mu_\phi(x), \text{diag}(\sigma_\phi^2(x)))$
  • 先验分布: $p(z) = \mathcal{N}(z; 0, I)$ (标准正态,各维度独立)

我们需要计算:

$$D_{KL}(\mathcal{N}(\mu, \sigma^2) || \mathcal{N}(0, 1))$$

假设各维度独立,多元分布的KL散度可分解为各维度之和:

$$D_{KL}(q || p) = \sum_{i=1}^d D_{KL}(q_i || p_i)$$

因此只需推导一维情况:

$$D_{KL}(\mathcal{N}(\mu, \sigma^2) || \mathcal{N}(0, 1)) = \int \mathcal{N}(z; \mu, \sigma^2) \log \frac{\mathcal{N}(z; \mu, \sigma^2)}{\mathcal{N}(z; 0, 1)} dz$$

3.2 详细推导

写出两个高斯分布的概率密度函数:

$$\mathcal{N}(z; \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(z-\mu)^2}{2\sigma^2}\right)$$

$$\mathcal{N}(z; 0, 1) = \frac{1}{\sqrt{2\pi}} \exp\left(-\frac{z^2}{2}\right)$$

因此:

$$\log \frac{\mathcal{N}(z; \mu, \sigma^2)}{\mathcal{N}(z; 0, 1)} = \log \mathcal{N}(z; \mu, \sigma^2) - \log \mathcal{N}(z; 0, 1)$$

$$= \left[-\frac{1}{2}\log(2\pi\sigma^2) - \frac{(z-\mu)^2}{2\sigma^2}\right] - \left[-\frac{1}{2}\log(2\pi) - \frac{z^2}{2}\right]$$

$$= -\frac{1}{2}\log(2\pi\sigma^2) + \frac{1}{2}\log(2\pi) - \frac{(z-\mu)^2}{2\sigma^2} + \frac{z^2}{2}$$

$$= -\frac{1}{2}\log\sigma^2 - \frac{(z-\mu)^2}{2\sigma^2} + \frac{z^2}{2}$$

现在计算期望:

$$D_{KL} = \mathbb{E}_{z \sim \mathcal{N}(\mu, \sigma^2)}\left[-\frac{1}{2}\log\sigma^2 - \frac{(z-\mu)^2}{2\sigma^2} + \frac{z^2}{2}\right]$$

$$= -\frac{1}{2}\log\sigma^2 - \mathbb{E}\left[\frac{(z-\mu)^2}{2\sigma^2}\right] + \mathbb{E}\left[\frac{z^2}{2}\right]$$

逐项计算:

第一项: $-\frac{1}{2}\log\sigma^2$ (常数)

第二项: $\mathbb{E}\left[\frac{(z-\mu)^2}{2\sigma^2}\right] = \frac{1}{2\sigma^2} \mathbb{E}[(z-\mu)^2] = \frac{1}{2\sigma^2} \cdot \sigma^2 = \frac{1}{2}$

第三项: $\mathbb{E}\left[\frac{z^2}{2}\right] = \frac{1}{2} \mathbb{E}[z^2]$

对于 $z \sim \mathcal{N}(\mu, \sigma^2)$:

$$\mathbb{E}[z^2] = \text{Var}(z) + (\mathbb{E}[z])^2 = \sigma^2 + \mu^2$$

因此第三项为 $\frac{\sigma^2 + \mu^2}{2}$

综合三项:

$$D_{KL} = -\frac{1}{2}\log\sigma^2 - \frac{1}{2} + \frac{\sigma^2 + \mu^2}{2}$$

$$= \frac{1}{2}(-\log\sigma^2 - 1 + \sigma^2 + \mu^2)$$

$$= \frac{1}{2}(\mu^2 + \sigma^2 - \log\sigma^2 - 1)$$

对于d维独立分布,求和得到:

$$D_{KL}(q_\phi(z|x) || p(z)) = \frac{1}{2} \sum_{i=1}^d (\mu_i^2 + \sigma_i^2 - \log\sigma_i^2 - 1)$$

这就是Stable Diffusion中使用的闭式解!

避坑指南:在代码实现中,编码器通常输出的是log方差 $\log\sigma^2$ 而非方差本身,这是为了数值稳定性。因此代码中的公式会略有不同。

图4:ELBO优化过程中潜在空间的演化。随着训练进行,编码器输出的分布(彩色点云)逐渐收敛到标准正态分布(白色等高线)。


四、Stable Diffusion中的特殊实现

4.1 KL项的权重设置

Stable Diffusion中VAE的完整损失函数为:

$$\mathcal{L}_{\text{VAE}} = \mathcal{L}_{\text{recon}} + \beta \cdot D_{KL}(q_\phi(z|x) || p(z))$$

其中:

  • $\mathcal{L}_{\text{recon}}$ 是重建损失(常用L1+感知损失+对抗损失)
  • $\beta$ 是KL权重系数,在SD中设置为极小值(约$10^{-6}$)

为什么要用这么小的β?

  1. 任务优先级: 在Stable Diffusion中,VAE的主要作用是压缩而非生成。解码质量(重建损失)比潜在空间完美对齐(KL损失)更重要
  2. 信息保留: 较小的KL权重允许编码器在潜在空间保留更多信息,这对后续U-Net的生成任务至关重要
  3. 数值稳定性: 过强的KL正则化可能导致编码器"偷懒",输出接近0的方差,失去学习能力
4.2 Rescaling技术

由于KL权重极小,实际训练中潜在变量的标准差可能远大于1。Stable Diffusion引入了Rescaling机制:

  1. 计算第一个batch中Latent特征的标准差 $\sigma$
  2. 用系数 $1/\sigma$ 重新缩放后续所有Latent特征
  3. 在U-Net中使用缩放后的特征
  4. 解码时逆向缩放

具体公式:

$$z_{\text{scaled}} = \frac{z}{\sigma \cdot 0.18215}$$

其中 $0.18215$ 是SD中的固定rescaling系数。

面试追问点:为什么SD中VAE的Latent空间下采样率是8?这是在压缩率和重建质量之间的权衡。实验表明,f=4时重建效果好但训练慢;f=16时压缩率太高损失细节;f=8是最佳平衡点。

五、KL散度的非对称性及其意义

KL散度的一个关键性质是非对称性:

$$D_{KL}(P || Q) \neq D_{KL}(Q || P)$$

5.1 物理含义差异
  • $D_{KL}(P || Q)$:用Q近似P的代价。当P中概率高的地方Q给出低概率时,惩罚很大(重视假阴性)
  • $D_{KL}(Q || P)$:用P近似Q的代价。当Q中概率高的地方P给出低概率时,惩罚很大(重视假阳性)

在VAE中,我们选择 $D_{KL}(q_\phi(z|x) || p(z))$ 的原因是:

  1. 约束重点: 我们希望编码器输出的分布 $q$ 尽可能"覆盖"先验 $p$ 的所有区域
  2. 生成视角: 当从先验 $p(z)$ 采样生成时,希望采样点在 $q(z|x)$ 的高概率区域
  3. 避免模式坍塌: 如果反向($p||q$),编码器可能学习到非常窄的分布,导致生成多样性下降
5.2 在高斯情况下的表现

对于高斯分布:

$$D_{KL}(\mathcal{N}(\mu_1, \sigma_1^2) || \mathcal{N}(\mu_2, \sigma_2^2)) = \log\frac{\sigma_2}{\sigma_1} + \frac{\sigma_1^2 + (\mu_1-\mu_2)^2}{2\sigma_2^2} - \frac{1}{2}$$

$$D_{KL}(\mathcal{N}(\mu_2, \sigma_2^2) || \mathcal{N}(\mu_1, \sigma_1^2)) = \log\frac{\sigma_1}{\sigma_2} + \frac{\sigma_2^2 + (\mu_2-\mu_1)^2}{2\sigma_1^2} - \frac{1}{2}$$

当 $\sigma_1 \gg \sigma_2$ 时:

  • $D_{KL}(q||p)$ 可能会很大(惩罚方差过大的q)
  • $D_{KL}(p||q)$ 也会很大(惩罚方差过小的p)

但在SD的VAE中,由于我们希望 $q$ 接近标准正态($\sigma \approx 1$),所以两个方向都会惩罚方差偏离1的情况,但惩罚程度不同

深度理解:KL散度的非对称性本质上反映了决策风险的不对称。在VAE中,我们宁可让潜在分布稍微"宽"一些(保留更多信息),也不要让它"窄"到无法采样。这解释了为什么我们选择 $q||p$ 而不是 $p||q$。

图5:二维高斯分布的KL散度可视化。中心红色区域为标准正态先验$p(z)$,彩色点云为编码器输出$q(z|x)$的多个样本。KL散度衡量这两簇分布的差异。


代码手撕环节(Live Coding)

核心实现:VAE的KL Loss

import torch
import torch.nn as nn
import torch.nn.functional as F

class VAEEncoder(nn.Module):
    """
    VAE编码器:将输入x映射到潜在空间分布q(z|x)=N(μ, diag(σ²))
    """
    def __init__(self, in_channels=3, latent_dim=4):
        super().__init__()
        self.in_channels = in_channels
        self.latent_dim = latent_dim
        
        # 下采样块(简化版本)
        self.encoder = nn.Sequential(
            nn.Conv2d(in_channels, 128, 3, stride=2, padding=1),
            nn.GroupNorm(32, 128),
            nn.SiLU(),
            nn.Conv2d(128, 256, 3, stride=2, padding=1),
            nn.GroupNorm(32, 256),
            nn.SiLU(),
            nn.Conv2d(256, 512, 3, stride=2, padding=1),
            nn.GroupNorm(32, 512),
            nn.SiLU(),
        )
        
        # 输出均值和对数方差
        self.mean_layer = nn.Conv2d(512, latent_dim, 1)
        self.logvar_layer = nn.Conv2d(512, latent_dim, 1)
    
    def forward(self, x):
        """
        Args:
            x: 输入图像 [B, C, H, W]
        Returns:
            mu: 均值 [B, latent_dim, h, w]
            logvar: 对数方差 [B, latent_dim, h, w]
        """
        h = self.encoder(x)
        mu = self.mean_layer(h)
        logvar = self.logvar_layer(h)
        return mu, logvar


class VAEDecoder(nn.Module):
    """
    VAE解码器:从潜在变量z重建图像
    """
    def __init__(self, out_channels=3, latent_dim=4):
        super().__init__()
        self.decoder = nn.Sequential(
            nn.Conv2d(latent_dim, 512, 1),
            nn.GroupNorm(32, 512),
            nn.SiLU(),
            nn.ConvTranspose2d(512, 256, 4, stride=2, padding=1),
            nn.GroupNorm(32, 256),
            nn.SiLU(),
            nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1),
            nn.GroupNorm(32, 128),
            nn.SiLU(),
            nn.ConvTranspose2d(128, out_channels, 4, stride=2, padding=1),
        )
    
    def forward(self, z):
        return self.decoder(z)


def reparameterize(mu, logvar):
    """
    重参数化技巧:从q(z|x)采样
    
    关键公式: z = μ + σ * ε, ε ~ N(0, I)
    
    Args:
        mu: 均值 [B, latent_dim, h, w]
        logvar: 对数方差 [B, latent_dim, h, w]
    
    Returns:
        z: 采样的潜在变量 [B, latent_dim, h, w]
    """
    # 从标准正态分布采样噪声
    epsilon = torch.randn_like(mu)
    
    # 计算标准差: σ = exp(logvar / 2)
    std = torch.exp(0.5 * logvar)
    
    # 重参数化采样
    z = mu + std * epsilon
    
    return z


def kl_divergence_gaussian(mu, logvar):
    """
    计算高斯分布q(z|x)=N(μ, σ²)与标准正态p(z)=N(0,1)之间的KL散度
    
    闭式解公式:
    D_KL(q||p) = 0.5 * sum(μ² + σ² - log(σ²) - 1)
    
    Args:
        mu: 均值 [B, latent_dim, h, w]
        logvar: 对数方差 [B, latent_dim, h, w]
    
    Returns:
        kl_loss: KL散度损失 [B]
    
    面试必考点:为什么用logvar而非var?
    - 数值稳定性:避免exp(logvar)溢出
    - 梯度稳定性:直接优化logvar更平滑
    """
    # 使用闭式解
    kl_loss = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp(), dim=[1, 2, 3])
    
    # 另一种写法(数学等价):
    # kl_loss = 0.5 * torch.sum(mu.pow(2) + logvar.exp() - 1 - logvar, dim=[1, 2, 3])
    
    return kl_loss


def vae_loss_function(x, x_recon, mu, logvar, beta=1.0):
    """
    VAE完整损失函数
    
    Args:
        x: 原始输入 [B, C, H, W]
        x_recon: 重建输出 [B, C, H, W]
        mu: 编码器输出的均值 [B, latent_dim, h, w]
        logvar: 编码器输出的对数方差 [B, latent_dim, h, w]
        beta: KL散度的权重系数(Stable Diffusion中约为1e-6)
    
    Returns:
        total_loss: 总损失
        recon_loss: 重建损失
        kl_loss: KL散度损失
    """
    # 重建损失:这里使用L1损失,也可以用L2(MSE)
    recon_loss = F.l1_loss(x_recon, x, reduction='none')
    recon_loss = recon_loss.view(x.size(0), -1).sum(dim=1)  # 对每个样本求和
    
    # KL散度损失
    kl_loss = kl_divergence_gaussian(mu, logvar)
    
    # 总损失
    total_loss = recon_loss + beta * kl_loss
    
    # 返回batch平均值
    return total_loss.mean(), recon_loss.mean(), kl_loss.mean()


# ===== 使用示例 =====
if __name__ == "__main__":
    # 模拟输入图像
    batch_size = 4
    x = torch.randn(batch_size, 3, 256, 256)
    
    # 初始化VAE组件
    encoder = VAEEncoder(in_channels=3, latent_dim=4)
    decoder = VAEDecoder(out_channels=3, latent_dim=4)
    
    # 编码
    mu, logvar = encoder(x)
    print(f"mu shape: {mu.shape}")  # [4, 4, 32, 32] (256/8=32)
    print(f"logvar shape: {logvar.shape}")
    
    # 重参数化采样
    z = reparameterize(mu, logvar)
    print(f"z shape: {z.shape}")
    
    # 解码
    x_recon = decoder(z)
    print(f"x_recon shape: {x_recon.shape}")  # [4, 3, 256, 256]
    
    # 计算损失(Stable Diffusion设置beta=1e-6)
    total_loss, recon_loss, kl_loss = vae_loss_function(
        x, x_recon, mu, logvar, beta=1e-6
    )
    
    print(f"\nLoss breakdown:")
    print(f"  Reconstruction loss: {recon_loss.item():.4f}")
    print(f"  KL divergence loss: {kl_loss.item():.4f}")
    print(f"  Total loss: {total_loss.item():.4f}")
    print(f"  KL/Recon ratio: {(kl_loss.item() / (recon_loss.item() + 1e-8)):.6f}")

代码面试要点:

  1. 重参数化技巧: 必须解释为什么需要这个技巧(梯度传播问题)
  2. logvar的使用: 解释数值稳定性和梯度优化优势
  3. 损失的维度: 确保batch维度正确处理
  4. beta系数: 解释Stable Diffusion中为何使用极小值

进阶追问与展望

1. 为什么不使用JS散度或其他距离度量?

指标KL散度JS散度Wasserstein距离
可微性✅ 闭式解✅ 可计算✅ (但需优化)
几何意义信息损失概率分布重叠最优传输代价
在VAE中KL项有闭式解,计算高效JS散度无闭式解,需近似可用于GAN,但不适合VAE
主要优势信息论解释清晰对称,避免梯度消失梯度更平滑

结论: KL散度在VAE中的选择主要是实用主义——高斯情况下有闭式解,计算高效。

2. KL权重β的变化效果

根据β-VAE论文(Higgins et al., 2017):

  • β = 1: 标准VAE,潜在空间有一定结构但可能欠解纠缠
  • β > 1: 强正则化,潜在空间更平滑但重建质量下降
  • β < 1: 弱正则化,重建更好但潜在空间可能不连续

Stable Diffusion选择极小β(1e-6)是一种任务特定的权衡:

  • VAE在SD中是"预训练模块",主要提供压缩而非生成
  • 生成质量由U-Net主导,因此VAE优先保证重建精度

3. 最新SOTA改进方向

3.1 VQ-VAE: Vector Quantized VAE

用离散codebook替代连续潜在空间,避免KL正则化问题:

$$z_q(x) = \text{argmin}_{z_e} \|z_e(x) - e_k\|$$

Stable Diffusion也实验过VQ-VAE,但最终选择KL版本。

3.2 NVAE: Hierarchical VAE

引入层次结构,用多级潜在变量捕获不同尺度的特征:

$$p_\theta(x, z_{1:L}) = p(z_L) \prod_{l=1}^{L} p_\theta(z_l | z_{l+1}) p_\theta(x | z_1)$$

3.3 Flow-based VAE

使用正则化流增强潜在空间的灵活性:

$$q_\phi(z|x) = f_L \circ f_{L-1} \circ \cdots \circ f_1(f_0(x))$$

其中每个 $f_l$ 是可逆变换,Jacobian行列式容易计算。

4. 边缘案例分析

面试追问: 如果编码器输出的logvar非常大(如100),会发生什么?

分析:

  • KL项: $\exp(\text{logvar})$ 可能溢出,导致梯度爆炸
  • 采样: $\sigma = \exp(0.5 \text{logvar})$ 会非常大,采样z离μ很远
  • 重建: 解码器难以重建远离训练分布的z

解决方案:

  1. 梯度裁剪: 在优化时限制logvar的范围
  2. logvar约束: 添加额外的正则化惩罚logvar的绝对值
  3. 数值缩放: 使用类似SD的rescaling技术

总结:面试回答框架

当被问到"Stable Diffusion中VAE的KL正则化"时,建议按此结构回答:

  1. 一句话总结: KL正则化是信息约束器,平衡重建质量与潜在空间结构
  2. 数学层面: 写出KL定义,推导高斯闭式解,解释各项含义
  3. 物理直觉: 用信息论和几何角度解释KL的作用
  4. 工程细节: 说明SD中β=1e-6的原因,解释rescaling机制
  5. 代码实现: 介绍reparameterization trick,手写KL损失函数
  6. 深度思考: 讨论非对称性、β-VAE、改进方向

关键亮点:

  • ✅ 数学推导严谨: 从定义到闭式解
  • ✅ 多角度解释: 信息论+几何+优化
  • ✅ 实践导向: 解释SD的特殊实现
  • ✅ 代码规范: 符合工业界标准

谢谢阅读~
关注"每天一个多模态知识点"公众号,回复"VAE_KL"即可下载本文markdown源码

本文由mdnice多平台发布

很久以前,就想写一篇关于SDL与DevSecOps的文章,但疏于实践一直未能动笔。想写的原因很简单,因为总是听到有人说SDL落后、DevSecOps相关技术更高超。一提到研发安全建设,不分研发模式都在赶时髦一样地说DevSecOps。从我的观察来看,不结合研发模式来做研发安全,都是不成功的。

在数字化浪潮的推动下,一些公司已经完全步入DevOps模式,有的则出现瀑布、敏捷或DevOps并存,且后者是居多的。所以如何在多种研发模式下进行有效的研发安全建设,成为一个必须解决的难题。经过近十年的实践,终于在探索解法上有一点点收获与经验,于是有了“深耕研发安全”这一系列文章。

本文是开篇,介绍在数字化转型过程中,研发安全的工作模式与方法的迭代升级。从研发安全体系建设的角度出发,总结出难度比较大的三个典型问题。

01 市场侧的快速交付需求

市场需求不断变化,商机一瞬即逝。产品为实现抢占市场的需求,要求背后的研发和交付团队能够快速响应,对于安全团队来讲也是一样的。但纵观整个公司来看,有的业务严格按照瀑布开发计划执行、研发周期很长,有的业务又没有快速部署的需求,于是就出现了多种开发模式并存的状态:

图片

(图片创意来自互联网)

三种主要模式的区别如上图所示,表面上在于研发阶段所占时长、顺序的不一样,往里看还有研发、运维团队工作模式、研发工具的差异,这给安全工作带来了很大的挑战。

02 技术发展带来的多样化

其次是技术发展带来一些变化,很多年前在说PHP是最好的语言,现在很多大型的业务网站其实都还是Java,不过Go的应用也非常广泛。公司内部的研发技术栈,基本符合外部的趋势。但除了这三个外,主流语言还有C、C++、C#、Python,内部使用的语言还有ruby、rust、swift、Visual Basic...

图片

(图片创意来自互联网)

于是就出现了第二个比较大的挑战,表面看是研发语言种类很多,往里看则是开发框架、人员技能的差异。相关的安全工作开展,如安全组件、编码安全规范、静态代码扫描工具、开源组件安全管理、安全人员能力...也随之变得复杂。

03 研发基础设施的不统一

第三是研发基础设施没有完全统一,比如由于历史原因产品线各自管理代码和发布系统,公司层面缺少强有力的配置管理团队做全局管控...就会在出现各种代码管理工具、各类构建和发布系统。表面上看是研发工具多种多样,往里看则是研发流程(CI&CD)的不一样。

图片

对于安全测试工具嵌入不同的流程,同样带来了巨大的麻烦。

上述的每一个问题,都是安全团队遇到的痛点。当这些点都集中在一块儿时,困难好比是一个类似乘积的关系,瞬间被放大了很多倍。感觉遇到了一种混沌的状态,安全工作没有了抓手,甚至是无从下手。

图片

本文首发于微信公众号:我的安全视界观

2026年,AI编程工具已经非常成熟了。市面上这么多AI编程工具,哪个最好用?

本文选取了当前最具代表性的六款工具:Claude CodeAiderCursorGitHub CopilotMetaGPT 以及 OpenHands,从技术特性、优缺点及部署门槛进行客观对比。

Claude Code

Anthropic 于2025年推出了 Claude Code,这是一款基于命令行的编程智能体工具。它不同于网页版的对话框,而是直接运行在终端中,能够深度理解本地项目结构。最出名的 AI 编程助手,很贵,但一分钱一分货,不得不说它很好用。

image.png

通过终端直接通过自然语言操作。它不仅能写代码,还能自主运行测试、解释复杂的架构、甚至执行终端命令来修复错误。其背后依托的是推理能力极强的 Claude 3.5/3.7 Sonnet 模型。

优势

  • 推理能力极强:在处理复杂的逻辑重构和长代码理解上,目前处于行业顶尖水平。
  • 自主性:可以代理执行 git commit、运行 shell 命令,具备初级的“无人值守”能力。
  • 大上下文:能够一次性读取成百上千个文件,对大型遗留项目的理解力优于竞品。

劣势

  • 成本高昂:按 Token 消耗计费,且 Claude 模型单价较高,深度使用时账单压力大。
  • 交互门槛:纯命令行界面,对不熟悉终端的开发者不友好。

需要环境Node.js (v18+)

安装方法

curl -fsSL https://claude.ai/install.sh

claude
# You'll be prompted to log in on first use

/login
# Follow the prompts to log in with your account

Cursor

Cursor 目前是体验最流畅的 AI 代码编辑器。它本质上是 VS Code 的一个分支(Fork),在底层深度集成了 AI 能力,而非仅仅作为一个插件存在。

image.png

建立本地代码索引(RAG技术),让 AI 能够实时感知整个项目的上下文。提供 Tab 键多行补全(Copilot++)和 Composer(多文件编辑)功能。

优势

  • 开箱即用:界面与操作习惯与 VS Code 几乎一致,迁移成本极低。
  • 体验流畅:代码补全速度极快,预测准确率高。
  • 多模型选择:允许用户在 Claude 3.5、GPT-4o 等模型间切换。

劣势

  • 资源占用高:索引过程比较吃内存和 CPU,低配电脑运行大型项目会卡顿。
  • 隐私顾虑:代码需要上传至 Cursor 服务器进行处理(虽有隐私模式,但企业合规部门通常较敏感)。

安装方法:访问 Cursor 官网 下载对应系统的安装包,双击安装即可。

Aider

Aider 是目前开源界最受推崇的命令行 AI 编程助手,以其对 Git 的深度集成而闻名。

image.png

作为一个命令行工具,它与 Git 仓库深度绑定。Aider 修改代码后会自动进行 Git 提交,并生成清晰的 Commit Message。它支持连接几乎所有主流大模型(OpenAI, Anthropic, DeepSeek 等)。

优势

  • Git 深度集成:能清晰地管理代码变更历史,方便回滚。
  • 模型灵活:可以使用 DeepSeek 等高性价比模型,大幅降低使用成本。
  • 文件操作精准:专门针对代码修改进行了优化,很少出现“改错位置”的情况。

劣势

  • 无图形界面:必须习惯在终端与 AI 对话。
  • 上下文管理:相比 Claude Code,在处理超大型项目时需要手动添加文件到聊天上下文(/add 命令)。

需要环境Python (v3.8+), Git

image.png

安装方法

python -m pip install aider-install
aider-install

# Change directory into your codebase
cd /to/your/project

# DeepSeek
aider --model deepseek --api-key deepseek=<key>

# Claude 3.7 Sonnet
aider --model sonnet --api-key anthropic=<key>

# o3-mini
aider --model o3-mini --api-key openai=<key>

GitHub Copilot

作为行业的先行者,Copilot 依然是目前覆盖率最广的工具,主打“辅助”而非“替代”。

image.png

作为 IDE 插件运行,通过分析光标前后的代码提供实时补全。除此之外,Copilot Chat 提供侧边栏问答功能。

优势

  • 生态完善:支持 Visual Studio, VS Code, JetBrains, Vim 等几乎所有编辑器。
  • 企业级合规:拥有最完善的版权保护机制和企业管理后台,是大型企业的首选。
  • 低延迟:补全响应速度极快,干扰感低。

劣势

  • 能力受限:主要通过补全和对话辅助,缺乏跨文件自动重构、自动运行测试等 Agent 能力。
  • 模型更新较慢:相比 Cursor 或 Aider 能第一时间接入最新模型,Copilot 的模型迭代相对保守。

需要环境(依赖 IDE)

安装方法:在 IDE 的插件市场搜索 "GitHub Copilot" 安装并登录 GitHub 账号。

MetaGPT

MetaGPT 与上述工具完全不同,它不是一个结对编程助手,而是一个多智能体框架。

image.png

模拟一家软件公司。用户输入一句话需求(如“写一个贪吃蛇游戏”),内部的多个 Agent 会分别扮演产品经理、架构师、项目经理和工程师。它们会互相交互,输出从 PRD 文档、接口设计到最终代码的全套产物。

优势

  • 全流程生成:擅长从 0 到 1 生成完整的项目结构和文档。
  • 角色扮演:通过不同角色的互相制约(Review),减少逻辑漏洞。

劣势

  • 不适合日常开发:如果你只是想修一个 Bug 或加一个功能,MetaGPT 显得过于臃肿。
  • 成本与稳定性:生成一个项目需要消耗大量 Token,且多轮对话容易在后期出现上下文丢失。

需要环境Python (v3.9+)

  • 依然可以用 ServBay 来安装和管理 Python 环境。

安装方法

pip install metagpt
# 初始化配置
metagpt --init-config

OpenHands (原 OpenDevin)

OpenHands 旨在打造一个开源的全自主 AI 软件工程师,对标 Devin。

image.png

运行在一个安全的沙盒(Docker)环境中。它拥有浏览器、终端和代码编辑器。它可以像人类一样去浏览网页查文档、运行代码报错后自己看日志修 Bug。

优势

  • 全能性:理论上可以处理任何人类工程师能处理的任务,包括配置环境、部署应用。
  • 可视化交互:提供 Web 界面,用户可以看着 AI 操作终端和浏览器。
  • 安全性:所有操作都在 Docker 容器内,不会破坏宿主机系统。

劣势

  • 资源消耗巨大:运行慢,且对本地硬件资源要求高。
  • 部署复杂:依赖 Docker,配置过程相对繁琐。

需要环境Docker (必须), Python

安装方法

# 需先安装 Docker 并运行
pip install openhands
openhands # 启动服务

工具横向对比表

特性维度GitHub CopilotCursorClaude CodeAiderMetaGPTOpenHands
工具形态IDE 插件独立 IDE命令行工具 (CLI)命令行工具 (CLI)Python 框架容器化服务
核心依赖IDE (VSCode等)无 (独立安装)Node.jsPython, GitPythonDocker
主要定位实时代码补全沉浸式 AI 编程终端自动编程Git 协作编程软件公司模拟自主智能体
模型支持GPT 系列 (官方)Claude/GPT/自有Claude 系列任意模型 (BYOK)任意模型任意模型
自主程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
上手难度
计费模式订阅制订阅制按量付费 (API)免费 (需自备Key)免费 (需自备Key)免费 (需自备Key)
最佳场景企业日常辅助、补全个人开发、重构批量修改、运维脚本极客开发、Git流生成项目Demo复杂任务复现

总结建议

  • 日常干活、追求效率:首选 Cursor。它在现阶段提供了最好的人机协作体验。
  • 极客、命令行重度用户:尝试 AiderClaude Code。Aider 配合 DeepSeek 模型性价比极高;Claude Code 适合处理极难的逻辑问题。
  • 企业环境、安全第一GitHub Copilot 依然是最稳妥的选择。
  • 学术研究、实验性项目MetaGPTOpenHands 代表了未来的方向,但在实际生产环境中使用尚需谨慎。

模力工场新鲜事

  • 想用一个下午快速摸清一个领域,并产出一份条理清晰、信息量丰富的深度内容?本周模力工场带你体验 “AI 增效流水线:从信息到作品的智能生产工作流”。从智能阅读提炼(语鲸)、一键生成研报(AI 快研侠),到跨平台记忆管理(MemOS-MindDock),再到自动视觉设计,这条流水线覆盖“读、写、研、记、设计”全流程,助你将碎片信息快速整合为结构化的知识作品。例如,若你对近期热议的 Clawdbot 等 AI 助手产品感兴趣,不妨以此为主题,用这套工作流实践一番。点击进入模力工场首页,查看顶部专题横幅,扫码添加模力小 A,获取完整工具链与实操指引。

030 周上榜应用精选(附用户热评)

模力工场第 030 周 AI 应用榜来袭!本周共有 32 款应用上架,榜单完全由用户真实使用、测评与讨论热度驱动。我们从社区声量最高的应用中精选出十款,并透过用户真实评论,为你解读榜单背后的产品逻辑与行业风向。

创作平民化:人人都能成为内容创作者

  • 随变:潮人必备 AI 创作神器,让灵感瞬间变潮流短片!

”玩了几天随变,感觉有点像简洁版抖音…但 AI 创作出来的视频,如‘创作一条刀马刀马的舞蹈片段’它会理解为元素中有刀有马,BGM 也毫不相干…这显然是开盲盒,会消耗创作者热情。希望引入更多‘悦己’的功能。”【用户热评|@MATTHEW】

  • PixVerse:秒出电影感视频,视觉叙事交给 AI。

  • 小云雀:一句话生成爆款,创作门槛降至零。

  • WHEE:一站式视觉工坊,生图改图扩图,创意无限延伸。

  • 唱鸭:零基础玩音乐,AI 帮你谱写生活旋律。

学习力升级:AI 正在重塑教辅软件

  • 千问智学:全科 AI 辅导,教材全覆盖,答疑效率翻倍。

”千问智学高度契合我心中对答疑辅导类学习软件的期待。功能清晰划分为学习智能体、提分助手、宝藏资料、职业考试几大板块,每个分类还结合适用年龄、所学专业、所在地区等不同维度,打造了针对性的内容与服务…综合体验可以给到 9 分的高分。”【用户热评|@Abin】

  • 豆包爱学: 随身 AI 家教,拍题秒出思路,学习难题不再怕。

智能自动化:从被动回答到主动执行

  • Atoms:多 AI 团队协作,想法闪电变产品原型。

”用 Atoms 搭了一个族谱显示的网站...最戳我的是它的层级数据可视化功能,族谱的家族分支、辈分脉络展示得一目了然,不用自己折腾结构设计。而且全程打字输入需求就行,不用写一行代码,平台会自动匹配开发需求,内置多个角色也比较好用,做出来的族谱网站的展示效果整体合预期(有一些样式生成的没处理好,显示会重叠)。整体来说对新手很友好,搭建网站的核心需求都能完美满足,小细节的不足完全不影响基础使用,作为零代码工具来说很靠谱了。“【用户热评|@墨鱼罐头】

  • offer快 📍北京:AI 求职分身,智能匹配+自动投递,轻松拿下好工作。

心理疗愈:不仅是应用,更是思考伴侣

  • MetaSight 元见 📍杭州:命运 AI 投射仪,换个视角看清人生路径。

”我其实很好奇这个领域的 AI 应用能发展到什么程度。之前试用时,我只是输入了自己当前的工作状态、心情和年龄,系统就帮我推算出了未来的发展方向和行动建议…如果这类应用未来能结合 IoT 硬件,可能会真正引爆市场。目前应用面向的用户群中包含不少中老年人,他们对这类能根据现状推理出下一步计划与发展方向的功能,需求其实非常迫切。”【用户热评|@.】

榜单之外但有趣的应用

应用名称:扣子(2.0版本)

关键词:AI 职场助手|流程自动化|智能办公

模力小 A 推荐:专为职场人打造的智能效率伙伴,能帮你自动处理会议纪要、邮件撰写、日程安排等重复工作,让 AI 真正成为你的“数字同事”。

应用名称:Vidu AI MV

关键词:一键成片|AI MV 生成|影音创作

模力小 A 推荐:只需上传图片和音乐,即可自动生成拥有专业转场、节奏卡点和电影级质感的音乐短片,让普通人也能轻松打造专属 MV。

本周上榜应用趋势解读

本周上榜的一批 AI 应用呈现出几个非常鲜明的趋势:创作力提升、学习力强化、智能自动化与心理疗愈并行发展。

在创意生产与多媒体内容创作方向,我们看到像随变、PixVerse、小云雀、WHEE、唱鸭这样的应用迅速聚焦 AI 驱动的视觉与音频内容生成,从“一句话生成爆款内容”、秒级视频产出,到图像改图、一站式创作体验,AI 正在让个人创作者从繁琐操作中解放出来,把灵感瞬间转为可传播的成果。这与行业趋势一致:AI 正在大规模重塑创意产业和内容生产流程,创作者不再受制于传统软件约束,而能借助 AI 助力快速迭代与表达创意。

在教育与知识服务方向,豆包爱学、千问智学等产品体现了 AI 在学习辅导领域的深化应用,它们通过拍题讲解、教材覆盖的智能辅导模式,正在将 AI 从“工具助手”升级到“学习伴侣”,这与全球教育领域推动 AI 个性化辅导、提升学习效率的大趋势不谋而合。

此外,AI Agent 与自动化服务型工具(如 Atoms、offer 快、MetaSight)正在形成一股新潮流。Atoms 体现了多智能体协作快速将想法变成可用产品的能力;offer 快则将 AI 直接介入求职流程中,实现岗位筛选、沟通跟进与自动申请;MetaSight 则尝试把 AI 带入命理解读与人生洞察场景,让智能体具备不仅执行任务、还促发用户自我思考的能力。

综合来看,本周上榜的 AI 应用不仅覆盖了内容创作、学习辅导、个性化洞察和流程自动化等核心领域,还共同凸显了一个核心趋势:AI 正在从“简单生成”向“深度交互与高效执行”转变,让用户的生产力、学习效率和生活智能都进入一个新阶段。

One more thing,

模力工场将亮相 OceanBase 社区嘉年华!诚邀您加入我们的上海现场展位。作为 OceanBase 合作的创新社区,模力工场将于 1 月 31 日 登陆上海社区嘉年华,并拥有专属展位。这不仅是一次技术交流——我们更希望和你一起,在现场用 AI Coding 展现创造力、在开放麦分享你的项目故事、与行业先锋面对面切磋、在开源市集交换灵感。我们为你预留了专属席位,期待与你共同呈现:当开源精神遇上 AI 创造力,能碰撞出多少令人惊艳的可能。立即报名,锁定与数百位技术同行深度连接的一天!

随着人工智能在产业场景中的持续深入,单一的大模型调用已难以覆盖复杂业务流程。当前工程实践中,智能体逐渐被视为一种以大模型为核心、通过系统化编排实现任务闭环的应用形态。

在这一范式下,智能体并非模型能力的简单外延,而是一个由数据(Data)、工具(Tools)与规则(Rules)共同构成的协同系统。三者在认知、执行与控制层面各司其职,形成可复用、可治理的工程结构。


一、系统构成要素的职责划分

1. 数据(Data):可检索的外部知识与状态记忆

数据在智能体系统中主要承担“上下文补充”与“长期记忆”的角色。通过检索增强生成(RAG)等机制,数据以结构化或向量化形式被实时调用,为模型提供领域知识、业务状态与历史记录。

其核心价值不在于规模,而在于相关性、时效性与可控性

2. 工具(Tools):可被模型触发的执行接口

工具是智能体与外部系统交互的唯一通道,涵盖搜索服务、计算模块、业务 API 及内部系统能力。
通过明确的接口定义与参数约束,工具使模型从语言生成扩展为具备操作能力的执行单元。

3. 规则(Rules):行为边界与流程约束机制

规则用于限定智能体的行为范围、决策路径与输出形式。工程上,规则通常以流程控制、权限校验、条件分支及结构化 Schema 的形式存在,用于保障系统的稳定性与合规性。


二、协同机制:从感知到执行的闭环流程


在实际运行中,数据、工具与规则并非线性调用,而是通过多轮反馈形成闭环。

1. 规则驱动的任务对齐与数据筛选

任务启动后,规则首先明确目标与边界,随后触发与当前任务最相关的数据检索,避免无关信息干扰决策。

2. 数据支撑下的推理与工具选择

模型基于检索结果进行推理,并在规则允许的范围内选择合适的工具执行操作,实现从“理解”到“行动”的转化。

3. 工具反馈后的规则校验与流程推进

工具执行结果被回传系统,由规则判断是否进入下一流程、触发异常处理或执行补偿逻辑,从而形成可控的执行闭环。


三、工程落地中的关键挑战

1. 协议化接口与结构化输出

为降低不确定性,工具调用与数据返回需遵循明确的接口协议与 Schema 定义,这是多步骤稳定执行的前提。

2. 规则的硬约束与软引导并存

在高风险场景中,规则以代码形式进行强约束;在开放场景中,则通过提示与策略进行引导,形成分层治理结构。

3. 数据的动态回流与持续更新

工具执行过程中产生的新数据需及时进入可检索体系,构建持续演进的记忆闭环。


四、结论:从模型能力到系统能力


智能体系统的核心不在于模型规模,而在于数据可用性、工具可调用性与规则可执行性之间的协同程度。

在行业实践中可以观察到,真正具备生产价值的智能体,往往表现为一个以规则保障确定性、以工具扩展行动力、以数据增强认知深度的系统工程。这种结构性能力,决定了智能体在垂直业务中的可复制性与可扩展性。

image-20260127163313212

今天刷 Twitter 的时候,发现时间线被一个叫 ClawdBot 的东西刷屏了。

点进去一看,是个开源的 AI 助手框架。能干的事情挺多:通过 Telegram/WhatsApp 远程控制电脑、自动处理邮件、定时跑任务、甚至能帮你和 4S 店砍价(有个老外说靠它省了 4200 美元,虽然我觉得有点玄学)。

手上正好有台吃灰的 VPS ,干嘛不试试?

结果这一试,踩了一晚上的坑。官方文档写得比较散,很多细节要自己摸索。顺手把过程记下来,给想折腾的朋友省点时间。

image-20260127155609156


ClawdBot 是什么

简单说,ClawdBot 是一个本地运行的 AI 助手网关

它的核心是一个 Gateway 进程,负责:

  • 连接各种聊天平台( Telegram 、WhatsApp 、Discord 、iMessage 等)
  • 调用 AI 模型( Claude 、GPT 、本地模型都行)
  • 执行系统命令、读写文件、控制浏览器
  • 管理定时任务和自动化流程

你可以把它理解成一个7x24 小时在线的 AI 员工。它有记忆(知道你之前聊过什么),有手脚(能操作你的电脑),还会主动干活(定时任务、邮件监控)。

根据 Mashable 的报道,这东西火到 Mac mini 都卖断货了——很多人专门买一台小主机放家里,就为了跑这个。

不过我觉得没必要这么激进。一台便宜的云服务器就够了,一个月几十块钱,玩坏了也不心疼。


它能干什么

搭完之后我自己用了一下,体验确实不错:

  • 随时随地发消息:手机上给 Bot 发消息,秒回。出门在外也能远程操作服务器
  • 查服务器状态:让它跑个 htop 或者看 Docker 容器,截图发过来
  • 定时任务:每天早上 7 点发一份服务器健康报告
  • 写代码调试:把报错信息发给它,它能直接帮你改文件

网上还有人玩得更花:

邮件自动化:每 15 分钟检查一次收件箱,垃圾邮件自动归档,重要邮件立刻推送摘要到手机,还能用你的口吻起草回复。

笔记整理:连接 Obsidian ,自动更新每日笔记,从会议记录里提取待办事项,生成每周回顾。

睡觉时写代码:睡前把一个 Bug 丢给它,它会持续调试、提交、测试,早上起来 PR 就准备好了。

智能家居控制:有人在沙发上看电视,用手机让它帮忙调灯光、查天气、设闹钟。

当然,这些高级玩法需要配置额外的 Skills 和集成。本文先讲基础安装,能聊天、能执行命令就算成功。

image-20260127155715044

image-20260127155723447

image-20260127155745564


准备工作

你需要:

项目 说明
一台服务器 云服务器(我用的 Ubuntu 24.04 )、Mac mini 、旧电脑、树莓派都行,最好是国外的,不然网络环境都有的折腾了!
Telegram 账号 用来创建 Bot
Claude/GPT API 官方的或者中转站都行,后面会细说

关于设备选择

云服务器(推荐新手)

优点:便宜(最低几十块/月)、玩坏了不心疼、7x24 在线
缺点:需要一点 Linux 基础

Mac mini

优点:性能好、功耗低、能跑 macOS 专属功能( iMessage 等)
缺点:贵( 4000+ 起步)、权限太高有安全风险

我的建议

新手先用 VPS 试水。等熟悉了再考虑要不要买专门的设备。如果真要用 Mac mini ,别用日常工作的那台——万一配置出问题,或者 Key 泄露了,后果可能很严重。


安装方式

ClawdBot 支持多种安装方式,我按推荐程度排序:

方式一:一键安装脚本(推荐)

官方提供的快速安装命令,会自动处理依赖和权限问题:

# Linux / macOS
curl -fsSL https://get.clawd.bot | bash

# 安装完成后运行引导向导
clawdbot onboard --install-daemon

这个脚本会自动检测系统、安装 Node.js 22+、处理 npm 权限、全局安装 clawdbot 。

方式二:手动 npm 安装

如果你已经有 Node.js 22+:

npm install -g clawdbot@latest


详细安装步骤

下面用手动方式演示。虽然一键脚本更方便,但手动装能让你更清楚每一步在干嘛,出问题也好排查。

第一步:安装 Node.js 22+

ClawdBot 要求 Node.js 22 以上。Ubuntu 自带的版本太老,得手动装。

# 添加 NodeSource 仓库
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -

# 安装
apt-get install -y nodejs

# 验证
node -v
# 输出 v22.x.x 就对了

image-20260127160000295

踩坑 1:别直接 apt install nodejs,那样装的是老版本(通常 v12 或 v18 ),后面会报各种兼容性错误。

第二步:安装 ClawdBot

npm install -g clawdbot@latest

装完验证:

clawdbot --version

image-20260127160041920

踩坑 2:如果报 EACCES 权限错误,说明 npm 全局目录权限有问题。解决方法:

mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

第三步:创建 Telegram Bot

打开 Telegram ,搜索 @BotFather,发送 /newbot。这里好像必须新建!

按提示设置:

  1. 给 Bot 起个名字(显示名称)
  2. 设置用户名(必须以 bot 结尾,比如 my_clawd_bot

最后会给你一串 Token:

1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ1234567890

存好这个 Token,后面要用。

image-20260127160128795

第四步:准备 API

这一步最容易踩坑。

用官方 API

  1. console.anthropic.com 注册
  2. 创建 API Key (以 sk-ant- 开头)
  3. 充值一点余额

用中转站 API

如果用中转站,注意三点:

  • 必须支持 OpenAI 兼容格式
  • 必须支持 工具调用( function calling )
  • 确认 没有分组限制

踩坑 3:这里我是直接用的 CLI Proxy API 这个开源项目中转的 API,选的 gemini-3-flash 模型,感觉非常舒畅!

第五步:写配置文件

创建配置目录:

mkdir -p ~/.clawdbot
nano ~/.clawdbot/clawdbot.json

根据你的 API 类型选配置模板:

模板 A:Anthropic 官方 API

{
  "gateway": {
    "mode": "local",
    "bind": "loopback",
    "port": 18789
  },
  "env": {
    "ANTHROPIC_API_KEY": "sk-ant-你的密钥"
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-sonnet-4-5-20261022"
      }
    }
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "你的 Bot Token",
      "dmPolicy": "pairing"
    }
  }
}

模板 B:OpenAI 兼容的中转站

{
  "gateway": {
    "mode": "local",
    "bind": "loopback",
    "port": 18789
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "gemini/gemini-3-flash"
      },
	  "elevatedDefault": "full" ,
      "workspace": "/wangwang",
      "compaction": {
        "mode": "safeguard"
      },
      "maxConcurrent": 4,
      "subagents": {
        "maxConcurrent": 8
      }
    }
  },
  "models": {
    "mode": "merge",
    "providers": {
      "gemini": {
        "baseUrl": "https://你的中转站 API/v1",
        "apiKey": "test",
        "api": "openai-completions",
        "models": [
          {
            "id": "gemini-3-flash",
            "name": "gemini-3-flash"
          }
        ]
      }
    }
  },
  "channels": {
    "telegram": {
      "botToken": "你的 TG Token"
    }
  },
  "plugins": {
    "entries": {
      "telegram": {
        "enabled": true
      }
    }
  }
}


踩坑 4api 字段必须填 openai-completions。我一开始填的 openai-chat,死活启动不了。

踩坑 5models 数组不能省,不然报错说缺少必填项。注意 agents 中也有配置模型名,别忘了改!

第六步:启动测试

clawdbot gateway --verbose

看到这两行就成功了:

[gateway] listening on ws://127.0.0.1:18789
[telegram] [default] starting provider (@你的 Bot 名字)

image-20260127160536261

第七步:配对

第一次给 Bot 发消息,它会回复配对码:

Pairing code: X9MKTQ2P
Your Telegram user id: 123456789

在服务器上执行:

clawdbot pairing approve telegram X9MKTQ2P

配对完成后,只有你的账号能和 Bot 对话,别人发消息它不会理。

记下你的 Telegram User ID,后面设置权限白名单要用。

后续有啥需求就直接 tg 对话,让 AI 自行配置就行了!比如我让它帮我集成了 exa 的搜索功能!

image-20260127160903264


设置开机自启

nohup 跑的话,SSH 一断就挂了。上 systemd:

cat > /etc/systemd/system/clawdbot.service << 'EOF'
[Unit]
Description=ClawdBot Gateway
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/clawdbot gateway --verbose
Restart=always
RestartSec=5
Environment=HOME=/root

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable clawdbot
systemctl start clawdbot

这样就完事了。开机自动启动,挂了 5 秒后自动重启。


日常维护

几个常用命令:

# 看运行状态
systemctl status clawdbot

# 看实时日志
journalctl -u clawdbot -f

# 重启
systemctl restart clawdbot

# 健康检查
clawdbot doctor

# 全面状态
clawdbot status --all


进阶:命令白名单

如果想让某些命令自动执行,不用每次批准:

# 允许 docker 命令
clawdbot approvals allowlist add --agent "*" "docker *"

# 允许 systemctl
clawdbot approvals allowlist add --agent "*" "systemctl *"

# 允许 /usr/bin 下的程序
clawdbot approvals allowlist add --agent "*" "/usr/bin/*"

# 查看当前白名单
clawdbot approvals allowlist list


进阶:定时任务

ClawdBot 内置 Cron 功能。比如每天早上 7 点发送服务器状态:

clawdbot cron add --schedule "0 7 * * *" \
  --timezone "Asia/Shanghai" \
  --message "检查服务器状态,给我发个简报" \
  --deliver telegram \
  --to "你的 TG 用户 ID"

或者写进配置文件:

{
  "cron": {
    "jobs": [
      {
        "id": "daily-report",
        "schedule": {
          "cron": "0 7 * * *",
          "timezone": "Asia/Shanghai"
        },
        "sessionTarget": "isolated",
        "payload": {
          "agentTurn": {
            "message": "检查服务器状态,生成简报"
          }
        },
        "deliver": {
          "channel": "telegram",
          "to": "你的 TG 用户 ID"
        }
      }
    ]
  }
}


常见问题

clawdbot: command not found

npm PATH 问题。确认全局目录在 PATH 里:

npm config get prefix
echo 'export PATH=$(npm config get prefix)/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

端口被占用

默认端口 18789 冲突了:

lsof -i :18789  # 看谁在用

clawdbot gateway --port 18790 --verbose  # 换个端口

Bot 收到消息但不回复

按顺序检查:

  1. Gateway 在不在跑:clawdbot status
  2. 配对了没:clawdbot pairing list telegram
  3. API 还有没有额度
  4. 看日志:journalctl -u clawdbot -f

all models failed

API 配置问题:

  1. Key 对不对
  2. baseUrl 格式对不对(结尾有没有 /v1
  3. model id 写对没
  4. 跑一下 clawdbot doctor

工具调用失败

你的 API 不支持 function calling 。这种情况 Bot 能聊天,但执行命令用不了。换一个支持工具调用的 API 。


完整配置示例

一个功能完整的配置,开箱即用:

{
  "gateway": {
    "mode": "local",
    "bind": "loopback",
    "port": 18789
  },
  "agents": {
    "defaults": {
      "model": {
        "primary": "openai-compat/claude-sonnet-4-5-20261022",
        "fallback": ["openai-compat/claude-haiku-3-5-20241022"]
      },
      "elevatedDefault": "full",
      "thinking": "medium"
    }
  },
  "models": {
    "mode": "merge",
    "providers": {
      "openai-compat": {
        "baseUrl": "https://你的 API 地址/v1",
        "apiKey": "你的密钥",
        "api": "openai-completions",
        "models": [
          {
            "id": "claude-sonnet-4-5-20261022",
            "name": "Claude Sonnet 4.5"
          },
          {
            "id": "claude-haiku-3-5-20241022",
            "name": "Claude Haiku 3.5"
          }
        ]
      }
    }
  },
  "tools": {
    "exec": {
      "backgroundMs": 10000,
      "timeoutSec": 1800,
      "cleanupMs": 1800000,
      "notifyOnExit": true
    },
    "elevated": {
      "enabled": true,
      "allowFrom": {
        "telegram": ["你的 TG 用户 ID"]
      }
    },
    "allow": ["exec", "process", "read", "write", "edit", "web_search", "web_fetch", "cron"]
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "你的 Bot Token",
      "dmPolicy": "pairing",
      "allowFrom": ["你的 TG 用户 ID"],
      "groupPolicy": "disabled"
    }
  },
  "cron": {
    "jobs": []
  }
}

配置亮点

  • fallback:主模型挂了自动切备用
  • thinking: medium:启用中等深度思考
  • groupPolicy: disabled:只响应私聊,不进群
  • 双重白名单:elevated 和 channels 都设了 allowFrom


总结

整个过程折腾了大半天,大部分时间花在排查配置格式上。

几个关键点:

  1. Node.js 版本:必须 22 以上
  2. API 要通用:别用有分组限制的 Key
  3. 配置格式严格api 字段、models 数组这些容易出错
  4. 用 systemd 管理:别用 nohup
  5. 安全第一:白名单必须设,日志定期看

搭完之后确实方便。出门在外随时能跟服务器交互,定时任务也不用自己写脚本了。

但说实话,这东西更适合有一定技术基础的人。如果只是想聊天,直接用 Claude 官网就够了。折腾 ClawdBot ,图的是「可控」和「自动化」。

antigravity 的 gemini 模型,不管是 pro 还是 flash 。简直就离谱了。

calude code 也太好用了,几秒钟就能准确定位答案。gemini 一开始还行现在越来越拉胯,calude 额度现在一限制就是几天,太离谱了。

  • 无限循环
  • 海量 token 生成。也不知道在干嘛。

吐槽完毕,请问大佬们 calude code 如何购买最划算,是订阅 cursor 么,还是如何使用 calude code 性价比最好呢

家里的母缅因发情了,就打算借一只公猫来配种,于是找到了这只可爱又霸气的银虎斑缅因。虽然最后没配上,但这只猫真的很乖,于是拍了几张照片留作纪念。

银虎斑缅因猫喝水]
银虎斑缅因猫在洗衣机旁
银虎斑缅因猫趴在地上
银虎斑缅因猫站在电脑桌上
银虎斑缅因猫站在玻璃前半明半暗

现在,已经被他的主人接回家割蛋了。

既然没有缘分,我们家的母猫也要准备割掉了。下面这张是我们家其中一只母猫发情的样子。

棕虎斑缅因猫发情