普通视图

发现新文章,点击刷新页面。
昨天以前Wulu's Blog

2025 读书总结

2026年3月1日 19:56

去年只看完了一本书。

《你当像鸟飞往你的山》

作者:塔拉·韦斯特弗
译者:任爱红
出版社:南海出版公司

在看这本书之前,我陆续听说过,但一直没什么兴趣去了解。在我印象中这是一本"励志"书,而我并不喜欢"励志"或"成功学"类的书籍。当时我正在看一些工具书,读得艰难有些疲惫,就想换本有故事性的书来放松一下。

于是,这本书陪我度过了多个通勤和午休前的时间。读完后我发现,虽然作者的故事确实很励志,但这本书想表达的不止于此——它给我带来的更多是关于个体与家庭、个人与信仰关系的思考。

书中最让我印象深刻的,是作者在"回归家庭"和"保持自我"之间的挣扎。也许这两者并非完全对立,但她极端的成长经历把这种冲突逼到了非此即彼的境地。更难的是,"回归"这个选项有着真实的诱惑:回到家庭,回到宗教,仿佛就可以不再烦恼。放弃自己的主体性,不用再为自己负责,上帝会解决一切。那种安稳,并不是没有吸引力的。

这让我想到一个我一直在思考的问题。这种用归属感换取安全感的冲动,在宗教信仰里同样存在——信仰一个至高无上的力量,仿佛生活的问题都能得到解答,仿佛你也能借此拥有某种庇护。这种对外部至高力量的依赖,与作者面临的选择很相似:是选择依赖某个更大的存在来承担自己,还是承担独立思考的重负,以及随之而来的孤独?作者的选择给出了她的答案。

总的来说,我觉得这本书有一种温柔的治愈力量。它没有简单地批判或赞美她的家人,也没有简单地美化自己的选择,而是以真诚的探索和思考,展现了一个人如何在复杂的关系网络中寻找自己的位置。

树莓派5 优化与踩坑

2026年1月25日 20:24

本文记录我使用树莓派 5 过程的经验,即是笔记,也是分享。

优化:增大 swap 分区

我在我的树莓派 5 4GB 上跑 Docker,部署了多个服务。当加入 Nextcloud 后,系统开始出现明显卡顿,响应速度大幅下降。输入 top 命令发现,内存几乎用满,swap 更是直接 100% 占用:

MiB Mem :   4049.9 total,    146.7 free,   3369.8 used,    789.0 buff/c
MiB Swap:    200.0 total,      0.0 free,    200.0 used.    680.1 avail

这时我才发现树莓派 5 的 Raspberry Pi OS (Bookworm) 默认仅配置了 200MB swap。这个保守的设置可能是为了照顾使用 SD 卡的用户——毕竟频繁的 swap 读写会严重缩短 SD 卡寿命。

但既然树莓派 5 已经配备了 PCIe 接口,官方也推出了专用的 M.2 HAT+ 和 SSD 套件,如果你和我一样使用 SSD 作为系统盘,完全可以将 swap 调大,充分发挥 SSD 的读写性能和耐用性优势。

  1. 打开配置文件:

    sudo nano /etc/dphys-swapfile
  2. 修改 CONF_SWAPSIZE,我的树莓派系统是安装在 SSD 上的,所以 swap 调大点没关系。如果你用的是 SD 卡,建议设置小点,不要超过 1GB,因为频繁的 swap 读写会大幅缩短 SD 卡寿命。

    CONF_SWAPSIZE=4096  

    为了设置超过 2GB 的 swap, 还需要修改 CONF_MAXSWAP 调大限制,可以和 CONF_SWAPSIZE 一致,也可以设置的更大一些方便后续调整。

    CONF_MAXSWAP=4096
  3. 重启 swap 服务

    sudo /etc/init.d/dphys-swapfile restart
  4. 验证

    free -h

优化:开启 zram

在 AI 的建议下,我还开启了 zram。zram 是一个在内存中创建压缩交换空间的技术。简单来说,它会将不常用的内存页压缩后存储在内存里,通常能达到 2-3 倍的压缩比。对于树莓派这种内存有限的设备来说,zram 是个非常实用的优化手段。

  1. 安装

    sudo apt update
    sudo apt install zram-tools
  2. 验证

    cat /proc/swaps

    可以看到

    Filename                                Type            Size            Used            Priority
    /dev/zram0                              partition       262128          257344          100
    /var/swap                               file            4194288         697648          -2

避坑:树莓派 5 PCIe 排线干扰

如果你使用树莓派 5 搭配 树莓派官方 M.2 套件(HAT+),建议不要把树莓派直接叠放在路由器上。

之前有段时间,我发现树莓派经常重启,有时甚至直接卡死无响应。最严重的一次,我部署的 Karakeep 书签服务因为底层数据错误导致数据库损坏,数据瞬间全丢,万幸最后从 Meilisearch 中抢救回来了。

排查过程中我尝试了很多方法(包括修改PCIe节能设置等),最后发现罪魁祸首可能是官方 FPC 排线的抗干扰能力不足(虽然官方说是抗干扰的)。后来我将树莓派与路由器物理分离一段距离后,就再也没出现过类似问题。

如果你不需要使用树莓派的 WiFi 功能,也建议关闭。

参考链接

https://linuxblog.io/raspberry-pi-performance-add-zram-kernel-parameters/

https://github.com/geerlingguy/raspberry-pi-pcie-devices/issues/559

在 Antigravity 使用 VS Code 应用扩展商店

2025年11月20日 21:53

默认情况下,Antigravity 使用 Open VSX 作为扩展市场,因此许多在 Visual Studio Code 中可安装的扩展在 Antigravity 里可能搜不到。如果在从 VS Code 迁移过来,可能会很不习惯。

可以通过下面方式,让 Antigravity 能够使用 VS Code 的应用扩展商店:

  1. 在 Antigravity 的菜单栏中的 “首选项” 中打开 “Antigravity Setting”。

  2. 在设置中的 “Editor” 区域,设置以下参数:

    Marketplace Item URL

     https://marketplace.visualstudio.com/items

    Marketplace Gallery URL

    https://marketplace.visualstudio.com/_apis/public/gallery
  3. 重启 Antigravity 即可。

树莓派安装 OpenWrt 及扩容教程

2025年9月27日 12:02

时隔多年再次重装 OpenWrt,早已忘记当初的安装方法。许多教程已经过时或缺少关键细节,因此记录本文以便日后查阅,也方便有需要的人参考。如有问题,欢迎在评论区讨论。本文仅作为参考,请谨慎操作,数据风险自负。

本文将演示如何在树莓派4B上安装 ImmortalWrt 并进行扩容。

1. 安装 ImmortalWrt

ImmortalWrt 是 OpenWrt 的一个分支 ,它移植了更多的软件包,支持更广泛的设备,默认优化了配置文件,并为中国大陆用户进行了本地化修改。

1.1 下载 ImmortalWrt

前往 ImmortalWrt 固件选择工具 下载对应固件:

搜索设备型号,查找对应固件。

image.png

每个设备一般会对应四个固件:

image.png
  • SYSUPGRADE vs. FACTORY:
    • FACTORY 固件是用于首次安装ImmortalWrt。
    • SYSUPGRADE 固件是用于升级已经运行ImmortalWrt的设备,它会保留你的配置。
  • EXT4 vs. SQUASHFS:
    • EXT4 是一个可读写的日志文件系统,更灵活,可以更方便地修改系统文件。
    • SQUASHFS 是一个只读的压缩文件系统,通常与一个小的可写分区(如JFFS2或UBI)结合使用。它在系统稳定性、节省空间和抗意外修改方面有优势。如果系统被破坏,可以更容易地恢复到初始状态。

首次安装,选择 FACTORY 版本,树莓派设备推荐使用 EXT4。

下载 FACTORY(EXT4) 的版本。

1.2 烧录 ImmortalWrt

利用 rufus 工具将上一步得到的 immortalwrt-[版本号]-bcm27xx-bcm2711-rpi-4-ext4-factory.img.gz 直接烧录到内存卡,保持 rufus 默认设置即可。

2. 初始化系统

2.1 连接与首次登录

ImmortalWrt 不再默认创建 Wi-Fi 热点,所以需要通过有线的方式连接到它。

把内存卡插到树莓派中,接通电源。然后用网线连接树莓派和电脑。

在电脑上访问 192.168.1.1。默认账号名为 root,密码为空。

登录后按照提示修改默认密码。

2.2 配置网络

进入 “网络” - “接口”,然后编辑默认 lan 接口。

image.png

根据实际需求配置网络。

由于我将其作为旁路网关使用,所以设置了静态 IP 地址,并指定了相应的网关和 DNS。且在“DHCP 服务器”界面,勾选“忽略此接口”。

确认无误后,点击“保存并应用”,并强制执行。

然后,就可以用网线将树莓派连接到路由器了。

