0%

设想这样一个搜索相关性模型:用一个 0.5B 量级的小模型,把 item 和 query 拼成一条序列送进去,取最后一个 EOS 位置的隐状态,接一个 MLP 做相关性分档。item 侧拼着标题、属性、详情,动辄上千个 token;query 侧只有几十个。同一条 item 会在许多不同的 query 下被召回,每一次都要连同 query 从头算一遍。于是我们自然会想,能不能把 item 预先压成一小段 KV 存下来,在线只让 query 对着这段 KV 做注意力,把 item 那上千个位置从在线计算里拿掉。

这个想法与 gisting 很接近(Learning to Compress Prompts with Gist Tokens,Jesse Mu、Xiang Lisa Li、Noah Goodman,NeurIPS 2023)。此篇前半讲这篇论文做了什么,后半讨论把它搬到相关性任务上以后,哪些地方成立,哪些地方要改,哪些地方搬不过去。

阅读全文 »

越狱的 iPhone 上,APP 进程中可能被插入任意代码。对于聊天软件来说,这最多意味着多出几个主题或手势。这属于功能上的定制,无伤大雅。但对于金融 APP 来讲,这意味着用户可见的界面和实际执行的逻辑之间,不一定再有可靠的对应关系。

例如说……

  • 注入代码可以读 App 沙盒里的任意文件,其中包括被错误地留在磁盘上的机密信息。
  • 可以读取键盘事件,把用户的每次输入上传到攻击者的服务器。
  • 可以在用户按下转账确认的那一瞬间改掉收款账号。
  • 可以制作一个和登录页一模一样的假界面,把密码骗到手。
  • 也可以绕过证书验证,让整个会话以明文暴露给中间人。

这些威胁在现实中都能找到对应的黑灰产,相关产业的规模比多数开发者估计得大。因此,监管对金融 APP 移动客户端的安全检测一直有明确要求。从这个角度看,检测越狱既正当,也必要。

下面按攻防的次序,把这两年处理过的十来款 App 归纳一遍。每个回合先看攻击方做了什么,再看检测方可以怎么补。

阅读全文 »

某银行 APP 在越狱设备上启动后,大约五百七十毫秒便会退出。围绕这次退出,我们进行了二十几轮分析与干预。最终没有得到可用的绕过方案,不过这些实验揭示了一件更值得记录的事:检测环境、保护检测代码和阻止异常启动,是怎样共同起作用的。

阅读全文 »

天下苦 AI 味久矣。这话如今说出来,大概不会有人反对。打开任何一个信息流,都能看见同一副腔调:三段式排比、莫名其妙的加粗、把一切结论都包装成「这意味着」,结尾还要来一句「希望对你有帮助」。

「偷懒」是人类进步的源动力。我确实想写点东西,但从前写一篇要坐三四个小时,现在让模型起草,十分钟就能出一版。问题在于那一版实在不忍心发出去。它不太像人话,发出去是污染大家的 timeline,也白白增加读者的理解负担。

思来想去,决定给 AI 去去味儿。

阅读全文 »

我在做一个跨语言的算子引擎,同一套语义分别用 Go、Java、C++ 实现。有一处用到了读写锁——一个请求局部的数据结构,多个算子并发读它的字段,偶尔有写。三个实现都用各自语言「标准」的读写锁:Go 的 sync.RWMutex、Java 的 ReentrantReadWriteLock、C++ 的 std::shared_mutex。

某次做性能剖析时,我注意到一件有点意思的事:C++ 这边,读写锁的单次拿放在 profile 里是个能看见的开销;而 Go 和 Java 那边,同样形态的拿放几乎不出现在火焰图里。同样一把读写锁,凭什么 C++ 要贵这么多?

这篇文章记录我顺着这个疑问挖下去的整个过程:先用反汇编搞清楚 glibc 的 pthread_rwlock 到底慢在哪、Go 为什么便宜,然后把 Go 的算法移植到 C++(中间失败了一次),最后发现这个原理上完全正确的优化,在真实负载上根本测不出收益。这最后一点,可能是整件事里最值得说的。

阅读全文 »