[杂记] 一些零散的思考与近况

几度提笔想写点什么,但总是abort,请原谅本文的话题跨度

ai

总是绕不开这个话题

人机协同

最近见到了很多人对vibe coding各式各样的观点。

  • 强烈抵制的一派认为ai写的都是slop,给出的理由也很具体,在各种各样的场景下ai犯了各种各样愚蠢的错误——而人不会的时候至少不会乱用

面对着一个个具体的代码例子,我很难不赞同,ai就是这样一知半解却又表现得很懂的样子。

  • 一些前ai时期过来的,对ai使用依然保持克制

  • 学校课程作业中的代码部分,手写应该已经几乎灭绝了

  • 羽则是强调如何在vibe的同时保持自己的思考

对于这个问题,对我影响最大的还是这篇文章

当我们对ai许愿的时候,抽象泄漏是必然的。对于我熟悉的后端程序,这体现在代码的可读性、健壮性、性能、已有抽象的完整性、对外部的依赖、日志记录内容、代码行数以及 “品味”、包括各种规范和习惯风格…对于前端,除了刚才列举的还有直接展示给人的ui/ux

对代码质量要求越严格,越会觉得ai也许能省体力但不太能省脑力

与之相对的,另一面则是放弃对项目的可理解性,面向一个清晰的目标goal就好了,完全解放大脑。

那么抽象泄漏真的重要吗?如果ai代码ai读,可读性似乎就不再需要关注,性能在大多数情况下,ai也不会做得太差,至于建立的抽象被破坏,还能跑似乎也不是不行…这样一来,大部分抽象泄漏似乎都不那么重要?

只能说真正的会读心的许愿机还没有造出来,在此之前,一个项目还是需要可理解性。

这样一来,一个项目的代码实现变得cheap,而前期制定技术方案、抽象、架构等等变得重要。结论不变,能省体力但是不能省脑力。

前端

似乎周围人们对于喷ai前端这件事从一开始就没有停过

从早期的蓝紫配色,到现在 (色块)标题· 意义不明的文字 \n 意义不明的总结

好吧也许确实需要一点设计,好的前端绝对不是靠一些skill就能得到的

其实非前端代码也是类似的道理,只是不会被看见罢了。

至于我的态度?我的接受度应该算比较高吧,几轮image 2.5 + opus 5.5 + 人工微调 已足够让我满意

如何高效地烧token

自从买了几个20x 就经常遇到要重置了额度刷不完的苦恼,久而久之对烧token也有了一些心得:

降低缓存命中 如果目标是把额度耗完,就要理解计费原则。以GPT-6-astra 为例,它的输入/输出/缓存 价格分别是$10/$50/$1,而这三者的token用量占比大致是9 : 1 : 149,最终价格分布是 31:17:52。总结一下就是,第一,缓存命中的价格只有十分之一,token用量占比远大于其余;第二,输出以远低于其余的token用量贡献了极其可观的额度消耗。

那么优化也要据此展开:

缓存是依据模型而建的,我们可以在任务中更换模型,如果有多个账号还可以负载均衡一下(多缓存几次)。不过缓存的保留时间还是蛮长的,听说tibo又要改成永不过期,所以效果有但不多。

缓存依赖的是前缀,如果可以在所有系统提示词前面塞一个时间戳,那就再好不过了。只是这需要魔改客户端,不够好。

OpenAI 需要在请求里标识缓存桶,用一些别家的agent客户端就可能没有这个适配,会有奇效。

增加输出 思考内容也是输出的一部分,拉高思考就可以得到更多输出价格,不过也就仅此而已了,这个操作空间不大。

拖长任务轮次:如果目标只是把token那一栏堆得高高的,就要换个思路。根据刚才的数据,输入是毫无疑问的主要来源,更具体而言,测一轮鹈鹕一问一答,思考得久但吃不了多少token。实时computer use每次都请求并快速响应,不仅上下文很快就满了,轮次和持续时间也长。而且一旦触发了上下文压缩缓存命中也受影响,再好不过了。