3. 扩容分区

完成后上述步骤后,ImmortalWrt 就能正常使用了。但是默认 ImmortalWrt 只用了 300MB 的储存,并没有用完整张储存卡。所以可用空间很少,并且被浪费。

接下来我们来扩容。

  1. 安装需要用到的工具

    opkg update  
    opkg install fdisk resize2fs losetup
  2. 查看当前分区状况

    fdisk -l

    你会看到类似下面的输出(120GB 的内存卡,只用了 64MB + 300MB):

    image.png
  3. 重新分区

    进入 fdisk 工具:

    fdisk /dev/mmcblk0

    输入 p 查看分区表,记住第二分区开始的位置:

    image.png

    输入 d 删除第二个分区:

    image.png

    输入 n 重新创建分区:

    • 分区类型:选择 p ,或直接回车使用默认值。
    • 分区序号:选择 2 ,或直接回车使用默认值。
    • 起始扇区:输入之前记录的 147456(根据实际情况替换,使用原起始扇区)。
    • 结束扇区:可以指定大小,或直接回车使用默认值,默认值是占用所有剩余空间。
    • 当提示是否移除标识:输入 N
    image.png

    最后,输入 w 确认并执行变更:

    image.png
  4. 再次查询分区情况,可以看到第二个分区现在已经扩大。

    fdisk -l
    image.png
  5. 接下来还需要让系统能够识别这个分区:

    先查看当前是否有循环设备:

    losetup

    此时,输出可能为空。或者有一些设备。在下个命令中,不要与已有设备冲突,可以用 loop1 或其他未使用的编号。

    创建循环设备:

    losetup /dev/loop0 /dev/mmcblk0p2

    扩展文件系统到分区全部空间:

    resize2fs -f /dev/loop0
  6. 重启系统,网页访问树莓派,可以看到扩容成功,磁盘空间大小已经更新。

    reboot
    image.png

4. 参考链接

https://blog.caliburn.work/archives/1709726837347

Docker容器中的定时任务:使用Supercronic运行Python脚本

2025年4月23日 20:06

上一篇文章中,我介绍了 eudic-maimemo-sync 项目——利用 Python 脚本调用欧路词典墨墨背单词的开放API将生词本自动同步到墨墨背单词,并演示了如何用 Docker 将其部署到树莓派上,每天自动执行同步。

这篇文章,我想分享我在配置 Docker 容器实现定时任务时遇到的一个问题,以及我是如何解决它的:我最初在容器内使用标准的 Cron 服务来调度 Python 脚本。但我发现,即使把环境变量传入了容器,Cron 触发脚本时依然读不到这部分配置,导致 Python 读取不到 API 密钥。原因是 Cron 不会继承容器的环境变量,它运行在相对隔离的环境中。

为了解决这个问题,我开始在网上搜索并向大语言模型求助,最后得到几个可能的方案:

  • .env 文件直接挂载进容器,让脚本从指定路径读取
  • entrypoint.sh 文件中,读取环境变量,然后显式地将它们写入 crontab 文件或注入到 Cron 进程环境中
  • 使用 Supercronic 或其他替代 Cron 方案

虽然前两种方法可行,但需要额外的配置和脚本处理。经过测试,我最终选择了 Supercronic。它是一个与 Cron 语法兼容、专为容器设计的任务调度工具,用法和原生 Cron 几乎一致,且能够直接继承容器内的环境变量,大大简化了配置过程。将 Cron 替换为 Supercronic 后,问题就迎刃而解了。

如果你有同样的需求,想要通过容器定时运行 Python 脚本或其他程序,我推荐试试 Supercronic。我精简了eudic-maimemo-sync 项目,编写一个基础示例 docker-python-supercronic-example。示例中展示了如何在 Docker 容器里配置 Supercronic,并定时执行 Python 脚本,供大家参考。


接下来我讲讲如何使用这个示例:

.
├── Dockerfile          # 用于构建包含 Supercronic 的 Python 镜像
├── docker-compose.yml  # 容器部署的配置
├── entrypoint.sh       # 生成 crontab 并启动 Supercronic 的脚本
├── test.py             # 按计划运行的示例 Python 脚本
└── requirements.txt    # Python 依赖项

开始使用

  1. 克隆此仓库

    git clone https://github.com/emuqi/docker-python-supercronic-example.git
    cd docker-python-supercronic-example
  2. 为你的架构选择 Supercronic

    Dockerfile 默认配置为 ARM64 架构。对于其他架构(例如 x86_64),需要修改 Dockerfile

    访问 Supercronic Releases,找到适合你的 CPU 架构的 安装说明。安装说明内一般会包含要添加到 Dockerfile 的代码。

    替换以下部分:

    # 最新版本请访问 https://github.com/aptible/supercronic/releases
    # 根据你的CPU架构选择合适的 Supercronic 版本
    ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.2.33/supercronic-linux-arm64 \
    SUPERCRONIC_SHA1SUM=e0f0c06ebc5627e43b25475711e694450489ab00 \
    SUPERCRONIC=supercronic-linux-arm64
    RUN curl -fsSLO "$SUPERCRONIC_URL" \
    && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
    && chmod +x "$SUPERCRONIC" \
    && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
    && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
  3. 创建 .env 文件用于设置环境变量

    CUSTOM_MESSAGE=来自计划任务的问候!
    CRON_SCHEDULE=*/5 * * * *  # 每 5 分钟运行一次
  4. 构建并启动容器

    docker compose up -d --build
  5. 检查日志以验证程序是否按预期运行

    docker logs my_python_cron_job

    你应该能看到类似下面的日志输出:

    my_python_cron_job  | time="2025-04-23T18:53:00+08:00" level=info msg="Python script start" channel=stdout iteration=0 job.command="/usr/local/bin/python /app/test.py" job.position=0 job.schedule="* * * * *"
    my_python_cron_job  | time="2025-04-23T18:53:00+08:00" level=info msg="Message: Hello World!" channel=stdout iteration=0 job.command="/usr/local/bin/python /app/test.py" job.position=0 job.schedule="* * * * *"
    my_python_cron_job  | time="2025-04-23T18:53:00+08:00" level=info msg="job succeeded" iteration=0 job.command="/usr/local/bin/python /app/test.py" job.position=0 job.schedule="* * * * *"

配置

环境变量

变量 描述
TZ 容器时区
CRON_SCHEDULE 用于调度的 Cron 表达式
CUSTOM_MESSAGE 传递给 Python 脚本的示例变量

Cron 计划表达式示例

  • * * * * * - 每分钟
  • */5 * * * * - 每 5 分钟
  • 0 * * * * - 每小时(0分时)
  • 0 0 * * * - 每天午夜
  • 0 18 * * * - 每天下午 6:00

自定义

  1. 用你自己的 Python 脚本替换或修改 test.py
  2. 通过编辑 .env 文件或 docker-compose.yml 中的 environment: 部分来扩展或覆盖变量。添加的任何新变量(例如 NEW_VAR=value)都将被加载到容器中。
  3. 将所需的任何依赖项添加到 requirements.txt
  4. 重新构建并运行容器:docker-compose up -d --build

树莓派 | 欧路词典生词本 & 墨墨背单词 云同步教程 (eudic-maimemo-sync)

2025年4月16日 16:32

在浏览网页时,我常用欧路词典的“欧路翻译”浏览器插件进行划词翻译。这个插件会自动记录查阅过的单词,并将其添加到欧路词典的生词本中。 然而,在单词记忆方面,我更习惯使用“墨墨背单词”。

因此,我在寻找一种方法,将欧路词典的生词本同步到墨墨背单词的词库。这样,我就可以用自己习惯的软件来记忆日常阅读中遇到的生词了。

欧陆墨墨.png

后来我发现,这两个软件其实都提供开放 API。于是,我开发了 eudic-maimemo-sync 工具,实现欧路词典生词本到墨墨背单词云词库的自动同步。同时,我还将其部署在树莓派上,让它每天自动运行,实现了生词本的无缝同步。

image.png

接下来,我将介绍如何配置和使用这个工具,并分享开发过程中遇到的一些问题和解决方法。也欢迎大家贡献代码或提出建议。

目录

eudic-maimemo-sync 使用教程

1. 下载代码安装依赖

前置条件:已安装 Python 3 环境

下载代码:

git clone https://github.com/eMUQI/eudic-maimemo-sync.git

安装依赖:

cd eudic-maimemo-sync
pip install -r requirements.txt

2. 配置环境变量

接下来,需要配置环境变量。首先,复制 .env.example.env

2.1 欧路词典相关配置

  • 获取欧路词典 API 密钥

    访问此页面,登录后,获取你的API密钥。并将获取到的 API 密钥填入.env文件中的EUDIC_API_KEY字段。

    image.png
  • 获取生词本 ID

    运行 get_wordbook_id.py,查看生词本信息,记下你需要同步的生词本 ID。

    python get_wordbook_id.py
    image.png

    将需要同步的生词本 ID 填入 .env 中的 EUDIC_CATEGORY_ID

