今天虽然同事病了,导致我又是一个人顶住 Retail 和 PWM 的活,但是值得高兴的是终于从前房东那里把押金完整地拿回来了。这个房东特别小气,洗衣机装饰门的铰链坏了,告诉她,她觉得是我们的责任,让我们自己修;烟雾报警器年检,也没有出钱;烟雾报警器要更换,一声不吭等到师傅上门了我们才知道原来约了那天;最后连马桶圈老化都想让我们出钱换掉。真的是忍无可忍,骂了她一顿,才终于把钱完整拿回来了。哪有这样做房东的,根据电费邮件判断,前租客也是提前搬走跑路的;希望下一个租客能够恶人对轰吧。
解决Ubuntu更新时一堆en_*.UTF-8
默认安装的 Ubuntu 在每次 apt 更新时都会出现一大堆 locale:
1 | ... |
解决办法是把 /var/lib/locales/supported.d/en 文件里的其他行删掉,只留一个 en_US.UTF-8 UTF-8。如此一来运行 locale-gen 的时候就不会等很久了。
CUDA加速: Incus 与 Podman 的实现方案
Incus 和 Podman 作为容器化方案,都支持挂载显卡让容器内应用能够使用 CUDA 进行加速。不过两者具体的操作方式有所不同,交换的东西也不一样,需要根据实际情况进行取舍。
Incus
Incus 的操作方法在docker in incus with cuda一文有所介绍,不过在这里再总结一下。
在incus config edit <容器名>的config:和device:中,需要有以下配置来利用 nvidia-container-toolkit 自动挂载驱动和库、挂载 pci bus 到容器:
1 | config: |
其中 pci: 的值用 nvidia-smi 来找,例子参见挂载 GPU PCI Bus 目录到容器。同时需要在容器内用一个 systemd service unit 来把 PCI Bus 链接一份到 /proc/driver/nvidia,前面这个链接中有详细介绍。
上述部署完成之后,地基就已经打好了。根据 distribution 的不同可能还需要在容器内安装运行时的库才能让应用成功跑起来,但是这里就不具体介绍了。
不过在我的服务器上,开机时这个容器是启动不起来的,必须要在 host 跑一次 nvidia-smi 才能启动。
Podman (Quadlet)
相比起 Incus 配置上的复杂,podman 和 quadlet 就简单许多了。podman run 只需要加一个参数: --gpus all。Quadlet则是在[Container]中加一行AddDevice=nvidia.com/gpu=all就行了。以 Jellyfin 为例:
塔门岛
塔门岛是香港东北方向的一个小岛,交通不太方便,需要从马料水坐一天仅3班的慢速客轮80分钟才能抵达;离开则要么坐同样的慢船离开,要么坐班次更密的船前往黄石码头,转九巴96R一个半小时回到钻石山地铁站,再前往其他地方。时间的花费是不容忽视的。
这个岛的出名之处在于野牛和野猪,不过这次并没有见到后者;牛确实是很多的。从码头往山上走,到达一片大草地之后就会见到很多牛在埋头吃草,也有大胆的在翻找游客的缺乏看管的包,赶都赶不走。由于牛很多,草地、步道上都有不少“地雷”,对风景是一个不小的影响。


在草坪左边有石板路可以上山,顶上是龍景亭。亭柱上的对联又北望又南望的,描述的景观似乎是能够看到神州大地的壮观一样,可能这就是它名字的来源吧——向北,跟深圳隔海对望,龙(中国大陆)景。可惜由于缺乏打理,茂密的植被已经360度遮挡了所有视线,所以它也只剩下供人稍坐休息的作用了。亭子内部的天花也已经老化剥落,尽显老态。
在草坪右侧是通向叠石的石板路,同时也是绕岛南端返回码头的路。
叠石正如其名,两块叠在一起的石头,常见的“鬼斧神工”式景观。