所以最终结论很朴素:开一个大仓库,给一个不需要人理解的又长又模糊的任务,最好agent自己可测试,开好auto、fast、max然后去睡觉,嗯goal是对的。

rust

modules or crates

前段时间读了两个项目,代码量都在十万行rust这个数量级,但是组织方式区别还是蛮大的。一个拆分成了十数个crates,另一个则是一整个crate。

crate是编译和分发的单元(事实上编译和分发二者并不天然绑定,后者更合适的称呼是package,只是习惯上都叫作crate),如果某些部分需要独立分发,拆分天经地义

如果项目比较大,部分代码 依赖/被依赖 比较多,为了编译友好,拆分出来也是应当的

那么如果项目没有大到编译极慢的程度,也没有独立分发需求呢?

crates的依赖关系是DAG,而modules则允许循环依赖,因而前者对项目架构要求更高。

所以如果让我设计项目架构,我会倾向于多crates,理由也很直接,不灵活的依赖关系能一定程度上约束agent对现有抽象的破坏

linter

clippy默认开启的代码规则只有很少的一部分

  • must_use 表示返回值必须被使用。
  • clippy::must_use_candidate :一个对外导出的函数或方法,返回值不是 (),并且看不出副作用(不接收 &mut 参数,也不修改外部状态)。这种函数调用后丢掉返回值就等于什么都没做,所以 clippy 要求标上 #[must_use]
  • clippy::large_enum_variant : 枚举类型的实际大小是其中最大的那个,所以差得太多会造成空间浪费,一个直接的解决方案是加一层Box
  • cfg_not_test : 有时候出于方便测试等目的,会使用cfg(not(test)) 和 cfg(test)写两份代码。直接后果就是有代码永远不会被测试,即使是古法这种逻辑也需要谨慎处理,agent时代这种约束就更有意义了。
  • dead_code : 不解释了

有时间单独整理整理吧,这里可写的太多了

一些比赛

hpc

超算队选拔赛开始了,token烧不完的主办方拿出了 [AI] model 1 (GPT-6-astra)作为斩杀线开始了全自动解题,领先一众选手,然后是[AI] model 2(deepseek v4.1f),model 2.1(搭载了dsh),model 3(glm-5.3)和短短几小时斩杀了所有人满分登顶的model 4(fable 5.1)

这就是我作为[AI] model 5 (opus 5.5) 入场前的局面了。接下来opus5.5 成功全自动地将fable 5.1 斩杀,满分登顶。

拉高思考还时不时能找出新思路从而扩大分差

评价为没有人类了

ctf

说来惭愧,近半年分给ctf的时间着实有限,现在看起来已经被agent斩杀了

虽然ctf场景下不那么容易让astra 和opus / fable 火力全开,但是deepseek v4.1 flash 也足够碾压我了

和hpc被agent斩杀类似,这种反馈明确目标清晰的东西,agent最喜欢了。

显然当前这些比赛还没有找到一个和agent和平相处的方法,不知道未来会发展成什么样子

羽:直接面试吧

大修网

羽推荐了这篇文章,严肃阅读学习

自从开始折腾服务器上线服务,就恶补计算机网络运维知识,每天看着时不时掉线的服务与莫名其妙超高的延迟就来气。

现有的服务器网络架构大概是这么一堆:

所有设备都可以通过tailscale连接,包括:

  • 树莓派 提供对外服务,使用cloudflare tunnel完成对公网的暴露,包括aucept.in的某些子域名(不包括博客本体),物理位置在学校。
  • gl-mt3000 处理有安全需求的流量,使用tailscale 提供的app connector转发特定域名的流量。物理位置在天涯海角
  • vm 跑着部分对内服务,尚未充分利用,物理位置也在学校
  • arch linux 我的轻薄本,目前24h挂在公司,但会时不时拿回去,尚未充分利用
  • mac 我的办公本,可以认为24h 跟着我往返学校和公司

其中最大的不稳定因素就是cloudflare!

尝试效仿一些前文故事agent优化一把梭,但是失败了,果然我是不可替代的

树莓派 -> cloudflare