2.2 墨墨背单词相关配置

  • 获取墨墨背单词 API 密钥

    打开墨墨背单词手机 App,进入「我的」-「更多设置」-「实验功能」-「开放 API」,生成并复制 API 密钥,然后将其填入 .env 文件中的 MOMO_API_KEY 字段。

  • 获取云词库 ID

    运行 get_notepad_id.py,查看云词库信息,记住你需要同步的云词库 ID。

    python get_notepad_id.py
    image.png

    将需要同步的词库 ID 填入 .env 文件中的 MOMO_NOTEPAD_ID 字段。

3. 手动同步

运行 sync.py,即可手动触发一次同步。

python sync.py

4. 自动同步(部署到树莓派上或者其他 Linux 设备)

确保部署前已经成功手动运行过 python sync.py,验证配置无误。

使用Docker

我个人比较喜欢用 Docker, 隔离性好,依赖管理简单,不会弄乱系统的环境。在我的树莓派 5 上运行良好,额外的性能开销在可接受范围内。

创建一个 docker-compose.yml 配置文件:

services:
  eudic-maimemo-sync:
    image: ghcr.io/emuqi/eudic-maimemo-sync:latest
    container_name: eudic-maimemo-sync
    restart: unless-stopped
    env_file:
      - .env
    # volumes:
    #   - ./words_data.txt:/app/words_data.txt # 如果想查看单词记录,取消此行和上一行的注释
    environment:
      - TZ=Asia/Shanghai
      - RUN_ON_STARTUP=true # 设置为 true 时,容器每次启动时会执行一次同步任务
      # CRON 定时任务表达式配置:
      # 示例:每小时的第 0 分钟执行(即整点执行)
      # - CRON_SCHEDULE=0 * * * *
      # 示例:每天凌晨 3:15 执行
      - CRON_SCHEDULE=15 3 * * *
      # 请确保所有必需的环境变量(如 EUDIC_API_KEY 等)已在 .env 文件中定义或在此处直接指定。
    healthcheck:
      # Test if the supercronic process is running
      test: ["CMD-SHELL", "pgrep supercronic || exit 1"]
      interval: 2m
      timeout: 5s
      retries: 3
      start_period: 10s

你可以通过 CRON_SCHEDULE 来设置任务的运行周期:

  • CRON_SCHEDULE=0 * * * *: 每小时的第 0 分钟执行(即整点执行)
  • CRON_SCHEDULE=15 3 * * *: 每天凌晨 3:15 执行

在相同目录下创建一个 words_data.txt 文件,用于记录同步的单词列表,方便调试或查看。如果不需要,可以跳过此步。

touch words_data.txt

启动容器

docker compose up -d

其他方式

你还可以使用 cron 或者 systemctl 的方式来定时运行这个同步脚本。如果你熟悉这些工具的配置,欢迎分享你的方法或提交 Pull Request。


开发中遇到的问题

  1. 欧路词典 API 的 User-Agent 要求: 欧路词典 API 对请求的 User-Agent 有特定要求,不接受 Python HTTP 库(如 requests)的默认 User-Agent。因此,在与该 API 交互时,必须显式设置一个浏览器类型的 User-Agent,以确保请求被正确处理。本项目中,我采用了 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36

  2. 墨墨背单词 API 云词库格式: 墨墨背单词 API 文档中关于添加单词到云词库所需的数据格式说明不够清晰。文档中只说明数据类型是 string,但未明确其具体结构。经过试验,结构为以井号 # 开头的行作为分类标记(例如日期),换行后紧跟该分类下的单词,每个单词独占一行。下一个分类同样以 # 开头的标记开始。如 #20250415\napple\nboy#20250416\ncat

    #20250415
    apple
    boy
    #20250416
    cat
  3. Docker 中定时任务:从 Cron 到 Supercronic 的迁移: 一开始,我尝试在 Docker 容器内部署 Cron 来定时执行 Python 任务。但是,Cron 任务默认在隔离的、极简的环境中执行,无法直接继承 Docker 容器启动时定义的环境变量(例如 API 密钥等配置)。虽然有方法可以间接加载,但配置比较繁琐。于是我迁移到了 SupercronicSupercronic 是一款专为容器环境设计的 Cron 实现,它兼容标准的 Crontab 语法,还能继承容器的环境变量。如果你有类似的项目,推荐你使用 Supercronic 作为替代方案。

最后,欢迎提交 Pull Requests 或 Issues 到 eudic-maimemo-sync。有任何想法,也欢迎在下方留言。

相关链接

在 AI 时代,我为什么写博客?

2025年3月4日 21:07

这两天,在 Hacker News 上看到 Giles Thomas 的两篇文章,深有感触。

第一篇是 《On the benefits of learning in public》,讲述了 "learn in public" 的好处,比如能够巩固和深化知识。我写的大多数文章其实都是教程,也算是 "learn in public" 的一种实践,但我有时会怀疑这些教程是否真的有意义,因为它们看起来很简单、基础,似乎谁都能写,不够深刻。我会质疑那些记录基础操作步骤的文章是否值得发布——毕竟它们有时看起来只是对官方文档的简单复述,或是任何开发者通过Google都能找到的常见解决方案。如果说只是为了记录下来,方便以后自己查询,也许它们呆在个人知识库就足够了。

这篇文章给了我启发:他把自己写的教程描述为“我希望在刚开始学习时就能找到的文章”("tutorials that I wished someone else had written for me before I started trying to learn this stuff")。这句话让我豁然开朗:即使是简单的教程,只要它能够帮助初学者少走弯路,就有其独特价值。这在很大程度上消除了我的疑虑,给了我很大的鼓舞,因为这也正是一直以来我希望自己的文章能够达到的标准。

比如我的这两篇文章,或许就是某个人摸索时的及时雨:

https://wulu.zone/posts/whisper-cn

https://wulu.zone/posts/mi-iot-homekit

另一篇是 《It's still worth blogging in the age of AI》,这篇文章探讨了在人工智能普及的时代,博客写作的意义。在他的上一篇文章登上 Hacker News 热门后,一个常见的问题浮现:如果人们都在使用 ChatGPT、Claude 和 DeepSeek 获取信息,谁还会阅读博客内容?除了 AI,还有谁会阅读你写的内容?Giles 认为是值得的,并且给出了他的思考。我觉得如果你是博客作者,你能在其中找到共鸣,推荐大家去看。

我为什么写博客?

读完这两篇文章,我再次思考:我为什么写博客?这个问题其实早已存在。从为了满足自己拥有网站的虚荣心而搭建博客的最初时期,到随性有灵感时更新,再到中途停笔的时期,到最后现在有意识地重新开始写作。这种问题总会反复出现。

尽管与作者笔耕不辍不同,我的博客更新并不频繁,不太算是一个经常写博客的人。但文章中提到的几点博客写作的价值依然让我共鸣:

  1. 知识结构化:将知识记录下来帮助自己更好地掌握,而且也方便后续查询
  2. 成就感:当别人阅读并从我的文章中获益时带来的那种多巴胺刺激
  3. 个人品牌:通过博客创建一个能展示自己思想观点的作品集

我认可费曼学习法和 "learn in public" 等观念,就像文章提到的“如果你不能向一个聪明且感兴趣的听众解释清楚某件事,那么你就没有真正理解它。”。写作是思考的升华过程。当我们将想法用自己的语言阐述时,思维才得以精细的加工。而且为了准确表达,我常常会查阅额外资料,这本身是一个深度学习的过程。

记录下这些教程还有一个好处:文字是对抗遗忘的工具。记忆并不那么可靠,记录下来后,回头再看当时写下的文章,能够帮助自己回溯。文字能够复现消逝的自我。


另一方面,写作对我而言除了是一种思想训练和学习方式,更是一种存在的证明。在《直视骄阳》这本书中了解到波动影响理论后(在我的《2024 读书总结》中有提到,如果你感兴趣的话),我发现写作能有效缓解我的存在焦虑。

刚接触互联网时,我就读到了《欺骗的艺术》这本书,了解了社会工程学,对在互联网上分享信息产生了警惕。这种警惕加上我的性格特点,导致我一直以来很少在互联网上透露个人信息,甚至很少写一些感想类的文章。我的博客大多数聚焦于技术分享,个人观点则被谨慎地隔离在外。

直到经历了一场深刻的心理危机,接受心理咨询并广泛阅读心理学和哲学书籍后,我的世界观发生了微妙的转变。我开始渴望与人连接,期待真诚的交流。这种认识让我开始思考在博客上分享更多个人感想的可能。虽然仍有矛盾和犹豫,但我开始相信,适度的自我揭示和真诚分享不仅是自我成长的一部分,也可能为他人提供某种共鸣或安慰。我期待我的文字能够帮助人,与更多人产生联系,传播那或许是非常微小但真实的影响。