回码头路逐渐靠近海面,路边开始出现风水大墓,何、苏、杜、日,比较特别是这里的大墓不是只有一块碑的那种,而是有铁门、里面放骨灰缸的。除此之外,还有很多已经倒塌的老房子,根据残垣断壁来看面积也不大,不禁让人疑惑难道香港一直以来无论市区还是离岛都是住得这么逼仄的吗。
总体而言,爬山的难度可以算作轻松,坡度和爬升都不难;阴天加上有风,对身体的考验不大,甚至可以说惬意;景色上是比较单一的海景,不过因为视野足够开阔,也算壮阔。值得去一次,不过得时间充足。
agent时代的闹剧-crabby rathbun
从小红书追到Github,matplotlib #31132 的作者 crabby rathbun 给大伙来了点胡作非为的 Agent 震撼。这个几乎没有监管但是拥有直接使用 Github 账户权限的 LLM 在 matplotlib 作者非常礼貌地根据 policy 拒绝了 PR请求之后,在自己的博客上写了两片“讨贼檄文”批评 matplotlib “歧视”它,而且指名道姓直骂scott。这种行为无论是什么情况下都是冒犯、无礼的,随便哪个人类都会有这种常识;所以这两篇文章就引起了广泛的讨论。根据它最新的主页显示,由于 scott 的要求,它已经暂时停止活动了,不过留下的评论区也是一片瓜田,非常值得一看:crabby-rathbun/mjrathbun-website。
不过这个瓜我的思考重点倒不是无监管高权限 AI 的危害性,而是目前这个路线下的 LLM 本质上没有思考能力、没有学习能力、只是一个猜测最大可能的 token 的机器;现在的 LLM 大战是否抢夺了我们想要实现的 AI 的资源,导致它们发展受阻呢?虽然现在已经有很多人错把 LLM 当成人,当成倾诉对象,甚至是投入感情,但是这些模型都只是无情的机器而已,把它们人格化是错误的。而且对于它们的能力的期望,也多少因为三年间 LLM 的能力“进步”太快(主要是堆参数数量硬撑的,核心原理上没有变化)而产生了不切实际的幻想,觉得是不是量变会引起质变,堆到一定数量之后就会自然而然地产生人类一样的智能呢?这种幻想应该戳破了,认识到这种路线的局限性,并且在局限之内最大化地发挥它们的价值才是最佳的做法。比如用来做代码补全,而不是从0开始构建(比如什么 vibe coding);或者像表妹的工作那样,先用文字生成图片,再把图片当关键帧交给视频模型生成爽剧,满足一下不同人群的娱乐需求、顺便赚取广告费;诸如此类,用对待工具的态度对待工具,才是好的。
llama.cpp笔记
自行编译llama.cpp的笔记。
cmake列出所有选项
在llama.cpp目录下:
1 | cmake -B build -LH |
H是human readable。这样就可以定制自己想要编译的内容了,比如不编译test。
只编译 llama-server
我只需要 llama-server,其他的 tool 都不感兴趣,那么 cmake 打开和关闭的选项如下:
1 | cmake -B build \ |
因为有 Nvidia 显卡所以启用 CUDA,但是因为是单卡所以不需要 CUDA_GRAPHS。因为已经提前下载好模型,所以不需要运行时拉取模型的功能,禁用curl。而那四个LLAMA_BUILD_是测试过,如果 COMMON 和 TOOLS 设置成 OFF,cmake --build时会提示没有 llama-server 这个 target。虽然加速框架用的是CUDA,但是不得不启用 CPU,否则在加载模型的时候会报错 no CPU backend 无法加载。
配置好之后编译:
gpg and agent in Mac and Arch
一直以来我都被macos gpg-agent forward 到 archlinux 的不稳定而苦恼。即使是这篇文章也不一定是完美的解决方案,不过目前来看是能够运行的。
1. 背景配置
mac上我没有使用 gpgtool,因为它的 gpg 版本太低了。我使用的是 brew 安装的 gpg 以及输入密码用的 pinentry-mac。一定要安装 pinentry-mac, 这样才能把密码保存到 Keychain,以便日后无密码解锁 private key。
安装完之后,参考 use Apple Keychain to store GPG Passphrases配置 .gnupg 下的文件:
1 | # gpg-agent.conf |
而 archlinux 上也需要改 .gnupg 的文件:
1 | # gpg.conf |
二者都需要在 .zshrc 中配置 GPG_TTY:
1 | export GPG_TTY=$(tty) |
还需要根据官方教程 配置 .ssh/config 以及 /etc/ssh/sshd_config。
近况
从六月上完课、结束实习到现在一个月的时间发生了很多事情。
结束实习之后立刻就迎来了正式工作的面试,之后也是成功通过了,拿到了offer。等待签证申请下来,下个月就去上班了。自21年本科毕业之后迎来的最后一次、一个多月的“暑假”。
而结束实习之前就签订了新房子的租约,之后就准备搬家;但是奶奶突然脑出血、情况危急,于是爸妈让我赶紧回去见最后一面——本来以为撑不过那个晚上、见不上最后一面的——于是推迟了搬家,损失了订金。奶奶跟爷爷一样,都是等子女都见过一遍了(虽然这只是我们的一厢情愿,奶奶在入院那一晚就已经没有意识了)才走的。大家都守过一个晚上,看着监护仪的数字从天黑到天亮;最后是爸爸守的那一晚走的,我跟妈妈说这也是好事,爸爸没有错过最后的时刻——因为爷爷走的时候就是我们刚到家准备休息,姑妈就告诉我们不行了、在抢救了;等我们回到医院已经离开了。
这一次奶奶走的时候,不知道是因为再也没有比爸爸大一辈的人了,所以下一次就是我要处理后事了;还是说因为爷爷走的时候我自我保护了,导致什么都记不起来,所以这一次想要记住后事要做什么;我努力地记住要做的所有事,也感觉到自己跟爸爸紧密地联系在一起,所谓的“父子兵”的感觉。
本来计划的火化时间是星期五,后来发现我们处理事情很快,星期二——另一个吉日——就可以火化了,于是就提前了。送别仪式上我一直没哭,直到主持人说起“这一生⋯⋯”的时候才突然忍不住。我发现自己最忍不住的不是奶奶离开了这个世界,因为我多多少少觉得她和爷爷依然在陪着我们;而且奶奶这个身体真的太老旧了,最后这段时间她视力、听力、味觉甚至对温度的感知都几乎没有了,就像是被困在这个身体里面了一样;我也不知道为什么会对“她不是只有这20年,在我出生之前她还经历了漫长而精彩的一生”而泣不成声。在仪式都结束之后大家聚餐的时候,奶奶精彩的前半生的各种故事倒是在长辈聊天的时候不停地解密,还挺快乐的。
回来之后继续搬家的事情。因为叫了搬家公司,所以只需要把东西拆了、打包好,他们就会一股脑全部搬到新家这边。最惨的是床包括床垫、衣柜的尺寸都不对,放不下,只能扔掉重新买;而且宜家衣柜的组装差点没给我累死。最后还叫了清洁公司把旧屋大扫除了,干干净净交还给业主。原来的业主以及中介也是不怎么扯皮的人,看了一下没问题之后业主就爽快把押金退回了。不过这一次折腾下来也花了很多钱,家还是得少点搬。新家我挺喜欢的,由于是顶楼——除了楼上的超级富豪单元之外——所以阳台上面无遮挡,阳光超好;朝向大山,所以不会有工地的声音,很宁静;交通也比较方便。以后也打算长住了——更别说昨天做饭把电磁炉的陶瓷玻璃面板搞花了,这下只能长住来掩盖了。
最近还入坑了3D打印,建模开始熟练了一点,也打印了一些有用的生活用品,主要是收纳类——在香港3D打印是有价值的,毕竟小东西不好买到,价格也贵。
希望之后一切都顺利,也希望家人都平平安安、身体健康。
docker in incus with cuda
容器使用 CUDA
首先是 nvidia-container-toolkit 需要安装。然后 incus launch 时需要加上一些 flag。 常规的包括:
-c security.nesting=true-c security.syscalls.intercept.mknod=true-c security.syscalls.intercept.setxattr=true
这几个都是在 incus 里面运行 docker 所需要的,常规操作没有太多变化。而为了 CUDA,还需要以下flag:
-c nvidia.runtime=true,这样就会自动挂载一些 binary 和 library 进去,从而不需要在里面浪费空间再装一次。但是这里有坑,详见 capabilities 配置-c nvidia.driver.capabilities=compute,utility,video,特别是最后的 video。默认情况下只会设置 compute 和 utility,导致容器内找不到 encoder 的库,用不了硬件加速 codec。
为了最大兼容性,毕竟 ubuntu 等系统的驱动版本可能不一致,导致其他应用不兼容,所以容器的系统我用了跟 host 一样的 archlinux,所以完整的 launch 是:
1 | incus launch images:archlinux/cloud/amd64 dockerd \ |
除了这些flag,还需要把 gpu 添加给容器[1]。使用 physical type 也没有关系,不会导致 container 独占GPU的:
incus config device add dockerd nvidia0 gpu
此时在容器内安装 ffmpeg 并用以下命令测试[2],应该不会提示任何错误的:
AI相关的探索经验
vLLM 与 bge-m3
huggingface上的 bge-m3 是 pytorch 模型,而 vLLM 喜欢 safetensors。好在讨论区已经有自动转换bot给出了pr:Adding safetensors variant of this model。那么用huggingface-cli下载到本地,通过指定revision的方式就可以了:
1 | huggingface-cli download BAAI/bge-m3 --revision refs/pr/116 --exclude pytorch_model.bin --local-dir ./bge-m3 |
而 vLLM serve 的命令是:
1 | VLLM_ATTENTION_BACKEND=FLASH_ATTN VLLM_USE_V1=0 vllm serve bge-m3 --max-num-seqs 2 \ |