树莓派对cf 走ipv4 + HTTP/2,这一段是第一个不稳定链路,经常报一些1033错误。cf 在国内是没有节点的,所以实际会连到香港。

唔,关闭ipv6 是因为此前发生过一次拥塞,上行极慢,而绑定ipv4以后暂时还未遇到。

还有quic。理论上说基于udp的HTTP/3 应当在链路不稳定时表现得更好,然而依然遇到了一次较长时间的超时,所以也关了。

想不到有什么便宜的优化方法,鉴于最近1033见的比较少,先维持原状吧。

gl-mt3000 -> ?

用的是2.4GHz 频段,寄宿在另一个wifi下,似乎没有网线可用。我对此无能为力。

树莓派 -> gl-mt3000

这段流量横跨太平洋,依赖ts打洞连接,走wireguard,嗯udp,听起来就很悬,实际上能有1-2 MB/s,在请求高峰时,比如遇到codex把一串图片一遍遍传来传去就会TIMEOUT。

不过重新测了一下,瓶颈在于这个2.4GHz的网络,本身质量就不太好,收发流量全经手一遍就更慢了,不过,无能为力。

user -> cloudflare

这又是另一个重灾区,平时在公司卡得要死,以至于现在设备后台一直跑着一个探测自动选择cf 节点的脚本。

手机开着流量就不会有这个问题,说明多半是公司网络出口->cf节点的延迟,唔,无能为力了。

me -> 树莓派

这是ssh 的链路,走的是tailscale ssh,在公司的时候打洞就没有成功过,统统走的中继!

分析一下:

ts的STUN服务器全都在海外,它探测到的树莓派出口是教育网出口,同时我的设备在国内,树莓派发过来的包走联通的出口。

回顾打洞过程,需要我的mac设备和树莓派同时向彼此发包,以让防火墙放行,这需要彼此知道彼此的地址,借助STUN服务器完成,但是STUN 服务器告诉mac的是教育网出口,而树莓派发来的包走的是联通出口。

这样一来,教育网出口的防火墙就会拦截mac的数据包,因为树莓派从没有通过这个出口向mac发请求过,另一侧同理,最后两边互相一个包都收不到。
按照这个猜想,树莓派 -> gl-mt3000 应当能打洞成功,实验结果表明确实是这样!

那么只要在mac的候选地址里加上树莓派对应的出口就可以了,官方客户端里有个现成开关 TS_DEBUG_PRETENDPOINT,借助一个公开的STUN服务器探测一下树莓派到我的出口即可

很好啊,效果立竿见影,本来肉眼可见的延迟消失了。接下来在后台维持一个保活脚本,这条链路就算修好了!

项目

这能说吗,这好像不能说。

worktree 与 diff

如何愉快(一点也不)地看diff呢,不同的人有不同的偏好,我当然是lazyvim插件派:

return {
  "sindrets/diffview.nvim",
  cmd = { "DiffviewOpen", "DiffviewClose", "DiffviewFileHistory" },
  keys = {
    { "<leader>gvv", "<cmd>DiffviewOpen<cr>", desc = "Uncommitted changes" },
    { "<leader>gvm", "<cmd>DiffviewOpen origin/main...HEAD --imply-local<cr>", desc = "vs origin/main" },
    { "<leader>gvp", "<cmd>DiffviewOpen origin/main...HEAD<cr>", desc = "HEAD vs origin/main" },
    { "<leader>gvu", "<cmd>DiffviewOpen @{upstream}...HEAD<cr>", desc = "HEAD vs remote" },
    { "<leader>gvw", "<cmd>DiffviewOpen origin/main<cr>", desc = "Worktree vs origin/main (direct)" },
    { "<leader>gvl", "<cmd>DiffviewOpen HEAD~1..HEAD<cr>", desc = "Last commit" },
    { "<leader>gvf", "<cmd>DiffviewFileHistory %<cr>", desc = "Current file history" },
    { "<leader>gvo", ":DiffviewOpen ", desc = "Custom" },
    { "<leader>gvq", "<cmd>DiffviewClose<cr>", desc = "Close" },
  },
}

用起来很舒服

群友:“一点也不agent native”