写作帮助我整理思绪,获得分享的快感,同时也是应对生活空虚感的方式。即便有时感觉像 Giles 文章中提到的 "feel like you're shouting into the void" (就像对着虚空喊叫),但偶尔从“虚空”传来的一条留言、一个点赞,都将成为继续前行的动力。

AI 时代的写作价值

在AI盛行的时代,我认为坚持写作变得更加重要。从我的理解来看,现阶段的大语言模型本质上还是基于概率的文本生成,而每个人独特的思考和写作方式是无法被完全替代的。当越来越少的人选择写作,那些仍然坚持的声音反而变得更加珍贵,更加真实,充满温度和灵魂。写作不仅是信息的传递,更是人类思想和情感的独特表达。

这就是为什么,尽管面对AI的崛起,我依然相信博客写作的价值——它帮助我思考,连接他人,留下我存在的印记,同时也为这个世界贡献一份真实的人类声音。

题外话:一个邀请

在浏览 Hacker News 的关于上面文章的评论区时,我被 Aditya Athalye 的做法所吸引——他学习Derek Sivers和patio11的做法,在他的网站放了一份“长期邀约”。

我觉得这种方式很吸引我,我也想学习这种方式,以下是我的对所有人发起的邀请:

如果你对我的文章,或者我所讨论的任何主题感兴趣,欢迎你给我发送邮件。我的邮箱地址是:wulu@wulu.zone

我会不定期查看邮件,可能我无法及时回复,但我承诺只要你是以友善和尊重的态度联系我,我一定会回应。每一次真诚的交流都可能成为意外的收获和启发,或许这也是在AI时代写博客和保持人际连接的另一种价值所在。

谢谢你的阅读!期待收到你的来信。

2024 读书总结

2025年2月17日 21:35

过去这一年,我的阅读主要围绕心理健康、自我认知和个人成长展开。这些书籍帮助我更深入地理解了自我和他人,也为日常生活提供了实用的工具和方法。虽然遗憾没能在读完时及时记录感受,但重温这些书籍时,仍能感受到它们带给我的启发和改变。以下是我对这些书籍的简要回顾与思考。

《蛤蟆先生去看心理医生》

作者:罗伯特·戴博德
译者:陈赢
出版社:天津人民出版社

一本很薄的故事书,有点像童话或者寓言故事,如书名,讲述了蛤蟆先生去看心理医生的故事。 读起来很轻松,流畅,一下就可以读完。这本书提供了一个了解心理咨询的视角,是一本不错的心理学读物。 书中还科普了交互分析理论(Transactional Analysis,TA)中的儿童自我状态,父母自我状态,成人自我状态。这个理论认为我们会在这三种状态不停地切换,非常有趣的理论,有助于帮助了解自我。

《直视骄阳》

作者:Irvin D. Yalom
译者:张亚
出版社:中国轻工业出版社

这是一部关于如何面对死亡的深刻著作。

这本书讲了死亡焦虑的普遍性,如何识别死亡焦虑,它能够带来什么,以及我们可以如何去面对它。

对我而言,这本书帮助最大的就是带我了解了伊比鸠鲁的观念:

  • 死亡本身不可怕,因为我们无法感受死亡,死后“我”就消失了,即“完全虚无的死亡”。
  • 生前和死后,是对称的两极。死后其实和生前并无差别。
  • 波动影响。指人有意无意会对周围的任何事物产生影响,就像池塘中的涟漪,即使细微但是很长远。

这本书给了我一些方法去处理我的死亡焦虑,也给我带来了一些新的思考去看待自己的死亡和他人的死亡。书中还讨论了死亡意识如何反过来影响我们的生活态度,以及如何将对死亡的思考转化为珍惜当下的动力。如果你有存在焦虑或者死亡焦虑,我非常推荐这本书。

《非暴力沟通》

作者:马歇尔·卢森堡
译者:刘轶
出版社:华夏出版社

这本书介绍了非暴力沟通。也是一种生活理念。它提示我要关注自己内心的感受和需求,真诚地与人沟通。

通过把注意力放到观察、感受、需求和请求这四个要素来改善沟通,同时非暴力沟通还强调自主的重要性,强调个人责任。我觉得这一点和存在主义的观念是很吻合。

书中还提到了很多非常有意思的讨论:比如观察和评论的区别,请求和要求的区别。这些讨论不仅帮助我反思与人的沟通,也帮助我反思人际关系。

非暴力沟通方法在亲密关系中尤其有效,能帮助伴侣之间建立更深入的理解和连接。

书中还有很多内容,需要真正去读并且实践才有用,非常有帮助,非常推荐这本书。

《Headspace 冥想正念手册》

作者:安迪·帕帝康
译者:李芳龄
出版社:星出版

这本书科普了冥想和正念,有很多帮助理解冥想的故事,还提供一些方法帮助入门冥想。

之前一直听说过冥想,听过很多关于冥想的传闻,却也没有真正了解过。今年特别想尝试一下冥想,买了这本书来了解一下,让我对冥想有了不同的认识。书中还提供了很多隐喻帮助理解冥想。我也尝试了冥想,对我而言确实有帮助的。

如果你也对冥想感兴趣,或者正在尝试但觉得摸不着头绪,很推荐这本书。我看的这个版本是繁体中文,还有一个简体中文的版本,名字是《十分钟冥想》。

《天生敏感》

作者:伊莱恩·阿伦
译者:于娟娟
出版社:华夏出版社

这是一本讲述所谓高敏感人群的特质的书。

听了枫言枫语的节目,专门看了这本书。我大致也属于比较敏感的人群,这本书帮助高敏感人群了解自我,理解自我,并且提供了一些方法更好的与外部世界相处。还有很重要的是,能够带来很大的认同感。

《素食者》

作者:韩江
译者:胡椒筒
出版社:四川文艺出版社

这是一本小说,由2024年诺贝文学奖作者韩江写的。书中通过三个视角来叙述同一个故事,这点比较有趣。我是慕名去看,没有我想象中的好看,整本书像是讲述几个精神病的故事,很压抑。

《也许你该找个人聊聊》

作者:洛丽·戈特利布
译者:张含笑
出版社:上海文化出版社

这是一本讲述心理咨询的书。这本书很厚,由一个心理咨询师的视角写作,书中以一个个故事组成,每一个章节是一个故事,有作者本人的故事,也有作者作为心理咨询师在咨询室里遇到的故事。虽然很厚但是读起来没有压力,可以慢慢看看,每天看几个故事。我喜欢这本书不是一本说教的书,平易近人,没有让人感觉是在尝试告诉你什么道理,而是通过一个个故事,让你自己去感受,找到自己的理解。

结语

希望今年能保持阅读的习惯,也期待遇见更多好书。

使用 Audacity 制作立体音效果

2024年12月9日 22:13

制作短视频时,巧妙的音效能提升表现力、吸引观众兴趣并提高完播率。比如,下面这个视频,视频和声音有着一致体验。声音跟随着画面的焦点移动,在左右耳朵穿梭。

这种声音的立体移动效果,实际上是通过精妙的声道控制实现的。

具体而言,声音的左右穿梭可以通过调整左右声道的音量来完成。比如,我们可以逐步减弱左声道的音量,同时逐渐增强右声道的音量。这种渐进式的音量变化,会给观众造成声音从左向右流动的听觉错觉,仿佛声音正在穿越立体空间。通过细腻地控制声音的转换,我们可以为视频增添一层令人着迷的听觉维度,提升视听体验。

接下来,我将分享如何使用 Audacity 制作这种立体音。

安装 Audacity

你可以前往 Audacity 或者是它的 Github 页面下载。但需要是要注意的是,在官网下载时,如果你没有选择 “Download without Muse Hub” 选项,那么它可能会捆绑安装 Muse Hub。

image.png

你还可以安装可选的 FFmpeg 库。如果你要使用 Audacity 编辑 AC3, M4A, MP4 或 WMA 格式的音频,则是必须的。

https://support.audacityteam.org/basics/installing-ffmpeg

1. 使用包络工具标记左右声道切换的位置

将音频导入 Audacity,你可以直接将音频拖入 Audacity 或者选择“文件 > 导入 > 音频”。

然后你可以看到音频的波形图:

image.png

首先我们使用“包络”工具标记声道切换的位置。

找到“包络”工具,

image.png

在期望声音左右切换的位置点一下,标记声音切换的位置,方便后面我们调整各声轨的音量变换。

标记声轨.gif

比如,我想要每一秒声音切换(声音从左到右或者从右到左)一次,我就每隔一秒标记一下:

image.png

2. 分离音轨左右声轨

点击“分离立体声轨”,将左右声道分开成两个声轨,方便编辑。

image.png

3. 分别调整左右声轨

分离声轨后,上面的声轨代表左声道,下面的声轨的右声道。这样就能分别控制左耳和右耳听到的声音。按照下图的方式调整声轨。

逐渐减弱左耳听到的声音,同时逐渐增强右耳的声音,就能制造声音从左到右的效果。

同理,逐渐减弱右耳听到的声音,同时逐渐增强左耳的声音,就能制造声音从右到左的效果。

调整声轨音量.gif

反复调节,调整到你期望的效果:

image.png

最后,通过“文件 > 导出音频”,导出降噪后的音频。

参考链接

https://manual.audacityteam.org/man/envelope_tool.html

更多

https://wulu.zone/posts/audacity-noise-reduction-guide

使用 Audacity 进行音频降噪教程

2024年11月14日 22:20

我一直使用 CapCut 来剪辑视频。有时想做一些安静或突出音效的视频,但当放大声音总会听到底噪(环境音)。可能是空调,也可能是风扇的声音。这种持续噪音基本无法通过静音部分内容去除,所以需要使用音频降噪功能。CapCut 原本提供免费音频降噪的功能,但后面变成了收费功能。于是,开始在网上找能够实现这一功能的软件。我的需求很简单,只要能够实现音频降噪这个功能就行,所以我没有选择使用功能强大的音频剪辑软件,我在寻找一个轻量化的软件。

我找到了 Audacity,它轻量化(不到100MB)且是开源的,功能强大易于使用。它的降噪功能,总体感觉比 CapCut 好。在 Audacity 中,可以选择噪音样本,再设定降噪范围,并且可以调整降噪的参数,最后的效果也比 CapCut 更佳。

接下来,我分享如何使用 Audacity 降噪音频。

安装 Audacity

你可以前往 Audacity 或者是它的 Github 页面下载。但需要是要注意的是,在官网下载时,如果你没有选择 “Download without Muse Hub” 选项,那么它可能会捆绑安装 Muse Hub。

image.png

你还可以安装可选的 FFmpeg 库。如果你要使用 Audacity 编辑 AC3, M4A, MP4 或 WMA 格式的音频,则是必须的。

https://support.audacityteam.org/basics/installing-ffmpeg

1. 取得噪音特征

将音频导入 Audacity,你可以直接将音频拖入 Audacity 或者选择“文件 > 导入 > 音频”。

然后你可以看到音频的波形图:

image.png

用鼠标左键选取噪音样本(仅包含你想要减少的噪音的区域),然后点击“效果器 > 噪音移除与修复 > 降噪”:

image.png
image.png

然后 ,点击“取得噪音特征”。

image.png

2. 调整参数降噪音频

接下来,选择你要降噪的范围:

image.png

然后再次点击“效果器 > 噪音移除与修复 > 降噪”:

image.png

点击“预览”可以听降噪后的效果,调整降噪的参数,直到预期的效果。这通常最好通过反复试验来完成,调整滑块并使用预览按钮聆听降噪后的音频。最后,点击“确定”。

  • 降噪强度(dB): 控制对识别噪声所应用的音量减少量。使用能将噪声减至可接受水平的最低值。高于必要的值可能使噪声更安静,但会导致剩余音频受损。
  • 灵敏度:控制音频中有多少被视为噪声,范围是 0(关闭)到 24(最大)。灵敏度越高,意味着去除的噪声越多,但也可能会去除一些所需的信号。较低的灵敏度可能会在降噪后的音频中留下伪影(不自然的声音失真)。建议将灵敏度设置为能有效去除噪声且不出现失真的最低值
  • 频率平滑(频带):当值为 1 或更高时,此控制将噪声降低扩展到指定数量的相邻频段中。这会修改您打算保留的信号,但是如果在降噪音频中残留伪影,平滑可以使这些伪影听起来更可接受。平滑可能会使所需的音频不太清晰,因此当噪声较轻时,请尝试将此控件保持在 0(关闭)
image.png

最后,通过“文件 > 导出音频”,导出降噪后的音频。

参考链接和拓展链接

除了上面的方法,你还可以通过 Audacity 使用频谱编辑(Spectral Editing)、噪音门(Noise Gate)和陷波滤波器(Notch Filter)等方式来降噪音频,如果你感兴趣,下面是参考链接:

https://support.audacityteam.org/repairing-audio/noise-reduction-removal

https://manual.audacityteam.org/man/noise_reduction.html

https://manual.audacityteam.org/man/alternative_noise_reduction_techniques.html

Moonhack 2024: 缓解气候变化

2024年10月20日 16:06

今年八月,树莓派基金会的本地化协调人员联系了我,向我介绍了 Moonhack,并询问我是否有兴趣翻译该项目。起初,我并不了解这个活动,但在网上搜索后,我发现它是一个有教育意义的活动,旨在通过编程教育,帮助全球各地的孩子提升科技(STEM)素养。同时,我也注意到在中文世界中,这个编程活动并不知名。

我觉得这个项目很有意义,它为儿童编程学习提供了优质资源。我希望能够通过将其翻译成中文,让中文世界的孩子们更方便地获取这些教育资源。因此,我参与了翻译活动,翻译了其中的两个 Scratch 项目。

现在,Moonhack 2024 已经正式启动,我希望通过这篇文章,向更多人推广这个活动,提供多一种学习编程的方式。即使不参加活动,活动中提供的项目教程也是个不错学习资源。

Moonhack 是什么?

Moonhack 是一项面向青少年的免费国际编程挑战赛,由 Code Club Australia 每年举办。在过去的 8 年里,超过 190,000 名儿童一直在编写 Moonhack 项目。

你可以在这里查看往年的项目:https://moonhack.com/previous-projects/

Moonhack 2024

Moonhack2024 于 10 月 14 日至 31 日举行。今年的主题为:气候变化。这些项目将帮助参与者了解从农业工作者如何利用气候数据提高农作物产量和实践可持续农业,到全球气温上升对海洋生物种群的影响等话题。

参与者可以使用 Scratch、micro:bit 或 Python 进行编程。

今年有六个项目,感兴趣的可以前往 Moonhack 官网了解:

  • Great Pacific Garbage Patch 大太平洋垃圾带(不限制编程平台)

    在任何编码平台中使用您的编码技能,创建一个可以清理太平洋大垃圾带的解决方案。

    项目主页 | 中文教程PDF

    image.png
  • In Deep Water 深陷水中(Scratch项目)

    创建一个迷宫游戏,帮助减缓上升的水位。帮助乌龟在水位上升之前回到地球。

    项目主页 | 中文教程PDF

    image.png
  • Sweeten the Crop 让作物更甜美 (Scratch项目)

    你能种出完美的甘蔗作物吗?创建一个点击游戏,尽力尝试一下吧。

    项目主页 | 中文教程PDF

    image.png
  • Water Adventure 水之旅(Scratch项目)

    创建一个展示水循环的动画。然后进一步开发,反映人类的影响。

    项目主页 | 中文教程PDF

    image.png
  • Talking Rubbish 垃圾会说话(micro:bit项目)

    创建一个设备,用于跟踪放入垃圾桶中的垃圾类型,并利用数据制定行动计划。

    项目主页 | 中文教程PDF

    image.png
  • Turtles and Temperature 海龟与温度(Python项目)

    编写一个程序,利用温度数据来观察这对海龟幼崽性别的影响。

    项目主页 | 中文教程PDF

    image.png

相关链接:

https://www.raspberrypi.org/blog/moonhack-2024/

https://moonhack.com/

https://www.codeclubau.org/moonhack-2023/

谈谈 Follow 这款 RSS 阅读器

2024年10月10日 22:39

简介

Follow 是一个最近新出的 RSS阅读器,由 RSSHub 的作者 DIYgod 的新团队 RSSNext 开发。

我喜欢 RSS 这个概念,尤其是 RSSHub 使得许多原生不支持 RSS 的网站和平台都能够通过 RSS 来订阅,让 RSS 有更多可能。我喜欢互联网开放的理念,更倾向不受特定平台限制地获取信息,并希望避免推荐算法的影响。长期以来,我使用 FreshRSS 来管理的 RSS 订阅。看到 Follow 这个新兴的 RSS 阅读器项目出现,我感到非常兴奋,期待它为 RSS 生态注入新的活力。

image.png

Follow 目前处于内测阶段,需要邀请码才能体验。当我在社交媒体看到 Follow 的宣传时,我向 DIYgod 私信,并且幸运地获得了一个邀请码以参加早期测试。现在我使用 Follow 已经差不多一个月,接下来谈谈我的体会。如果你也对Follow 感兴趣,文末我提供了两个邀请码

Follow 吸引我的地方

  • 出色的UI设计和动效

    具体可以查看 Follow 的核心开发者 Innei 写的文章《浅谈 Follow 中的设计理念》,这里就不再赘述。

  • 与 RSSHub 深度结合

    通过与 RSSHub 深度结合,Follow 提供了非常便捷的订阅体验,你可以直接在 Follow 里面搜索订阅 X、bilibili、youtube 等热门的社交平台以及各种 RSSHub支持的网站。

    image.png
  • 对媒体提供不同的视图

    在不同的视图下,Follow 将 RSS 订阅以不同的形式呈现。大多数的 RSS 阅读器,只提供了一个统一的视图,也就是文章视图。而 Follow 团队别出心裁的为各个视图设计不同的信息处理方式。

    比如在“播客视图”,你会感觉 Follow 变成了一个优秀的播客播放器。有一个精致的播放器,展示 shownote,甚至支持点击 shownote 中时间轴节点跳转播放进度。

    image.png

    在“视频视图”,信息以视频封面呈现。点击视频,能够直接在 Follow 播放视频。

    image.png
    image.png
  • 自动化 提供了丰富的自动化能力,比如AI摘要、翻译、重写和 Webhooks 等。

    image.png
  • 处于活跃开发阶段,反馈问题能够快速的处理

    Follow的开发者非常活跃,也有全职开发人员,问题处理的速度很快。有功能请求开发者也会积极考虑和开发。我反馈了一些问题都得到了回复和处理。

    image.png

缺点?

谈完了又优点,再来谈谈我认为的一些缺点。其实也不至于说是这款软件的缺点,只能说是我个人不是那么喜欢的地方。

  • 默认索引用户订阅的站点,可能暴露付费RSS订阅或者私人订阅。目前,Follow 自动将用户的 RSS 订阅整合到其数据库中,并在其他用户搜索时显示。虽然这提高了用户体验,但也带来了隐私和安全风险。特别是对于私人RSS源(如Wallabag)或付费内容,即使选择了"私人关注",它们仍可能被包含并被公开搜索。我向 Follow 反应了这个问题,但是遗憾的是开发团队认为这不是目前开发的重点。

  • 后端不是开源的,无法自部署。这一点就见仁见智,习惯了使用 FreshRSS,我确实有点贪心希望 Follow 能够自部署。我看到 Follow 团队正在招聘全职开发、产品经理和市场营销专家。我猜测 Follow会发展成为一个付费服务,如果定价合理的话,我会愿意支持。希望Follow 团队能够越走越远。

展望

  • 修正隐私问题,在维护互联网开放的精神同时,保护用户的隐私。克制合理地分享。
  • 发布移动版本。

Follow内测邀请码

如果你曾在 RSSHub 项目贡献过代码,你可以直接私信 DIYgod 或者 Follow 的X账号获取邀请码。

你也可以向内测用户获取邀请码,这里提供两个邀请码,先到先得,使用后请在评论区反馈。如果你很想参加内测,也可以直接评论,并且谈谈你对Follow 的看法,我会直接在评论回复邀请码。但是我的邀请码也十分有限(10天一个),只能尽量邀请。

  • 8i19XX0IQa (已使用)
  • 4d8Xv451u8(已使用)

241024更新:现在 Follow 已经开始 Beta 测试,不用邀请码也能体验一些功能,但是会有一些限制。

  • soGuIpSY1Q(已使用)

241125更新:现在 Follow 网页终于支持移动端访问了,还支持PWA! 在墨水平板上也能使用,效果也很不错。

IMG_5900 (大).jpg
  • cMGg7BIhgy(已使用)
  • Wa65ezWJTP(已使用)

2025.02.14 更新的新邀请码:

  • nkTrKI8ZPA(已使用)
  • 05C71sAN4L(已使用)
  • QQUyUYGOJY(已使用)

2025.03.01 更新

Follow 开始了 ios 内测,原生支持移动端了🎉

IMG_8748.jpeg

分享几个新的邀请码:

  • 8uEXAEpB6K(已使用)
  • 3xXiqHMCEj(已使用)
  • BTmconUxsQ(已使用)

2025.03.23 更新:Follow 正式发布 iOS 版本 Folo

https://apps.apple.com/us/app/folo-follow-everything/id6739802604

分享几个新的邀请码:

  • fbsYJICV12(已使用)
  • GgdjYNUTMz(已使用)
  • K5GQEjXUHe(已使用)
  • wxIoi5HpFE(已使用)
  • sq_cuxWahO(已使用)

欢迎在 Follow 上订阅本博客:https://app.follow.is/feed/53322153570297857

我整理的 STEAM 教育硬件资讯列表:https://app.follow.is/share/lists/72173389013837824

学习英语的播客列表:https://app.follow.is/share/lists/92088247676273664

开放课程推荐 「面向开发者的 ChatGPT 提示词工程」

2023年6月12日 22:16

ChatGPT 上线至今已经有一段时间了,但是不少人还没真正掌握它的使用技巧。

其实,ChatGPT 的难点,在于 Prompt(提示词)的编写,OpenAI 创始人在今年 2 月时,在 Twitter 上说:「能够出色编写 Prompt 跟聊天机器人对话,是一项能令人惊艳的高杠杆技能」。

因为从 ChatGPT 发布之后,如何写好 Prompt 已经成为了一个分水岭。熟练掌握 Prompt 编写的人,能够很快让 ChatGPT 理解需求,并很好的执行任务。

目前你在网上看到的所有 AI 助理、智能翻译、角色扮演,本质上还是通过编写 Prompt 来实现。

只要你的 Prompt 写的足够好,ChatGPT 可以帮你快速完成很多工作,包括写爬虫脚本、金融数据分析、文案润色与翻译等等,并且这些工作还做的比一般人出色。

为了帮助大家能更好的掌握 Prompt 工程,DeepLearning.ai 创始人吴恩达与 OpenAI 开发者 Iza Fulford 联手推出了一门面向开发者的技术教程:《ChatGPT 提示工程》

--- https://github.com/GitHubDaily/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese

ChatGPT的难点在于Prompt(提示词)的编写,熟练掌握Prompt编写的人能够很快让ChatGPT理解需求,并很好地执行任务。为了帮助开发者更好地掌握Prompt工程,吴恩达与OpenAI联手推出了一门面向开发者的技术教程《ChatGPT提示工程》。

虽然这门课程已经推出一段时间了,但我最近才开始学习。学完确实受益匪浅,推荐给大家。课程介绍了大型语言模型时的提示原则和相关策略,并提供了每个策略的实例。可在 deeplearning.ai 平台上学习,并提供预置OpenAI Key的Jupyter Notebook环境。可以边观看视频边使用Jupyter Notebook运行课程中的代码实例。

如果你觉得全英文视频有些吃力,也可以查看这个项目,在B站上传了相关视频并提供中英文字幕。即使你是跟着B站的课程学习,依然强烈建议跟着视频在 deeplearning.ai 平台上运行课程案例。

image.png

课程大纲与笔记

建议至少学习完第一章,以下是我整理的课程大纲与笔记:

访问链接:《ChatGPT Prompt Engineering for Developers-大纲&笔记》

ChatGPT Prompt Engineering for Developers-大纲&笔记.png

相关文章

https://wulu.zone/posts/API2D

指定 Whisper 输出为简体中文

2023年5月16日 23:29

Whisper是OpenAI推出的一种开源语音识别模型,能够自动识别多种语言,将音频转换文字。Whisper由python实现,同时拥有丰富的社区支持。除了原始的Whisper之外,还有一些相关的项目,有移植到 C/C++的whisper.cpp和能使用GPU加速的faster-whisper。如果你不懂编程或者不熟悉命令行,也有也有很多开发者开发了图形界面,比如buzzConst-me/Whisper等。

Whisper 支持直接输出srt格式的字幕文件。我最近用 Whisper 生成字幕文件,再配合ChatGPT 使用GPT-Subtrans 翻译字幕,整体效果很好。不过, Whisper有一个问题,就是Whisper 使用--language来指定语言,但无论是简体中文还是繁体中文,对应的代码都是zh。很多情况下,使用Whisper 生成字幕文件,设置参数--language zh,会生成繁体中文的字幕文件。

解决方案

在网上终于查到解决方案,分享给大家。 在 Whisper 的讨论区中,@jongwook 提出:

  1. 使用 --initial_prompt 参数,用简体中文输入 "以下是普通话的句子。" 就能生成简体中文字幕。(补充:whisper.cpp 用户可以尝试使用--prompt参数)
  2. 以此类推,用繁体中文输入 "以下是普通話的句子。" 就能得到繁体字幕。
$ whisper --language Chinese --model large audio.wav
[00:00.000 --> 00:08.000] 如果他们使用航空的方式运输货物在某些航线上可能要花几天的时间才能卸货和通关
$ whisper --language Chinese --model large audio.wav --initial_prompt "以下是普通話的句子。"  # traditional
[00:00.000 --> 00:08.000] 如果他們使用航空的方式運輸貨物,在某些航線上可能要花幾天的時間才能卸貨和通關。
$ whisper --language Chinese --model large audio.wav --initial_prompt "以下是普通话的句子。"  # simplified
[00:00.000 --> 00:08.000] 如果他们使用航空的方式运输货物,在某些航线上可能要花几天的时间才能卸货和通关。

另外,有关 --initial_prompt 参数,可在 openai的文档 查看更多。其中也提到 "有些语言可以用不同的方式书写,比如简体或繁体中文。模型可能默认不会使用你想要的转录写作风格。你可以通过使用你偏好的写作风格的提示来改善这一点。"。

Api2d 国内可用的chatgpt api代理

2023年4月16日 22:46

前言:AI技术的普及和应用,让我们的生活更加便捷和愉悦。尤其是近期火热的ChatGPT,在自然语言交互等方面,已经取得了很重要的突破。然而,由于诸多因素的影响,使用ChatGPT在国内变得越来越困难。希望通过这篇博客,让更多的人了解到 API2D 这个很好的ChatGPT 访问方案,让大家都能受益于AI技术的进步。

api2d 是什么?与ChatGPT是什么关系?

最近openai开始封禁亚洲用户的账号还有部分机房ip,使得在国内使用ChatGPT越来越难。再加上ChatGPT本来注册就有一定门槛,付费也不方便,只能用美国本地的银行卡支付。

找到一个替代方案:API2DAPI2D 是一个集成OpenAI接口的工具,为用户提供国内可用的API支持,而且还支持微信支付。它实质上为一个国内可用的ChatGPT API代理,会将请求转发到ChatGPT api,再将结果返回给用户。由于api2d的使用方式与chatgpt基本一致,只要应用程序支持设置OpenAI API Host,就可以轻松地使用。

更多详细信息可以查看他们的官网。这篇文章主要介绍两个最重要的地方:1. 价格 2. 使用方法。3. 支持ChatGPT 4.0

  1. 价格API2D按实际使用的Token数量收费,聊天接口价格大约为OpenAI的1.5倍(考虑到国内可以支付和使用,还可以接受)。API2D 使用P作为计费单位,1P=100token,每次调用最低消耗1P。建议通过Github账号注册,这样能够获得50P的免费点数。 image.png

2.使用方法。对于用户来说,找支持填写第三方OpenAI API Host的应用。填入https://openai.api2d.net/和api2d的forwardkey。对于开发者来说,API2D 提供了开发者文档。

利用api2d快速搭建一个属于自己的ChatGPT网站

  1. 注册 api2d。 注册没什么特别的。有一点需要注意:注册的时候建议使用github账户注册,可以获得50P(相当5000token)的额度。
  2. 搭建 ChatGPT-Next-Web。毕竟api是无法直接使用的,所以需要搭建一个网页应用来使用ChatGPT。ChatGPT-Next-Web 是一个支持 chatgpt api 私人 ChatGPT 网页应用。具体可以查看他的中文文档。使用 Vercel 可以免费部署。参考链接:如何在Vercel搭建ChatGPT-Next-Web/。需要注意的是,设置环境变量步骤时,需要额外添加环境变量BASE_URL,值设为stream.api2d.net。设置OPENAI_API_KEY的值为api2d的forwardkey。最后,一定要设置CODE变量,不然别人就能用你的api访问chatgpt,CODE是 ChatGPT-Next-Web 的访问密码,设置了访问密码后,在设置页面填入密码就能使用。 image.png
  3. 绑定域名。如果你有域名,强烈建议绑定自己的域名,然后删掉Vercel分配给你的域名访问。Vercel 分配的域名 DNS 在某些区域被污染了,绑定自定义域名即可直连,而且有些人会根据 Vercel 提供域名的规律找到你的域名然后爆破。绑定域名也很简单。在 Vercel 项目设置添加域名,按照指引添加一条CNAME记录即可。
image.png

api2d还能做什么?

只要应用程序支持设置OpenAI API Host,就可以轻松地使用。如下图的开源项目 memosimage.png

更多项目在api2d的官网找到:

image.png

利用chatgpt实现编程想法的实践-PyPower

2023年3月22日 22:25

https://github.com/eMUQI/PyPower

PyPower

使用chatgpt一段时间后,萌生了一个想法:利用chatgpt辅助我编程。

大致需求是通过运行在树莓派上的网页服务来控制Windows主机关机,同时还可让树莓派发送wakeonlan数据包唤醒Windows电脑。最终实现的效果见上方链接。

代码编写过程

通过了好几天,数十次对话,终于把程序写出了。由于没有经验,这样一个简单的功能花了好几天的空闲时间才完成,中间数次向chatgpt请教网页知识。而且还不断调整需求。

下面是几个主要的提问:

  1. “如何实现利用python远程控制Windows电脑开机和关机。通过网络(局域网内)来控制,需要服务端是Windows,客户端是任何支持网络的设备。”
  2. “能否在Windows开启一个web服务,通过在局域网内网页来控制电脑关机呢”
  3. “如何添加身份验证呢?能否添加一个确认关机功能,直接访问网页就执行光机操作很容易误操作”
  4. “程序的架构是:Windows端作为服务器,只提供接口不需要渲染网页。树莓派运行网页服务,通过访问树莓派的上运行的网页来控制Windows关机。通过python来实现。”
  5. “修改树莓派的代码,用变量来设置 服务器的端口和ip”
  6. “不要修改代码原有的功能,在代码的基础上,添加一个检测电脑端服务是否开启的功能,并显示到网页上”
  7. “现在根据我刚刚给你的两个代码文件,判断项目内容。为这个项目写一个README”

经验&技巧

  1. 选择你擅长或者至少熟悉基础语法的语言。chatgpt生成的代码如果你不能大致看懂,那么让他写复杂一点的代码给你就很难了,chatgpt生成的代码可能有错误。比如说在这个项目的例子中,我只懂python的基础语法,对于用到flask框架,request wakeonlan库我都不了解。但是通过让chatgpt写上注释,我能做到简单的debug。
  2. 每次和chatgpt对话,当你向他要代码时,可以在最后加上“请加上合理的注释”。或者在对话最开始和chatgpt约定,只要发送代码都加上易读的指数。
  3. 由于chatgpt的会话限制,有可能chatgpt无法一次将完整内容发给你,内容会戛然而止。可以试着和chatgpt说“继续”,但是也有可能会出现chatgpt前言不搭后语。或者不同部分的功能分别询问,有意地控制chatgpt的内容不要超过限制。
  4. 当项目逐渐成型,代码变得很长,可以试着和chatgpt说:“请只给我修改或者新增的部分”。
  5. 如果让chagpt设计css,可以尝试让他使用bootstrap,效果还可以。

树莓派使用LUKS加密移动硬盘分区

2022年6月5日 14:38

前言

之前写过如何用树莓派挂载移动硬盘并使用SMB在局域网共享,使用了很长一段时间也没有什么问题。但是近期突然想到,这个移动硬盘里已经有太多私人资料了,虽然SMB和树莓派都有密码保护,但是硬盘本身却没有做任何的保护。一旦硬盘遗失,里面的数据就会直接泄露。于是就产生了加密硬盘,使用树莓派进行解密再使用SMB进行共享的想法。

关于加密方式,考虑过使用veracrypt加密,但是相比之下还是LUKS(Linux Unified Key Setup)更加“原生”,不依赖客户端,用起来也比较方便。

文前提示:本文不是针对完全不会的小白的教程,需要有一定的Linux基础,尤其是针对分区的操作,一定要看清楚分区名。进行操作前请备份好自己的数据。遇到问题欢迎在评论区留言。

加密指定分区

  • 树莓派配置:
Raspberry Pi 4b 4gb
OS: Ubuntu 20.04.4 LTS
Kernel: aarch64 Linux 5.4.0-1062-raspi
  1. 查看硬盘
sudo fdisk -l     

找到想要加密的硬盘分区,我这里已经提前分好区了。我这里把硬盘分成/dev/sda3/dev/sda4/dev/sda3作为日常盘,外出时使用。/dev/sda4作为加密盘,在树莓派上使用smb共享。

fdisk.png

本文中要加密的分区是 /dev/sda4 ,如果你参考了本教程的命令,记得要将后文中的所有 /dev/sda4 替换为你要加密的分区

如果你还没有分区,可以使用fdisk进行分区,具体用法可以查看 Fdisk-archwiki)。

  1. 格式化分区

提前备份好数据,然后格式化要加密的分区。将/dev/sda4替换为你的要加密的分区,注意提前备份好数据。

 sudo wipefs -a /dev/sda4    
  1. 加密分区

使用 cryptsetup 创建加密容器,使用 --type 指定使用luks2版本。使用 --cipher 指定加密算法,如果不指定默认会使用 aes-xts-plain64 ,但是树莓派的芯片不支持AES加速,加密解密会比较慢,使用 Adiantum 会比较快,具体可以看 LUKS-on-Raspberry-Pi

sudo cryptsetup --type luks2 --cipher xchacha20,aes-adiantum-plain64 luksFormat /dev/sda4

执行命令后,需要输入大写的 YES 确认执行操作,然后设置好密码。 创建加密容器.png

  1. 映射容器

加密后的分区需要解密才能使用,使用luksOpen解密分区。下面的的命令会将加密分区映射到/dev/mapper/cdata

sudo cryptsetup luksOpen /dev/sda4 cdata
ls /dev/mapper/
luksopen.png
  1. 创建文件系统

加密容器第一次使用的时候需要创建文件系统,例如我创建的是 ext4

sudo mkfs.ext4 /dev/mapper/cdata
image.png
  1. 挂载加密分区
sudo mkdir -p /media/CRYPT
sudo chmod 776 /media/CRYPT
sudo mount /dev/mapper/cdata /media/CRYPT

开机自动解密并挂载

  1. 创建密钥

由于需要使用密钥文件才能开机自动解密,我们需要先创建密钥文件,密钥文件可以使用自动生成的随机数,也可以自行创建。我创建的密钥文件是 /keyfilec

sudo cryptsetup luksAddKey /dev/sda4 /keyfilec
ADDKEY.png
  1. 验证密钥
sudo umount /dev/mapper/cdata    //取消挂载
sudo cryptsetup luksClose cdata  //锁上分区
sudo cryptsetup luksOpen /dev/sda4 cdata --key-file=/keyfilec   //使用密钥文件解密

我们取消挂载,然后将分区锁上。使用密钥文件来解密,没有看到任何提示,就说明我们已经成功使用密钥文件来打开加密分区了。 验证密钥.png

  1. 自动挂载 查看分区的UUID,后面自动解密时需要用到。
blkid /dev/sda4

sda4uuid.png 编辑 /etc/crypttab 自动打开加密分区,添加下面的内容。

cdata UUID=a8c7a856-dfe0-4273-b546-13b2cdf50f12 /keyfilec luks

编辑 /etc/fstab 自动挂载加密分区,添加下面内容。

/dev/mapper/cdata /media/CRYPT ext4 defaults 0 0
  1. 重启之后,就可以验证加密分区是否已经已经自动挂载了。

SMB共享

我的树莓派上已经配置好了smb,具体可以参考这篇文章的 配置SMB 部分。

sudo nano /etc/samba/smb.conf

修改 /etc/samba/smb.conf 在最后添加以下内容。

[share]
comment = share folder
browseable = yes
path = /media/CRYPT
create mask = 0700
directory mask = 0700
valid users = ubuntu
force user = ubuntu
force group = ubuntu
public = yes
available = yes
writable = yes

修改好配置后,重启smb服务。

sudo service smbd restart

参考文章

cryptsetup 文档

Frequently Asked Questions Cryptsetup/LUKS

Configuring LUKS: Linux Unified Key Setup (推荐)

LUKS on Raspberry Pi

使用RSS在泛用型播客客户端订阅《八分》

2022年3月21日 22:30

《八分》是一档由梁文道和看理想团队共同打造的文化类音频节目。时不时睡前听一听还是蛮有意思的。但是《八分》第四季只在喜马拉雅看理想App更新。其他平台的原有的《八分》都无法接收到第四季的更新,原先看理想提供的 RSS Feed 也已经失效不再更新。

想要听《八分》就只能下载「看理想」App或喜马拉雅独家收听。不想使用这些平台,想在泛用型播客客户端收听《八分》有什么方法呢?

太长不看版本

解决方案:使用RSS订阅播客。(具体原理看后文)

RSS地址: https://rsshub.app/ximalaya/album/51101122/0/shownote

AntennaPod为例:

AntennaPod1.jpg
AntennaPod2.jpg

https://github.com/AntennaPod/AntennaPod

RSSHub

RSSHub 是一个开源、简单易用、易于扩展的 RSS 生成器,可以给任何奇奇怪怪的内容生成 RSS 订阅源。RSSHub 借助于开源社区的力量快速发展中,目前已适配数百家网站的上千项内容.

RSSHub.png

想起之前了解到的一个开源项目RSSHUB,能够各种各样的的网站生成 RSS 订阅源。部署后,请求服务器特定的路径,就能得到对应 RSS。 请求路由时,RSSHub 会按照给定规则请求源站数据,然后以 RSS 格式输出。具体可见:RSSHub 文档

使用RSSHub服务器

首先在 RSSHub 文档页面 搜索喜马拉雅相关的路由。

RSSHub-search.png
RSSHub-ximalaya.png

找到我们需要的路由,希望显示播客shownote,选择 专辑(输出 ShowNote)。 可以看到路由是 /ximalaya/:type/:id/:all/:shownote?,必选的参数有 typeid。 根据指引填写参数,喜马拉雅《八分》的链接是:https://www.ximalaya.com/album/51101122 。那么对应的 typeid 就是 album51101122

我们使用RSSHub提供的服务器,补充好网址,得到的链接就是:https://rsshub.app/ximalaya/album/51101122/0/shownote

接下来只要将这个RSS地址添加到任意支持RSS的播客客户端就可以愉快地收听了~

自己部署

RSSHub的演示地址为 rsshub.app, 缓存时间 20 分钟,可以随意使用。但有些路由路由有反爬严格标记,如微博、知乎等,意味着目标网站有严重的反爬策略,demo 无法确保可用性。如果你需要更高的可用性,建议自建来提高稳定性。

自己部署RSSHub的方法也有很多,RSSHub 支持 DockerDocker ComposeAnsible手动部署 等方式。详情可以查看 RSSHub文档关于部署的部分

如果有问题可以在下方评论区提问,欢迎友好交流~

Python Wordle 解题小帮手

2022年1月24日 22:28

前段时间看了少数派的文章《最近突然火起来的 Wordle 是什么?平平无奇的它凭什么成了「万人迷」》,对Wordle 产生兴趣,玩了几天。可能是离开校园时候很久没有学习英语了,也可能是词汇量不够,总是解题失败。遂产生了写一个Python 程序来帮助解题的想法。

Wordle 规则介绍

Wordle 每天会更新一个5个字母的单词,在6次尝试中猜出单词就算成功。每个猜测必须是一个有效的单词(不能是不能组成单词的字母排列)。

每次猜测后,字母块的颜色会改变,颜色含义如下: Wordle规则.png

程序编写

单词数据

Wordle的单词数据直接写在网页源代码里,进入Wordle,按F12查看源代码。 Wordle源码.png

我们将这些数据提取出来就能的到Wordle单词列表,网上已经有人整理成json文件,同时还提出了SOARE是最好的起始词,有兴趣的可查看《The Best Starting Word in WORDLE》

代码编写

获取单词列表之后,就可以开始代码的编写了。 代码的基本思路就是,按照灰色、黄色和绿色三种情况分别处理,排除不符合的单词。

代码编写思路:

  • 包含灰色色块字母的单词排除
  • 不包含黄色色块字母的单词排除
  • 包含黄色色块字母但是还在错误的位置的单词排除
  • 与绿色色块字母位置不符合的单词排除

代码开源在Github:eMUQI/wordle-helper

import json
with open("words.json", 'r') as f:
data = json.load(f)
words = data['words']
# 初始化
fault = "" # 灰色色块
pos_wrong = ["", "", "", "", ""] # 黄色色块
right = ["", "", "", "", ""] # 绿色色块
# 提示
print(40*"-")
print("The Best Starting Word in WORDLE may is 'SOARE'")
print("for result, gray:0 yellow:1 green:2")
print(40*"-")
for i in range(5):
# 处理输入,记录字母
guess = input("{0}:".format(i+1))
results = input("result:")
for n in range(len(results)):
if results[n] == "0":
fault = fault + guess[n]
elif results[n] == "1":
pos_wrong[n] = pos_wrong[n] + guess[n]
elif results[n] == "2":
right[n] = guess[n]
else:
print("bad input")
# 生成建议
temp_list = []
for word in words:
# 检查灰色色块,也就是错误的字母
flag = True
for f in fault:
if f in word:
flag = False
break
if not flag:
continue
for n in range(5):
# 检查绿色色块,也就是正确的字母,字母和位置是否符合
if right[n] != "" and right[n] != word[n]:
flag = False
break
# 检查黄色色块,也就位置不对的字母
if pos_wrong[n] != "":
for ps in pos_wrong[n]:
# 检查是否有黄色色块字母
if ps not in word:
flag = False
break
else:
#检查是否还在错误的位置
if word.index(ps) == n:
flag = False
break
if not flag:
continue
temp_list.append(word)
print("suggest:", temp_list)
word = temp_list.copy()
print(40*"-")

小结

本身写个程序是为了练练手,满足一下写代码的快乐。 经过实际测试,发现基本上到第三轮或者到第四轮猜测,可以选择的单词就非常少了,辅助效果不错。不过如果用这个程序解题,那么解题的乐趣基本上也就没有了。慎用,哈哈。 usage.png

❌
❌