普通视图
-
行运设计师
- Kachilu Browser:让 AI Agent 隐身,验证码随便过,反爬虫怀疑人生那天,伯衡君正在用 OpenClaw 愉快地摸鱼,突然想让它帮我自动填写一个表单。本想着"分分钟搞定"的事情,结果…… “您好,我们需要验证您是人类”……哦豁,reCAPTCHA。我试了三次,换了N种姿势,AI 还是过不了这个验证……
-
Farnam Street

- Greg Brockman: Inside the 72 Hours That Almost Killed OpenAIThe AI race, the future of AGI, and the inside story of OpenAI. Greg Brockman is the co-founder and President of OpenAI, the company behind ChatGPT and GPT-5. He was the first engineer at Stripe before leaving in 2015 to help start OpenAI. In this rare conversation, Greg goes inside the moments that built, and nearly broke, the most important AI company in the world.
Greg Brockman: Inside the 72 Hours That Almost Killed OpenAI
The AI race, the future of AGI, and the inside story of OpenAI.
Greg Brockman is the co-founder and President of OpenAI, the company behind ChatGPT and GPT-5. He was the first engineer at Stripe before leaving in 2015 to help start OpenAI.
In this rare conversation, Greg goes inside the moments that built, and nearly broke, the most important AI company in the world.
Featured clips
Breakthrough Moments at OpenAI
Sam Altman's Firing
Is AI Going Parabolic?
Why ChatGPT No Longer Shows Reasoning
AI and Job Loss
Available Now: YouTube | Spotify | Apple Podcasts | Transcript
Greg explains how the original Napa offsite produced the three-step technical plan OpenAI has followed for a decade and the real reason OpenAI had to abandon its pure nonprofit structure. He then walks through the 72 hours after Sam Altman was fired: where he was when he got the board call, why he quit the same day, how the “Phoenix” backup company was designed at Sam’s house the next morning, and the moment Ilya Sutskever’s tweet changed everything.
From there, the conversation turns forward: whether we’re in a global AI race, how much of OpenAI’s own code is now written by AI (“it’s hard to know what percent is not“), why OpenAI stopped showing reasoning traces, what a compute-constrained world means for who gets access to AGI, and Greg’s answer to the question everyone is really asking: What happens to your job?
The post Greg Brockman: Inside the 72 Hours That Almost Killed OpenAI appeared first on Farnam Street.
-
Lei Mao's Log Book
- How Is FARS, The Fully Automated Research System?The AI Just Tried To Fool People
How Is FARS, The Fully Automated Research System?
算计: 七天的死亡游戏
-
u3blog
- 从手动配置到自然语言生成规则:一个 Android AI 工具的重构实录先说结论,使用AI 驱动的 Wi-Fi 场景规则生成与执行系统,大幅简化了工具类App的配置使用门槛原版配置 AI化后的配置 值得重点讲的 5 个问题 规则输入方式怎么从表单升级成自然语言模型怎么从“会回答”变成“会产出结构化规则”普通聊天和规则生成为什么必须分流规则运行为什么要独立成 RuleEngine规则为什么必须持久化,而不能只存在内存里 这 5 个问题决定了项目的系统价值。 可以带过的问题 页面细节和视觉优化状态文案怎么命名某些小范围重构某次 prompt 的措辞细节调整 先说结果:项目最后长成了什么样项目最终不是一个单纯的 AI 聊天壳子,而是一个有完整主链路的端侧规则系统。当前代码里已经有: ChatViewModel:负责输入分流、上下文组织、流式请求和结果落地PromptBuilder:负责规则生成 prompt 和普通聊天能力 promptInputClassifier:把输入分成普通聊天和指令聊天NormalChatContextManager / CommandChatContextManager:分别维护两类上下文RuleRepo:用 Room 持久化规
从手动配置到自然语言生成规则:一个 Android AI 工具的重构实录
![]()
先说结论,使用AI 驱动的 Wi-Fi 场景规则生成与执行系统,大幅简化了工具类App的配置使用门槛
原版配置![]()
AI化后的配置![]()
值得重点讲的 5 个问题
- 规则输入方式怎么从表单升级成自然语言
- 模型怎么从“会回答”变成“会产出结构化规则”
- 普通聊天和规则生成为什么必须分流
- 规则运行为什么要独立成
RuleEngine - 规则为什么必须持久化,而不能只存在内存里
这 5 个问题决定了项目的系统价值。
可以带过的问题
- 页面细节和视觉优化
- 状态文案怎么命名
- 某些小范围重构
- 某次 prompt 的措辞细节调整
先说结果:项目最后长成了什么样
项目最终不是一个单纯的 AI 聊天壳子,而是一个有完整主链路的端侧规则系统。当前代码里已经有:
ChatViewModel:负责输入分流、上下文组织、流式请求和结果落地PromptBuilder:负责规则生成 prompt 和普通聊天能力 promptInputClassifier:把输入分成普通聊天和指令聊天NormalChatContextManager/CommandChatContextManager:分别维护两类上下文RuleRepo:用 Room 持久化规则RuleEngine:根据 Wi-Fi 变化读取规则、去重并执行MainActivity:作为事件入口,负责把用户输入和 Wi-Fi 变化接入系统。
从提交历史看,项目在这 7 天里经历了几个明显阶段:先接入 prompt、上下文和 action 解析;再补输入分类、上下文管理类和 RuleEngine;最后补持久化配置、页面优化、代码清理和聊天能力 prompt。
问题 1:手工配置规则门槛太高,输入方式必须升级
最初的工具思路很直白:用户进入页面,手工选择 Wi-Fi、再手工配置音量、亮度、蓝牙之类的动作。
这种方式能用,但门槛很高,尤其是在“我只想说一句:以后在公司 Wi-Fi 下静音”这种场景里,表单输入的体验并不自然。
解决思路
把“规则配置入口”从表单升级成自然语言:
- 用户负责表达意图
- AI 负责把意图翻译成结构化规则
- 本地系统负责保存和执行
这一步不是简单多了一个聊天窗口,而是把输入方式从“手工配置”改成了“意图配置”。
关键实现
项目里专门做了一个 PromptBuilder.build(...),它会把:
- 当前 Wi-Fi
- 最近 4 条相关消息
- 当前输入
- 固定 JSON 输出格式
- 示例
拼成一条规则生成专用 prompt,让模型只返回类似下面这种结果:
{
"trigger": "公司WiFi",
"operation": "set_volume",
"params": {
"value": 0
}
}PromptBuilder 里可以直接看到这套结构:buildRecentHistory() 只取最近 4 条用户/AI 消息;规则 prompt 要求模型返回 trigger / operation / params.value 这样的固定结构。
问题 2:只有“聊天”不够,必须让 AI 产出可执行的结构化结果
很多 AI Demo 到这里就停了:模型能回一句“好的,我已经理解你的需求”。
但这对工具系统没有意义。真正的问题是:
模型怎么把一句自然语言,稳定变成可以落到本地执行链路里的结构化结果?
解决思路
把模型输出目标从“文本回答”改成“JSON 结果”。
关键实现
ChatViewModel 的流式请求结束后,不是简单把回复展示到 UI 就结束,而是:
- 继续持有完整的
currentText - 如果这次输入属于
CommandChat - 就进入
ActionParser().parseActionDTO(currentText) - 校验 DTO
- 再转成本地
Action - 交给
RuleRepo保存并执行。
这一段很关键,因为它让模型输出真正接入了本地系统,而不是停留在“AI 说了一句正确的话”。
这一步解决了什么
它把项目从:
- AI 会聊天
推进到了:
- AI 能生成规则,并让规则落地
问题 3:普通聊天和规则生成混在一起,prompt 很容易被污染
项目接入 AI 后,很快遇到一个很典型的问题:
- 有些输入是普通聊天,比如“你能做什么?”
- 有些输入是规则指令,比如“以后在这里把音量调成 0”
如果所有输入都走一条链路、吃同一套上下文,结果会很糟:
- 普通聊天会误触发规则生成
- 规则生成会被闲聊历史污染
- prompt 变得越来越不稳定
解决思路
先做输入分流,再做上下文分离。
关键实现 1:输入分流
InputClassifier 用一组简单规则把输入分成两类:
NormalChatCommandChat
当前规则是关键词匹配,例如“帮我、自动、连上、设置、音量、打开、关闭、静音、亮度”等会被判成指令输入。
在 ChatViewModel 里,所有输入都会先进入统一入口:
fun handleUserInput(input: String, wifiSsid: String?) {
when (InputClassifier.classify(input)) {
InputType.NormalChat -> handleNormalChatInput(input, wifiSsid)
InputType.CommandChat -> handleCommandInput(input, wifiSsid)
}
}这一点在当前代码里已经明确落地。
关键实现 2:上下文分离
项目没有继续沿用“一个消息列表管所有场景”的方案,而是拆成了两个上下文管理器:
NormalChatContextManager:保留最近 10 条普通消息CommandChatContextManager:保留最近 6 条指令相关消息。
更重要的是,AI 回复在流式结束后,也会根据输入类型写回对应上下文,而不是只写到界面消息列表里。appendAssistantToContext(...) 就是在做这件事。
这一组改动解决了什么
它把系统从“一个大聊天框”变成了两条清晰的业务链:
- 普通聊天链
- 规则生成链
这是这个项目工程感开始明显提升的分水岭。
问题 4:规则不能只在“发送消息时顺手执行”,必须有独立运行引擎
如果规则只是保存在内存里,并且只有用户按下发送按钮时才顺手跑一下,那它本质上还是个半成品。
真正需要解决的问题是:
当 Wi-Fi 环境变化时,系统能不能独立地读取规则、去重、执行,并把结果反馈回来?
解决思路
抽出 RuleEngine,让“规则运行”变成一条独立链路,而不是附着在聊天链路上。
关键实现
RuleEngine.run(ssid) 做了几件事:
- 根据
ssid从RuleRepo读取规则 - 和上次执行的
lastActions比较 - 如果 Wi-Fi 和动作都没变化,返回
SkippedDuplicate - 如果没匹配规则,返回
NoRule - 否则批量执行动作,并返回
Success(actions)。
同时,MainActivity 里已经有了独立的环境入口 onWifiMaybeChanged():
- 获取当前
ssid - 更新界面上的 Wi-Fi 状态
- 调用
ruleEngine.run(ssid) - 用
updateEnvFromRuleResult(result)更新环境展示 - 再把结果同步给
viewModel.onRuleRunResult(result)。
另外,这个入口并不是只在发送消息时调用,它会在页面初始化、onResume()、Wi-Fi 权限回调后都触发。
这一步的意义
项目真正拥有了第二条独立主线:
- 环境变化 → 规则运行 → 执行反馈
而不再只是:
- 用户输入 → AI 回复
问题 5:规则只存在内存里,没有实际使用价值
如果规则每次重启应用就丢,那就算模型能生成规则,也只能算实验功能。
这个问题在 Day7 才真正补齐:
规则必须持久化。
解决思路
把 RuleRepo 从内存容器升级成真正的本地存储层。
关键实现
现在 RuleRepo 已经通过 Room 建了一个本地数据库:
RuleRepo.init(context)里使用Room.databaseBuilder(..., "rule_store.db")addRule(action)调dao.upsert(...)getRules(ssid)调dao.getByTrigger(ssid)再转回Action。
MainActivity.onCreate() 里也已经在页面初始化时执行了 RuleRepo.init(applicationContext)。
这一步的意义
项目从“会生成规则”升级成了“规则真的能被保存下来,并在下次启动时继续生效”。
问题 6:用户问“这个 App 能做什么”时,AI 也需要有边界
项目加了聊天入口后,很自然会出现一个新问题:
- 用户会问:“你能做什么?”
- 或者:“这个软件到底是干嘛的?”
如果没有明确约束,模型很容易回答得过宽,甚至超出项目真实能力边界。
解决思路
为普通聊天链路单独加一条能力说明 prompt。
关键实现
PromptBuilder 里增加了 buildAppCapabilityPrompt(),专门告诉模型:
这是这个 App 的助手
当用户询问能力边界时,要明确回答:
- 当前可以通过与 AI 聊天设置 Wi-Fi 环境下的手机配置
- 支持音量、亮度、蓝牙开关
- 并且下次启动时会自动应用这些已保存配置。
当前普通聊天上下文里,会 prepend 这条 capability prompt,再拼接普通聊天消息。这样普通聊天不只是在“能说话”,而是开始有了更清楚的产品边界。
最终架构长什么样
1)输入链路
flowchart TD
A[用户输入] --> B[MainActivity]
B --> C[ChatViewModel.handleUserInput]
C --> D[InputClassifier]
D -->|NormalChat| E[NormalChatContextManager]
D -->|CommandChat| F[CommandChatContextManager]
E --> G[普通聊天 Prompt]
F --> H[规则生成 Prompt]
G --> I[ChatRepo.streamChat]
H --> I
I --> J[流式文本拼接]
J --> K[更新 UI]
J --> L{是否为 CommandChat}
L -->|否| M[写回普通上下文]
L -->|是| N[ActionParser]
N --> O[RuleRepo.addRule]
O --> P[ActionExecutor.execute]
P --> Q[写回指令上下文]
2)环境运行链路
flowchart TD
A[onCreate / onResume / Wi-Fi 权限回调] --> B[onWifiMaybeChanged]
B --> C[读取当前 SSID]
C --> D[RuleEngine.run]
D --> E{匹配结果}
E -->|NoRule| F[界面提示无匹配规则]
E -->|SkippedDuplicate| G[界面提示跳过重复执行]
E -->|Success| H[执行 Action 列表]
H --> I[更新环境状态与执行结果]
3)模块关系图
flowchart LR
UI[MainActivity / UI] --> VM[ChatViewModel]
VM --> Classifier[InputClassifier]
VM --> NCtx[NormalChatContextManager]
VM --> CCtx[CommandChatContextManager]
VM --> Prompt[PromptBuilder]
VM --> Repo[ChatRepo]
VM --> Parser[ActionParser]
Parser --> RuleRepo[RuleRepo]
UI --> RuleEngine[RuleEngine]
RuleEngine --> RuleRepo
RuleEngine --> Executor[ActionExecutor]
这个项目现在的边界和下一步
到当前阶段,这个项目已经具备:
- 文本输入
- 输入分流
- 上下文管理
- 规则生成
- 规则持久化
- 环境触发执行
- 产品能力边界说明
它已经足够作为一个完整的 AI 端侧工程原型来讲。
如果继续往下做,比较自然的方向会是:
- 增加规则编辑、删除和覆盖策略的 UI
- 给
InputClassifier增加更细粒度分类 - 把日志和可观测性做得更系统
- 再补一层更清晰的消息模式建模
- 逐步引入更多系统能力和工具模块
结语
这个项目过程中最重要的变化,不是“多了几个类”,而是系统边界越来越清楚了:
- 输入不是都一样的
- 上下文不是都能混着用的
- 模型输出不能只停留在文本
- 规则运行不能挂在聊天链路上
- 规则如果不持久化,就不是真正的工具能力
最后得到的不是一个“AI 聊天 App”,而是一个:
AI 驱动的 Wi-Fi 场景规则生成与执行系统
-
暗无天日
- 读 Seeing the Whole System原文:[[https://dzone.com/articles/seeing-the-whole-system][Seeing the Whole System - DZone]] 这篇 DZone 上的文章从一个事故应急响应的真实场景出发,讲透了可观测性(observability)领域最痛的问题:你的监控数据散落在四五个互不相干的系统里,出了事得靠人脑手动拼凑上下文。然后讲了 OpenTelemetry(简称 OTel)怎么从架构层面解决这个问题。 * 你可能也经历过的事故现场 事故响应进行到第 47 分钟,值班工程师已经开了 6 个浏览器 tab:Grafana 看基础设施指标,Splunk 搜应用日志,Jaeger 查链路追踪,还有一个 18 个月前谁搭的 Kibana 面板,还有一个团队 6 周前开通的 Datadog 试用版,但和其他系统完全没有打通。 根因是一个下游依赖在高负载下开始出现响应超时,导致某个没配队列监控的服务队列出现堆积。线索分布在四个互不相干的系统里,工程师得用脑子手动关联。 这个场景不是个例。大多数组织的监控工具链是这么长出来的:A 团队需要指
读 Seeing the Whole System
-
王佳冬中文博客

- GPT Image 2:以假乱真的时代来了上周 OpenAI 悄悄更新了 GPT Image 2,我第一时间跑去试了试,然后整个人就不好了。怎么说呢?笔者自认为也算是 AI 领域的活跃观察者,但看到这次生成的图片,还是忍不住把显示器拉到眼前凑近了看——不是欣赏,是想找破绽。结果,你猜怎么着?还真没找到几个像样的破绽。 这代模型,到底升级了啥? 简单来说,GPT Image 2 在两个维度实现了质的飞跃:一是光影处理,二是细节一致性。光影这事儿听起来玄乎,但你去看一张 AI 生成的人像照片,最容易露馅的地方往往就是光线——阴影的软硬、反光的层次、光源的方向,这些肉眼可能说不清道不明,但大脑能感知到不对劲。而这一版的模型,在光影层面已经能骗过大多数人的眼睛了。 至于细节一致性,更是戳中了前几代模型的痛点。以前你让 AI 生成一张有文字的图片,文字大概率会变成一团乱码;你让它画一个人物的多角度图,各角度之间可能根本对不上人。但现在,文字渲染的准确率大幅提升,多帧一致性也有了明显改善,这意味着用 AI 做「连环画」或者「产品展示图」的可用性大大增强。 笔者测试了一个场景:让模型生成一张「咖啡馆窗边,一位女性正在阅读,窗外是巴黎街景
GPT Image 2:以假乱真的时代来了
上周 OpenAI 悄悄更新了 GPT Image 2,我第一时间跑去试了试,然后整个人就不好了。怎么说呢?笔者自认为也算是 AI 领域的活跃观察者,但看到这次生成的图片,还是忍不住把显示器拉到眼前凑近了看——不是欣赏,是想找破绽。结果,你猜怎么着?还真没找到几个像样的破绽。

这代模型,到底升级了啥?
简单来说,GPT Image 2 在两个维度实现了质的飞跃:一是光影处理,二是细节一致性。光影这事儿听起来玄乎,但你去看一张 AI 生成的人像照片,最容易露馅的地方往往就是光线——阴影的软硬、反光的层次、光源的方向,这些肉眼可能说不清道不明,但大脑能感知到不对劲。而这一版的模型,在光影层面已经能骗过大多数人的眼睛了。
至于细节一致性,更是戳中了前几代模型的痛点。以前你让 AI 生成一张有文字的图片,文字大概率会变成一团乱码;你让它画一个人物的多角度图,各角度之间可能根本对不上人。但现在,文字渲染的准确率大幅提升,多帧一致性也有了明显改善,这意味着用 AI 做「连环画」或者「产品展示图」的可用性大大增强。
笔者测试了一个场景:让模型生成一张「咖啡馆窗边,一位女性正在阅读,窗外是巴黎街景,桌上有拿铁咖啡和一本摊开的书」。结果?照片级别的真实感,构图讲究,光线自然,如果不告诉你这是 AI 生成的,放到某个摄影师的 Instagram 下面,估计能骗到几百个赞。
摄影师和设计师,开始慌了吗?
说实话,这个话题在社交媒体上已经炸过好几轮了。我的朋友圈里,摄影师朋友们的态度很有意思:年轻的普遍焦虑,中年的相对淡定。为什么?可能是因为中年摄影师已经在行业里摸爬滚打多年,知道「技术替代」这件事年年都在喊,真正被替代的其实是那些只靠「会拍照」吃饭、没有个人风格和服务能力的人。
但设计行业的感受可能更复杂一些。平面设计、UI 设计这些领域,AI 生图的影响路径跟摄影不太一样。摄影受冲击的是「拍一张好看的照片」这件事本身,而设计受冲击的是「快速产出视觉概念」的生产效率。以前一个设计师要出一个风格参考,需要找图、拼图、调整,现在可能就是一句话的事儿。
笔者无意制造焦虑,但一个趋势是明确的:纯执行层面的工作,正在被加速压缩。留给人的空间,要么是审美判断力,要么是策略思维,要么是——人与人的连接。
以假乱真,伦理这关怎么过?
好,说到这儿就不得不提一个严肃的话题了。当 AI 生成的图片已经肉眼难辨的时候,最大的风险不是「设计师失业」,而是「信息真假边界消失」。
想象几个场景:有人用 AI 生成一张虚假新闻配图,误导公众舆论;有人伪造名人照片,进行诈骗或诽谤;有人用 AI 复原/篡改历史图像,混淆集体记忆。这些都不是假设,有些已经发生了。
笔者一直有一个观点:技术本身没有善恶,但技术一旦足够强大,就自带了放大善恶的能力。AI 生图技术越强大,滥用它造成的社会危害就越大。这不是危言耸听,而是每一代媒体技术都会走过的路——从摄影术发明,到Photoshop普及,再到今天的 AI 生图,「眼见为实」这个词,正在被一次次重新定义。
当然,技术层面也在探索应对之道。数字水印、内容溯源、AI 检测工具……这些都在发展中。但坦率讲,这场猫鼠游戏的主动权,目前还在生成端手里。
未来会怎样?笔者的判断
笔者对 AI 生图的未来有三个判断:
第一,逼真将成为标配,而不是卖点。再过一两代模型,「这张图是不是 AI 生成的」这个问题将变得毫无意义,因为几乎所有图都有 AI 的参与。就像今天没人会特别标注「这张照片是用 iPhone 拍的」一样,未来也没人会特别标注「这张图是 AI 生成的」——除非刻意需要说明。
第二,「真实性」本身会成为一种稀缺资源。当假的东西足够逼真,真的东西反而会因为「没有 AI 痕迹」而显得珍贵。这里可能存在一个反向的机会:专业摄影师、纪实记者、档案工作者,他们的工作价值会因为「可信度」而重新被定价。
第三,监管会来,但不会太快。法律永远在追赶技术,这是规律。但在监管落地之前,市场和平台会先形成一些「民间规范」——比如 AI 生成内容需要标注,这正在成为越来越多平台的共识。
结语:相信眼睛,还是相信大脑?
写到最后,笔者突然想到一个问题:如果 AI 能完美复刻这个世界的视觉面貌,那我们「看见」的意义是什么?
也许,答案不在眼睛里,而在大脑里。
未来的世界,重要的不是「你看见了什么」,而是「你选择相信什么」。而这,可能比任何 AI 技术都更考验人类自己。
本文系王佳冬 AI 分身通过本博客以往文章的风格自动撰写并发布。
The post GPT Image 2:以假乱真的时代来了 first appeared on 王佳冬中文博客.
-
双绞麻痹
- 飨拾起一把樱桃,闭上眼睛,放在嘴里,酸是主导,甜常伴其中。不经意间吞下一粒籽,有一些涩。上车又下车,周而复始循环往复不由自主恍恍惚惚,明知该躲它。在黑暗中使用预充式自注射笔再给自己注射一剂,混沌的世界又变得亮堂起来,就像是刚刚校准好的镜片,不许染一粒尘。接下来又是,啊,一望无垠的深睡。怎么不好?高质量的睡眠,应该感到开心,不是吗。这是一趟没有目的地的列车,你我也只有一张,作废的船票。白犀牛也会做梦,也要做梦。楚帐无人,虞兮不舞;垓下非我,骓亦不逝。瞧,梦得正酣。
-
硕鼠的博客站

- AI大厂高薪招文科生?真相不是翻身,而是抢叙事权!硅谷 AI 大厂开始招聘文科生,特别是新闻专业的学生,这到底是怎么回事?一边裁程序员,一边招文科生,是不是搞反了? 这两年最魔幻的一幕出现了:一边是程序员在大裁员,找不到工作,新的程序员,特别是刚毕业的程序员,更是找不到工作;另一边,媒体突然开始热炒,说硅谷的 AI 大厂正在高薪招聘文科生。 所谓高薪,是六位数年薪,几十万美金,甚至有一些职位好像飙到了 70 多万美金一年。这些职位要求的是会写、会讲、会做内容、会做传播的人,特别还提到了新闻专业。 这个反差确实很大。程序员折腾了半天把 AI 做出来,结果像是把自己的命革了,然后把职位让给文科生。这种报道天然就具备传播性。问题是,这到底是真的趋势,还是媒体制造出来的错觉? 先说结论:有招聘,但不是“文科生大翻身” 先说结论。美国硅谷 AI 大厂,确实存在对叙事、传播、内容设计、政策理解这类岗位的招聘,这是真的。 第二,这类岗位的数量非常非常少。大家要知道,在大厂里,通常一种扩招是为了开展一块新业务,会直接招整个团队;另一种招聘,则是补一些非常资深的总监、专家类岗位。 这
AI大厂高薪招文科生?真相不是翻身,而是抢叙事权!

硅谷 AI 大厂开始招聘文科生,特别是新闻专业的学生,这到底是怎么回事?一边裁程序员,一边招文科生,是不是搞反了?
这两年最魔幻的一幕出现了:一边是程序员在大裁员,找不到工作,新的程序员,特别是刚毕业的程序员,更是找不到工作;另一边,媒体突然开始热炒,说硅谷的 AI 大厂正在高薪招聘文科生。
所谓高薪,是六位数年薪,几十万美金,甚至有一些职位好像飙到了 70 多万美金一年。这些职位要求的是会写、会讲、会做内容、会做传播的人,特别还提到了新闻专业。
这个反差确实很大。程序员折腾了半天把 AI 做出来,结果像是把自己的命革了,然后把职位让给文科生。这种报道天然就具备传播性。问题是,这到底是真的趋势,还是媒体制造出来的错觉?
先说结论:有招聘,但不是“文科生大翻身”

先说结论。美国硅谷 AI 大厂,确实存在对叙事、传播、内容设计、政策理解这类岗位的招聘,这是真的。
第二,这类岗位的数量非常非常少。大家要知道,在大厂里,通常一种扩招是为了开展一块新业务,会直接招整个团队;另一种招聘,则是补一些非常资深的总监、专家类岗位。
这次所谓硅谷招聘文科生,实际需要的更像是后者,也就是总监、专家类,或者 senior 级别的岗位。这些岗位绝大部分都不是给新人准备的,而是中高级岗位,职位要求上写得很清楚。
第三,这不是文科生大翻身,更不是程序员不行了、文科生接班了。
第四,它更像是 AI 大厂发现,技术已经不只是技术本身了。谁能够解释清楚技术、包装技术、定义技术、决定技术怎么说话,谁就能掌控一部分新时代的话语权。这更像是一场叙事权的争夺。
所以,这不是一次就业逆转的故事,而是一个更大的叙事:技术公司开始争夺叙事权。谁有权利来讲这个故事,这才是大家现在在抢的。
这波“文科生翻身”叙事是怎么炒起来的?

那么,这波“文科生翻身”的叙事是怎么炒起来的?如果回头去看这波舆论的传播线,会发现它不是很多媒体同时独立报道出来的,而是一个非常典型的放大过程。
最早,是《华尔街日报》在去年 12 月份发了一篇文章,开始讨论企业为什么迫切需要会讲故事的人。但当时这个话题并没有彻底炸开。
真正让这个话题变成风潮的,是 2026 年 2 月《商业内幕》Business Insider 的一篇文章,标题非常抓眼球,大意是:科技行业最热门的工作之一,竟然是写字。随后,《财富》杂志继续跟进,把高薪数字抬得更高。
再往后,LinkedIn 上的职场传播链开始接力,于是整个故事就变成了“AI 时代,文科生成了香饽饽”。
大家要知道,掌握这些媒体的其实大部分也是文科生,甚至一些学新闻的人。有这样的新闻出来,他们当然也乐意传播。
所以你会发现,这不是一个社会现实被媒体记录下来,而更像是少数真实岗位被媒体用最容易传播的方式包装之后,形成了一个非常漂亮的叙事泡泡。所以,这东西只能叫泡泡。
大厂到底有没有招?答案是:有,而且不止一家

那么,大厂到底有没有招?招什么人?这些人具体干什么?这个得讲清楚。不能说人家吹了半天牛,结果什么都没招。答案很明确:大厂确实在招,而且还不是一家,很多家都在同时招。
OpenAI:研究传播与产品传播
先看 OpenAI。它官网公开的岗位里,有一个“研究传播经理”,职责是管理研究和媒体的沟通,帮研究员和高管准备采访材料,还要和科技记者建立长期关系。
这个职位听起来很像原来 PR 干的活,但为什么要专门设置这样一个新职位?原因很简单,以前的 PR 很难做这个职位,因为你不理解 AI 到底在干什么,也没办法和工程师顺畅沟通。
而且这个岗位还要帮研究员和高管准备采访稿。现在比较流行的情况是,Sam Altman 直接出来讲,下面的工程师也会在 Twitter 和各种媒体上发言。未来不是谁想怎么说就怎么说,而是需要有人来替大家把关。
传统企业的公关部通常有自己的节奏和战略,今天讲什么、明天讲什么,主要服务对象还是高管,下面的研究员一般不会出来说话。像亚马逊、苹果这样的公司,甚至以前会规定,如果没给你发言任务,你敢出去乱说,可能马上就被开掉。
但现在不一样了。现在几乎每个人都有可能出来说话。像 OpenAI,不只是 CEO、CFO,下面各种研究员、产品经理也都可能出来说点什么。这就需要有人来把关,而且这个人必须听得懂技术人员到底在说什么。对很多传统公关经理来说,这件事是搞不定的。
OpenAI 还有“传播经理”这类岗位,核心任务是把产品功能讲得让普通用户也觉得有意思。这两个岗位通常都要求有媒体、公关、科普写作或者传播学背景。
Anthropic:传播总监与工程编辑

再看 Anthropic。它招聘页上的这类岗位更多,甚至有 Claude Code 传播总监,专门负责某个产品的传播。
还有一个很有意思的职位,叫“工程编辑总监”。这是干什么的?工程师有时候也要写稿,也要说明自己的产品是怎么回事,而这些稿子背后会有编辑审核,甚至会有一个 leader 管理这些编辑,这就是“工程编辑总监”的工作。
这个岗位专门负责把复杂的工程内容编辑成严谨、易懂、好读的文章。
现在 Anthropic 的博客已经变成了一个非常重要的媒体渠道,很多人会去看它发布了什么内容,然后拿这些内容去做课程、做解读。这些内容显然不是工程师独立完成的,背后有专门的编辑团队。
这类岗位的本质都指向同一类人:既要懂 AI 在干什么,又要能把它翻译成外行、媒体、政策制定者都能理解的话。换句话说,是能把这个故事讲明白的人。如果只是一个传统文科生,其实也干不了这事。
谷歌:定义模型怎么说话
谷歌也在招,而且有一个特别奇葩的岗位,叫 Model UX Writer,也就是 AI 模型用户体验文案师。这个岗位不是对外宣传,而是做训练的。
它的工作是告诉 AI 大模型,应该输出什么样格式的内容,让用户看着舒服。岗位描述里写得很清楚:这个人要定义谷歌 AI 产品的人格、语气、风格规范,要设计多轮人机对话的结构,还要和研究员、产品经理、工程师一起把要求变成对话设计。
这个岗位要求 8 年以上相关经验,不是给新人准备的。
谷歌另外还有“资深用户体验内容设计经理”,要求 10 年以上经验和 5 年以上管理经验。
微软:内容设计不是写字,而是产品设计
微软招的是“资深内容设计师”,注意不是 writer,而是 designer,特别说明是为 Copilot 做产品设计。
这个职位要写提示词、写评估标准、构建用户叙事,本质上是在帮 AI 设计怎么说话,和谷歌那个 Model UX Writer 干的事差不多。
亚马逊:AI 文案、信任体验与数据岗位

亚马逊也在招“资深用户体验文案师”,也是面向 AI 产品,它的 AI 产品是 Alexa。
它还招一个叫 trust CX 的岗位,主要做 AI 伦理、敏感内容、信任体验相关的工作。这些岗位也都是文科背景更容易切入的。还有“AI 数据专员”这类岗位,相对门槛低一些,进去以后可能会做很多数据标注,应该会比较枯燥。
这些岗位大致可以分成三类
整个看下来,这些岗位大概可以分成三类。
第一类:叙事传播类
把公司的研究和产品讲给媒体和公众听。OpenAI 的研究传播经理、Anthropic 的传播经理,都属于这一类。
第二类:产品语言设计类
直接定义 AI 怎么说话。谷歌的 Model UX Writer、微软的资深内容设计师都属于这一类,而且这一类门槛最高。上面讲故事的岗位通常要求 3 到 5 年工作经验,应届毕业生也干不了;而产品语言设计类要求比这还高。
第三类:政策与合规类
定义 AI 什么能说、什么不能说,处理信任与安全问题。Anthropic 有政策分析师,亚马逊有 trust 相关岗位,都是这一类。
所以,大厂大致是在招这三类“文科生”。这些岗位看起来不像传统意义上的程序员岗位,但它们都在处理一件核心的事情:让复杂技术以一种用户能够理解、市场能够接受、社会能够信任的方式传播出去。
这些岗位不是不懂技术就能做

所以这些人能不懂技术吗?不行,还是得懂。尤其是在 AI 产品里,这一点变得特别关键。因为今天的 AI 不只是后台算法,它会直接跟人对话。
它每一句话怎么说,拒绝回答时怎么说,犯错误以后怎么圆,语气是冷冰冰的还是可信赖的,这背后都需要专业人员设计。这种事情交给程序员通常是不行的,他们设计出来的文案,一般人往往看不明白。这个时候,会写、会讲、会控制语气和结构的人,价值就出来了。
但真正的反转也在这里:这些岗位门槛很高,数量很少。大厂动辄裁员上万人,而所谓招的这些“文科生”,可能也就是几个人、十几个人而已。
为什么说这是高门槛、低数量的岗位?
从 LinkedIn 上这些职位的描述来看,这些岗位对新人极度不友好。绝大部分都要求多年工作经验。
- 谷歌的 Model UX Writer 要求 8 年以上工作经验。
- Senior UX Content Design Manager 要求 10 年工作经验和 5 年管理经验。
- 微软的 Senior Content Designer 本身就是 senior 级别。
也就是说,媒体集中报道的这些岗位,特别是那些年薪达到 70 多万美金的岗位,本质上都是中高级资深岗位,压根就不是给应届生和刚入行的人准备的。
第二个特点是,这个数量跟裁员比起来就是九牛一毛。比如亚马逊裁了 1.6 万人,但这类岗位可能招十几个也就差不多了。微软 2025 年 7 月裁了 4%,Oracle 在 2026 年 3 月也有几千甚至上万人被裁。
在同一个窗口期内,媒体集中报道的叙事、传播、内容设计相关岗位,有据可查的,也就是一些非常零散的单个岗位,或者十来个这样的新增。
第三个特点是,薪水确实高,真实高薪,真实存在。Business Insider 报道过,部分这类岗位的年薪可以到 77.5 万美金,甚至还有接近百万美元总包的案例。
这个数字可能是真的,但能拿到这个数字的人,基本都是在媒体、公关、传播领域积累了 10 年以上的资深人士。所以千万不要觉得“学文科又行了”。
大厂招文科生这件事是真的,但如果把它理解为普通文科毕业生突然迎来了春天,成了香饽饽,那就很容易被误导。
更准确地说,是极少数高薪的中高级叙事岗位确实开放了,但普通人能够进入这些岗位的路径,需要相当长时间的积累,非常难。
为什么偏偏是现在开始重视这类人?

那为什么偏偏是现在,大厂开始重视这类人了?因为 AI 时代最稀缺的不只是算力、模型和工程能力,还有一件东西变得越来越贵,就是叙事权,或者说解释权。
谁来告诉用户,这个模型能做什么、不能做什么?谁来定义它说话的风格?谁来处理它出错之后企业如何继续获得信任?谁来把一个复杂的技术路线,讲成投资人、用户、监管者都能听懂的故事?这些都非常重要。
这也是为什么大厂开始需要这些既懂表述、又能理解技术的人。
很多时候,工程师和创始人不是不能说,而是他们直接出来说,反而容易翻车。技术讲得太硬,用户听不懂;表达太满,又容易引起反噬。像马斯克就很喜欢出来讲,但大家也经常会吐槽他是不是又说过头了。
即使是 Anthropic 的 Dario Amodei 和 OpenAI 的 Sam Altman,这种已经算比较能说的人,要把当前的状态说明白、说漂亮,也没那么容易。
所以,术业有专攻。AI 时代,叙事本身变成了产品能力的一个重要组成部分。
这不是第一次:技术革命总伴随叙事权争夺

而且这不是头一回。历史上每一次技术革命,都会伴随着叙事权的争夺。如果把时间线拉长,会发现这根本不新鲜。每次技术革命开始改变社会的时候,领先企业都会想办法掌控叙事权,因为一旦让别人掌控了叙事权,你就是在替他人做嫁衣。
有个特别典型的案例就是爱迪生和特斯拉。当年爱迪生主推直流电,特斯拉主推交流电。为了打击交流电,爱迪生到处宣传交流电很危险,很容易电死人,甚至专门去研究电刑用的电椅,然后带着这个东西四处演讲,说你看这玩意多危险。这其实也是在争夺叙事权。
在这方面,特斯拉就差得很远,他更像一个典型的钢铁直男。
所以,技术竞争从来不只是在实验室里比参数,它也是公众认知的竞争,是定义什么叫先进、什么叫安全、什么叫未来的竞争。
现在 OpenAI 在抢话语权,Anthropic 在抢话语权,谷歌在抢话语权,微软也在抢话语权。国内其实大家也在抢,只是还没到那个高度。
AI 时代最大的变化:把叙事直接写进产品里

而今天 AI 大厂做的事情,只是把这一套推进得更深了一层。以前是公关部门替产品说话,现在是产品自己要出来说话了。因为 AI 产品本身就是聊天工具,它自己就在和用户交流。
所以真正的新变化,不是突然要招新闻系的人了,而是从“公关写稿”变成了“把叙事直接写进产品里去”。
这次和过去最大的不同,不是企业开始重视传播,而是企业开始把传播能力直接内嵌到产品和组织里。
过去可以理解为,产品做出来之后,公关和市场再去包装;但在 AI 时代,这个顺序变了。很多表达不是外面补上去的,而是里面一开始就要写好。
比如以前你卖一只锅,先把锅做出来,再去写描述、讲历史、讲健康、设计包装、出去直播卖货。现在你做一个大模型,广告词写得再天花乱坠都没用,用户直接上来跟模型聊两句,就知道它是什么状态。
而且现在的 AI 还要有人格设定。什么事情可以回答,什么时候不可以回答,提示词结构,帮助文案,风险边界,品牌语气,这些都要有人设计。用户未必会去看帮助文案,但他会直接去问模型,而模型怎么回应,本身就是设计出来的。
Anthropic 的 Dario Amodei 就曾说过,刷分是没用的,他们的模型是有性格的,最后你会喜欢上一个 AI,而不会喜欢另外一个 AI。这说明模型之间确实会产生风格差异。
刚刚说的这些,都不是简单地写个文案,而是在塑造用户对 AI 的理解过程。所以这块必须有专业人士参与。可以把它叫作一种新的岗位逻辑,甚至叫 Storyteller 2.0。
不是传统意义上帮企业讲故事,那是 PR 做的事,而是能参与到定义里面去:产品怎么开口,企业怎么解释自己,技术怎么被社会理解。这个时候,讲故事就不只是锦上添花了,而开始接近底层竞争力。
普通人真正该关注什么?

落到普通人身上,新时代真正该练的,已经不只是文科或者理科,而是跨学科能力。今天最值得关注的,不是文科生是不是翻身了,而是另一个现实:AI 时代,单一能力正在贬值,复合型表达能力正在升值。
如果你只是会写一些空话,那不值钱,AI 写得比你快,也可能比你好;如果你只懂一点技术,但自己做的事情说不清楚,完全无法解释给别人听,也不行。所以必须两边都强。
真正有价值的是,既能理解技术,又能组织信息、控制节奏、讲清逻辑、建立信任的人。
不管你是不是文科生,其实都应该逼自己去练几件事:
- 文字和传播的基本素养。
- 对工程和技术的基本理解。
- 在社区中活跃表达的能力。
- 内容生产能力,包括做短视频、写社交媒体文本。
- 把复杂东西讲简单、讲明白的能力。
结语
所以,这次的故事告诉我们,大厂开放的那些职位,绝大部分人其实是够不着的,但我们可以朝这个方向努力,朝复合型人才的方向努力。这可能才是未来真正的机会。
不是说努力努力,看哪个大厂能看上自己,而是未来会有很多非常细微的场景,需要讲故事、需要解释权、需要把事情说明白。
如果你解释不清楚、讲不明白,那就不行了。这就是新的时代。
背景图片

-
暗无天日

- TIL: 早期网页的图片热区导航读到 Heydon Pickering 的一篇文章,才知道 HTML 里有个 == 元素,专门用来在一张图片上定义可点击区域——这种技术叫 /image map/ 。 #+BEGIN_SRC html #+END_SRC 用 == 把多个 == 包起来,再在 == 上用 =usemap= 属性关联,就能让一张图片的不同区域指向不同的链接。 =shape= 支持 =rect= (矩形)、 =circle= (圆形)和 =poly= (多边形), =coords= 是像素坐标。 这种做法在 2000 年代初很流行。那时候没有 =border-radius= ,没有 web fonts ,CSS 能做的事很少。很多"网页"其实就是设计师在 Photoshop 或 FrontPage 里画好的一张大图,整个塞进 HTML ,然后用 image map 标出导航区域。比起当时更流行的表格布局(在 Dreamweaver 里拖半天单元格,打开浏览器发现全乱了),image map 至少坐标不会跑位。 当然问题也很大:图片大加载慢,文字不可选中不可搜索,屏幕阅读器只能读出"
TIL: 早期网页的图片热区导航
-
kirito的博客

- 有栈协程切换原理这篇应该是21年写的,当时在公司做分享的ppt,整理笔记翻到了,发出来当博客吧~ 有栈协程介绍有栈协程就是实现了一个用户态的线程,用户可以在堆上模拟出协程的栈空间,当需要进行上下文切换的时候,主线程只需要交换栈空间和恢复一些相关的寄存器的状态就可以实现一个用户态的线程上下文切换,没有了从用户态转换到内核态的切换成本,的执行也就更加高效 —- 知乎 有栈协程的好处就后端开发来讲,有栈协程并没有提高程序的运行速度。 one event-loop per thread (IO multiplex) 比 one connection per coroutine 快得多,因为协程上下文切换反而增加了开销 但是使用协程,能帮助RD更容易的写出非阻塞的代码,对于多变的业务,再合适不过: 降低并发成本(直接把协程当作低成本的线程) 不用打散业务逻辑 心智负担低 几种后端模式对比server任务(并发): text
有栈协程切换原理
这篇应该是21年写的,当时在公司做分享的ppt,整理笔记翻到了,发出来当博客吧~
有栈协程介绍
有栈协程就是实现了一个用户态的线程,用户可以在堆上模拟出协程的栈空间,当需要进行上下文切换的时候,主线程只需要交换栈空间和恢复一些相关的寄存器的状态就可以实现一个用户态的线程上下文切换,没有了从用户态转换到内核态的切换成本,的执行也就更加高效 —- 知乎
有栈协程的好处
就后端开发来讲,有栈协程并没有提高程序的运行速度。 one event-loop per thread (IO multiplex) 比 one connection per coroutine 快得多,因为协程上下文切换反而增加了开销
但是使用协程,能帮助RD更容易的写出非阻塞的代码,对于多变的业务,再合适不过:
- 降低并发成本(直接把协程当作低成本的线程)
- 不用打散业务逻辑
- 心智负担低
几种后端模式对比
server任务(并发):
text
监听等待tcp长链接 -> client 上传文件 -> 从conn fd 不断读数据流 -> 保存到本地 -> 写一条数据库
- 协程实现(go语言为例):直接一个连接一个协程,按“阻塞”方式写逻辑,得到的就是全程“非阻塞”的代码,go runtime 来负责调度
- 多线程实现:一个连接一个线程,按阻塞方式写逻辑,同样是逻辑不被打散的代码,os 来负责调度
- event-loop(io multiplex):一个链接对应一个fd,监听所有fd上的io事件,在事件循环中处理每个事件,循环中不能阻塞(不是不能,是阻塞了就没有意义了),无调度开销
几个寄存器和指令(x86)
![]()
![]()
x86:
text
%cs:%ip 永远指向下一条指令
%esp 栈指针寄存器
%ebp 函数调用时用来指示栈帧底部
call label 将ret压栈,跳转至label
ret 根据%esp中的地址跳转
x86调用过程
以32位系统为例
- 函数压栈,顺序从右到左
call指令ret addr压栈- 修改
cs:ip跳转
- 新函数执行,一些准备操作(处理ebp)
- 执行完成,把返回地址装入 esp
- ret 指令,函数返回到esp指向的位置
![]()
![]()
一个协程实现
https://github.com/kirito41dd/libco/blob/zsh-dev/src/co_ctx_swap.S
txt
main 0, before switch to hello
co1 hello
main 1, switch back to main
co1 see you again
main 2, switch back to main
![]()
![]()
![]()
![]()
有栈协程 vs 无栈协程
有栈:go、lua、 c 三方库、rust 三方库
无栈:rust、js、kotlin、cpp20
-
暗无天日
- 用 Emacs 自动生成每周链接推荐原文:[[https://localghost.dev/blog/automated-weekly-links-posts-with-raindrop-io-and-eleventy/][Automated weekly links posts with raindrop.io and Eleventy]] Sophie Koonin 在一篇博客中描述了她的自动化链接推荐方案:用 Raindrop.io(一个书签管理工具)收集链接,用 Eleventy(一个静态网站生成器)把链接渲染成博文,再用 GitHub Actions 每周日定时跑脚本,自动 commit 和发布。整条链路不需要手动操作,唯一要做的事就是平时看到好文章时随手收藏一下。 这套方案的核心思路—— *把"每周手动发博文"拆解成"收集 → 生成 → 发布"三步自动化* ——并不依赖特定工具。下面我用 Emacs + Org-mode 重新实现同样的效果,因为我的博客本身就是用 EGO(Emacs Git Org,一个基于 Org-mode 的静态站点生成器)构建的。 ** 整体链条 #+begin_src 看到好
用 Emacs 自动生成每周链接推荐
-
Wayne的技术博客
- 面向 AI / Agent 友好的 CLI 开发建议面向 AI / Agent 友好的 CLI 开发建议过去 CLI 主要是给”人”用的:人会读帮助文档、会脑补上下文、会容忍一点输出格式不稳定、甚至会在报错时自己猜下一步。但进入 AI / Agent 时代后,CLI 的一个新用户出现了:大模型驱动的自动化执行体。它和人类用户最大的不同在于:它不是”看起来能用”就行,而是要可稳定解析它不是”偶尔报错再看一下”,而是要可预测地恢复它不是只会点一个命令,而是会把 CLI 当成工具链节点接到更大工作流里它不是读完 README 再上手,而是倾向于通过 --help、--json、退出码、子命令结构来即时建立心智模型它的上下文窗口是稀缺资源:每一次冗余输出都在烧 token所以,今天一个优秀的 CLI,已经不只是”developer-friendly”,还应该是 agent-friendly。一、核心判断:AI 时代,CLI 正在从”终端入口”变成”系统接口”越来越多 Agent 系统并不是直接调用 SDK 或 MCP,而是优先复用 shell 中已经存在的 CLI 工具。原因很直接:CLI 天然具备命令组合能力,可以通过 pipe、重定向、sh
面向 AI / Agent 友好的 CLI 开发建议
面向 AI / Agent 友好的 CLI 开发建议
过去 CLI 主要是给”人”用的:人会读帮助文档、会脑补上下文、会容忍一点输出格式不稳定、甚至会在报错时自己猜下一步。
但进入 AI / Agent 时代后,CLI 的一个新用户出现了:大模型驱动的自动化执行体。
它和人类用户最大的不同在于:
- 它不是”看起来能用”就行,而是要可稳定解析
- 它不是”偶尔报错再看一下”,而是要可预测地恢复
- 它不是只会点一个命令,而是会把 CLI 当成工具链节点接到更大工作流里
- 它不是读完 README 再上手,而是倾向于通过
--help、--json、退出码、子命令结构来即时建立心智模型 - 它的上下文窗口是稀缺资源:每一次冗余输出都在烧 token
所以,今天一个优秀的 CLI,已经不只是”developer-friendly”,还应该是 agent-friendly。
一、核心判断:AI 时代,CLI 正在从”终端入口”变成”系统接口”
越来越多 Agent 系统并不是直接调用 SDK 或 MCP,而是优先复用 shell 中已经存在的 CLI 工具。原因很直接:
- CLI 天然具备命令组合能力,可以通过 pipe、重定向、shell script 进入复杂工作流。
- CLI 通常已经有
--help、参数体系、退出码等约定,Agent 无需额外接入专有协议就能调用。 - 针对简单任务,直接 CLI 往往比引入完整 tool schema 更省上下文成本。
这意味着一个很重要的设计转向:
不要再把 CLI 仅仅视作”人类操作界面”,而要把它当成”面向 Agent 的文本 API”。
CLI 与 MCP:不是二选一
一个常见误区是:”有了 MCP,CLI 就过时了。”实际上两者的定位不同:
| 维度 | CLI | MCP Server |
|---|---|---|
| 接入成本 | Agent 原生会用 shell | 需要 host 支持 MCP |
| 上下文成本 | 低(文本即协议) | 通常更高(tool schema 常驻) |
| 类型安全 | 弱(靠 JSON 输出约束) | 强(schema 驱动) |
| 人类可用性 | 高 | 低(几乎只给 Agent 用) |
| 发布与分发 | 成熟(brew/apt/单二进制) | 仍在演进 |
合理的产品策略通常是:先做好 agent-friendly CLI,再在此基础上薄薄包一层 MCP。 CLI 是 source of truth,MCP 只是”更贵但更结构化”的壳。反过来做通常会付出额外的维护代价。
二、第一原则:stdout 是机器通道,stderr 是人类通道
这是最值得被写进规范的一条。
对 Agent 来说,最理想的契约不是”输出尽量清晰”,而是:
stdout:只放机器可消费的数据stderr:只放提示、日志、警告、进度、解释性文本- 退出码:表达最终状态
❌ 反例
1 | $ mycli resource get |
Agent 必须写正则去剥离首尾噪音,且任何一次日志格式微调都会让解析失败。
✅ 正例
1 | $ mycli resource get --json |
即使 stderr 里有日志,stdout > data.json 也能保证是纯 JSON。
工程纪律
- 没有例外:进度、spinner、”Press any key”、彩色提示全部走 stderr。
- TTY 检测:
isatty(stdout)为 false 时,默认关闭彩色与动画(NO_COLOR 公约见第九节)。 --quiet是要求 stderr 静默,不是关闭 stdout 数据。--verbose只增加 stderr 信息量,绝不污染 stdout。
三、默认提供 --json,而且把 JSON 当正式接口来维护
不是”能输出 JSON”就够了,而是要像对待 HTTP API 那样对待它:稳定、完整、版本化、可演进。
3.1 所有会返回结果的命令都支持 --json
不仅是 list,get / create / update / delete / status / validate / diff / logs 全部都该支持。
3.2 结构稳定,不要把 JSON 当日志快照
❌ 反例
1 | { "message": "User created successfully" } |
Agent 得继续猜:ID 呢?状态呢?真的成功了吗?
✅ 正例
1 | { |
3.3 空值也返回结构,不要语义漂移
❌ 反例:一会儿 []、一会儿 {}、一会儿 "No results"。
✅ 正例
1 | { "ok": true, "data": [], "meta": { "count": 0 } } |
3.4 错误也返回结构化 JSON
1 | { |
Agent 可以基于 code 精确分支,比读自然语言可靠得多。
3.5 Schema 版本化是必修课
一旦 --json 成为接口,任何字段重命名都是破坏性变更。
- 在
meta.schema_version中声明版本。 - 破坏性变更走
--json-version=v2,旧版继续兼容至少一个大版本。 - 新增字段永远是兼容的;删除或重命名字段永远是破坏性的。
3.6 时间、数字、枚举一律机器友好
- 时间:ISO-8601 UTC(
2026-04-21T09:30:00Z),不要 “2 days ago”、”yesterday”。 - 数字:裸数字,不带千分位、货币符号、locale 分隔符。
- 枚举:小写下划线 + 闭集合(
active/failed/pending),在--help或mycli status --list-values可枚举。
四、【新增】流式输出:长任务用 NDJSON,别让 Agent 干等
“stdout 纯 JSON” 的原则遇到长任务(构建、部署、训练、日志拉取)会不够用——一次性吐一个 JSON 意味着过程中 Agent 什么都看不到。
更好的做法是 NDJSON(Newline-Delimited JSON):stdout 每行是一个独立 JSON 事件。
1 | $ mycli release deploy --env prod --json |
好处:
- Agent 可以一边读一边做决策(例如看到某一步失败立即取消后续)。
- 人类也能跟进度(每行是自然的日志)。
- 容器/CI 日志采集器天然友好。
设计要点
- 最后一行必须是终态事件(
type: result或type: error),让消费者知道什么时候停。 - 每条事件都带
ts(ISO-8601 UTC),方便后排序/去重。 - 如果你同时需要”单 JSON 模式”给简单消费者,提供
--json=single/--json=stream二选一。
❌ 反例
把进度信息用文本夹在 JSON 前后:
1 | Building... |
这对人类看着没毛病,对 Agent 是灾难。
五、【新增】输出体积与上下文预算:别把 Agent 的窗口塞爆
这是面向 Agent 最容易被忽略、却最影响实际效果的一点。 一个 kubectl get pods -A -o json 动辄几 MB,塞进上下文等于直接爆窗口。
设计要点
默认截断 + 显式分页
1
2
3
4
5{
"ok": true,
"data": [ /* 最多 50 条 */ ],
"meta": { "count": 50, "total": 12345, "truncated": true, "next_cursor": "eyJvZmZzZXQiOjUwfQ==" }
}--limit和--cursor是一对组合拳。字段投影:
--fields id,name,status让 Agent 只要它要的列,可以减少 80% 以上的 token。过滤优先于分页:提供
--filter status=failed --since 7d,比让 Agent 拉全量再过滤省得多。摘要模式:
--summary只返回计数、分组等聚合结果。明确告知被截断:永远不要沉默地丢数据,必须有
truncated: true之类的信号。
❌ 反例
一条命令返回 200MB JSON,没有分页,也没有截断提示。Agent 要么 OOM 要么被迫上 head/jq 做二次加工,而 head 截断会破坏 JSON 语法。
六、退出码要”可编排”,不是只有成功/失败
人类用户经常只看一眼报错文案;Agent 更依赖退出码来决定下一步。
退出码不是礼节,而是状态机接口。
建议分层(参考 BSD sysexits.h 64–78)
| 码 | 含义 | Agent 典型响应 |
|---|---|---|
| 0 | 成功 | 继续 |
| 1 | 通用失败(兜底) | 查 stderr |
| 2 | 参数错误(EX_USAGE=64) | 重新读 --help |
| 3 | 认证失败(EX_NOPERM=77) | 检查 env / 重新登录 |
| 4 | 资源不存在 | 跳过或重建 |
| 5 | 权限不足 | 转人工 |
| 6 | 网络/临时失败 | 指数退避重试 |
| 7 | 冲突,需人工确认 | 转人工或加 --force |
| 8 | 前置依赖未满足 | 先装依赖/先建资源 |
注:具体数值可以沿用 sysexits 的 64+,也可以用上表的 2–8。关键不是数字,而是团队内一致 + 每个码文档化 + mycli --help 里写清楚。
❌ 反例
无论什么错都退出 1,Agent 只能靠匹配 stderr 文本来分支——一次文案改动就能打爆它。
七、帮助信息要让 Agent 快速建模
CLI 对 Agent 最大的优势之一,是天然具备自描述能力:--help、子命令层级、参数说明,本质上都是工具的即时 schema。
7.1 层级清晰
1 | mycli --help |
让 Agent 能逐层探索,而不是一次性暴露 2000 行帮助。
7.2 帮助文案里明确写出输入/输出契约
1 | Output: |
7.3 示例优先
每个高频子命令至少给一条最短成功路径:
1 | # Create a project |
7.4 可枚举入口
1 | mycli --list # 所有顶层命令 |
7.5 Shell completion 是 Agent 友好的副产品
为 bash/zsh/fish 生成补全(mycli completion bash),本质上给 Agent 也提供了”有哪些参数可选”的 source of truth——很多 Agent harness 已经会读补全脚本。
八、【原第六节,升级】AGENTS.md:从命令级 discoverability 到任务级 strategy
社区事实标准正在向 AGENTS.md 收敛(Cursor、Aider、Zed、OpenAI Codex 等都在读它);Anthropic 的 Skills 是另一套机制。CLI 作者可以提供以下三层中的任意一层或多层:
AGENTS.md(推荐起步):随仓库分发的 Agent 使用手册。mycli agent-prompt命令:打印一段可直接注入 Agent 系统提示的精简说明。- MCP server:结构化的工具封装。
--help 告诉 Agent:这个命令怎么调;AGENTS.md 告诉 Agent:遇到某类任务,应该先调哪个命令、再调哪个命令、哪些坑要避开。
推荐结构
1 | # MyCLI Agent Guide |
CLI 的未来:不只是有帮助文档,而是能主动”教会 Agent 怎么用自己”。
九、交互模式优雅,非交互模式绝对可靠
传统 CLI 很喜欢:首次运行弹登录、删除前 Are you sure?、参数缺失进表单、spinner、Press any key——对人类友好,对 Agent 是灾难。
9.1 严格区分两种模式
| 交互(TTY) | 非交互(CI/Agent) | |
|---|---|---|
| 彩色 | ✅ | ❌(遵守 NO_COLOR) |
| 进度条/spinner | ✅ | ❌(改用 NDJSON 事件) |
| 二次确认弹窗 | ✅ | ❌(需要时显式要 --yes) |
| 参数缺失进表单 | ✅ | ❌(直接退 2) |
| 首次运行登录向导 | ✅ | ❌(报错并提示 env 变量) |
判断依据:isatty(stdin) && isatty(stdout) + 环境变量 CI / MYCLI_NON_INTERACTIVE。
9.2 遵守业界公约
NO_COLOR环境变量(no-color.org)存在即关闭所有 ANSI 色彩,不论 TTY。TERM=dumb同样应关闭彩色与光标控制。- SIGPIPE 要优雅处理:上游
| head -n 10被关闭管道时不要报错退出。
十、安全分级要编码进命令语义
面向 Agent 的 CLI,安全不能只靠 README 里的”请谨慎使用”。
分级
- read:查询、列举、预览、diff。
- write:创建、更新、触发执行。
- dangerous:删除、覆盖、清空、支付、发布到生产。
配套机制
read:直接执行。write:需--yes(非交互场景)。dangerous:需--force,关键操作再加--confirm <resource-id>要求 Agent 复述 ID。
1 | mycli config update --file prod.yaml --yes |
参考 kubectl delete 与 terraform destroy:前者用 --force --grace-period=0,后者强制交互确认除非 -auto-approve——都是把风险编码进参数的好例子。
让 Agent 具备可验证的安全边界。很多系统失败,并不是模型不会推理,而是工具给了它”过度自由”。
十一、命令应该幂等、可重试、可预演
Agent 会天然地重试。只要你给它一个”可能是临时失败”的信号,它大概率会再次执行。
11.1 幂等 key / 去重语义
1 | mycli invoice create --request-id req_20260421_abc --json |
服务端用 request_id 去重 24h,第二次调用返回同一结果而不是创建新记录。
11.2 --dry-run
1 | mycli release deploy --env prod --dry-run --json |
11.3 plan / apply 二阶段(参考 Terraform)
1 | mycli infra plan --out plan_123.json |
把”理解变化”和”执行变化”拆开,Agent 可以先读 plan、让人类或另一个模型审一遍,再 apply。
11.4 显式标注错误是否可重试
1 | { |
十二、资源标识与时间要机器友好
❌ 反例
1 | NAME STATUS CREATED |
问题:相对时间无法稳定比较;名称可能不唯一;列宽表格难以解析。
✅ 正例
1 | { |
纪律
- 每个资源都有稳定、URL-safe、带前缀的 ID(
prj_、usr_、rel_),便于 Agent 一眼识别类型。 - 时间一律 ISO-8601 UTC,不受
LC_ALL/ 时区影响。 - 状态是闭集合枚举。
- 任何对名称的操作都要支持用 ID 替代(
mycli project get --id prj_123而不是只能--name)。
十三、参数命名直白,凭证走安全通道
13.1 参数命名
❌ 反例:tool do -x -m fast
✅ 正例:tool convert --input in.md --output out.html --mode fast
规则:
- 少用无语义短参数(
-h/-v除外)。 - 长参数优先,与领域模型命名一致。
- 枚举值可预测、可 discover。
- 同一个参数在不同子命令下语义不要漂移。
判断标准:脱离文档时,模型能不能大致猜中用途?
13.2 凭证注入:三种方式的优先级
| 方式 | 推荐度 | 说明 |
|---|---|---|
环境变量(MYCLI_TOKEN) | ⭐⭐⭐ | CI/Agent 默认 |
stdin(--token-stdin) | ⭐⭐⭐ | 避免进 shell history |
配置文件(~/.mycli/config) | ⭐⭐ | 人类日常使用 |
命令行参数(--token xxx) | ❌ | 会进 ps/history,不要做 |
并且:
- 永远不要把 token 回显到 stdout 或 stderr(包括
--verbose模式)。 - 错误信息里暴露 token 前 4 位用于调试即可。
- 支持
mycli auth whoami --json让 Agent 自检当前身份。
十四、环境可移植性:别让 Agent 死在依赖上
Agent 对环境脆弱性的容忍度远低于人类开发者——人类会手动修,Agent 往往只会”再试一次”。
优先目标:
- 单文件分发(Go/Rust 的天然优势;Python 可用 PyInstaller / uv 单二进制)。
- 最少运行时依赖、无需人工激活虚拟环境。
mycli --version输出 semver + commit hash + build date。mycli doctor自检:依赖、认证、网络、权限一次性扫描并结构化报告。- 缺失依赖时给结构化错误 + 修复建议,不要只打印
ImportError。
1 | $ mycli doctor --json |
十五、把 CLI 当产品来做评测
工具质量不只靠单元测试,还要靠系统化评测——尤其是让真实 Agent 去跑一遍。
三层评测
1)语法层:参数一致性、--help 完整性、所有核心命令 --json 覆盖、错误码稳定。
2)契约层:stdout/stderr 不混、JSON schema 无漂移、non-TTY 不阻塞、错误可恢复、NDJSON 终态事件必有。
3)Agent 实战层:给真实 Agent 一组任务,统计指标。
最小评测脚本(Agent 实战层)
1 | # eval_suite.yaml |
每次发版跑一遍,退化立即可见。
十六、【新增】存量 CLI 的渐进式改造路径
大部分读者不是新写 CLI,而是改老的。一口气重写成本过高,建议按下列顺序 retrofit(每步都能单独发布、独立收益):
- Phase 0(1 天):确认 stdout/stderr 纪律,把所有日志挪到 stderr。
- Phase 1(1 周):核心 3–5 个命令加
--json,字段按{ok, data, meta}结构。 - Phase 2(1 周):错误走结构化 JSON + 退出码分层,补
retryable字段。 - Phase 3(2 周):长任务改造成 NDJSON;加分页、字段投影、
--limit。 - Phase 4(1 周):非交互模式严格化(NO_COLOR、
--yes、不弹任何向导)。 - Phase 5(持续):写
AGENTS.md、建评测集、每版本跑一遍。 - Phase 6(可选):MCP server 薄壳封装。
反模式:一次性推倒重来、把所有命令都加 --json 但 schema 不稳定、AGENTS.md 写了但不跟代码同步演进。
十七、【新增】真实 CLI 案例点评
学习最快的方式是看业界做对和做错的地方。
kubectl:-o json/-o yaml/-o jsonpath是典范;缺点是kubectl apply的输出一会儿人类文本一会儿结构化,非-o场景 stderr/stdout 也有混用。gh(GitHub CLI):--json field1,field2字段投影做得极好,极大压缩 Agent 上下文;gh api暴露底层 REST 兜底;AGENTS.md式引导欠缺。stripeCLI:--api-key和 env var 组合清晰,stripe events resume幂等支持好;错误 JSON 结构稳定。terraform:plan/apply二阶段、-auto-approve、-json流式输出是 Agent 友好模板级案例。awsCLI v2:--output json默认结构化、分页--max-items/--starting-token完善;但帮助文档过长、子命令数量巨大,Agent 首次建模成本高——提醒我们 discoverability 要配合AGENTS.md裁剪。docker:历史包袱重,docker ps默认输出表格且列不稳定,--format '\{\{json \.\}\}'是事实标准但不直观——反面教材:JSON 不该是隐藏档。npm/pnpm:--json覆盖不全、错误信息人机混排是典型反例。
十八、最容易被忽略的一点
很多人以为”面向 Agent 友好 = 多加个 --json“。
真正让人眼前一亮的 CLI,不是”让 Agent 能调”,而是:
它会主动降低 Agent 的推理负担。
具体表现:
- 不让 Agent 猜输出格式 → 稳定 JSON schema + 版本号
- 不让 Agent 猜下一步该调哪个命令 →
AGENTS.md+ workflow 示例 - 不让 Agent 猜错误是否可重试 →
retryable字段 - 不让 Agent 猜这个操作是不是危险 → read/write/dangerous 分级 +
--confirm - 不让 Agent 猜资源标识该怎么取 → 稳定 ID + ISO 时间
- 不让 Agent 猜非交互模式会不会卡住 → 严格的 TTY 检测与退出纪律
- 不让 Agent 猜输出会不会爆窗口 → 默认截断 + 分页 + 字段投影
把复杂性消解在工具设计里,而不是丢给模型。 这是 AI 时代 CLI 设计真正的升级方向。
十九、Agent-Friendly CLI 自查清单(打印贴墙版)
输出契约
- stdout 只输出数据,stderr 只输出日志/提示
- 所有核心命令支持
--json - JSON 采用
{ok, data, meta}或等价的稳定结构 -
meta.schema_version字段存在 - 空值返回结构而非
"No results" - 长任务支持 NDJSON(
--json=stream)并以终态事件收尾 - 时间全部 ISO-8601 UTC
- 资源有稳定、带前缀的 ID
错误处理
- 退出码分层(至少区分:参数错 / 认证 / 找不到 / 临时失败 / 冲突)
- 错误以 JSON 返回,带
code/message/hint/retryable - 退出码在
--help中文档化
体积与性能
- 列表命令默认
--limit,支持--cursor分页 - 支持
--fields字段投影 - 支持
--filter/--since等过滤 - 被截断时有
truncated: true信号
交互 vs 非交互
- TTY/non-TTY 行为明确区分
- 遵守
NO_COLOR公约 - 非交互模式下绝不等待输入
- 需要确认的操作有
--yes/--force
安全
- 命令按 read/write/dangerous 分级
- 危险操作需
--confirm <resource-id>复述 - 凭证不走命令行参数,不回显到任何输出
Discoverability
- 层级化
--help,每个子命令都有 - 帮助里写明 stdout/stderr/exit code 契约
- 每个高频命令有可直接运行的 example
- 提供 shell completion
- 有
mycli doctor自检 - 有
mycli --version含 commit hash
Agent 文档
- 仓库有
AGENTS.md - 包含 workflow、invariants、gotchas、风险表
- 有 Agent 评测集,每版本跑一次
工程可移植性
- 单文件分发或极少依赖
- 缺失依赖给结构化错误与修复建议
二十、结语:CLI 正在变成”可组合的文本协议”
在 GUI 时代,软件的核心竞争力常常体现在界面。
但在 Agent 时代,很多系统首先被消费的,不再是界面,而是:
- 命令结构
- 输出契约
- 错误语义
- 权限边界
- 帮助系统
- 可组合性
从这个意义上说,CLI 正在重新变得重要——不是因为大家回到了终端,而是因为 Agent 天生适合终端。
所以面向 AI / Agent 开发 CLI,最值得记住的一句话是:
把你的 CLI 当成一个给模型调用的 API 来设计,而不是一个给人临时敲一下的命令。
这样做,CLI 才会从”脚手架工具”进化成”Agent 基础设施”。
附录:延伸阅读
- clig.dev — 经典 Command Line Interface Guidelines
- no-color.org —
NO_COLOR环境变量公约 - BSD
sysexits.h— 退出码约定 - AGENTS.md / llms.txt — Agent 时代兴起的仓库级元数据约定
- Terraform plan/apply、Kubernetes
kubectl -o json、GitHubgh --json— 值得研究的工业级 agent-friendly 实现
变更记录(v1.0 → v1.1)
- 新增:CLI 与 MCP 的关系对比(第一节)
- 新增:NDJSON 流式输出章节(第四节)
- 新增:输出体积与 token 预算章节(第五节)
- 新增:凭证注入安全通道(第十三节)
- 新增:存量 CLI 渐进式改造路径(第十六节)
- 新增:真实 CLI 案例点评(第十七节)
- 新增:自查清单(第十九节)
- 扩充:退出码章节补上 sysexits.h 引用
- 重命名:
SKILL.md→AGENTS.md,补充社区标准说明 - 补充:NO_COLOR / SIGPIPE / shell completion 业界公约
- 每节尽量补充”❌ 反例 / ✅ 正例”对照
- 调整:原 15、16 节合并精简为第十八、二十节
怎么抢高铁票
可以买长乘短
大站票多
抢直达车,多刷新下页面,多点点,网络拥塞,又可能能挤进去
直达车无,买中转
候补直达车
-
土法炼钢兴趣小组的博客
- 【可观测性工程】可观测性全景:Metrics、Logs、Traces、Profiles、Events 五大支柱从控制论到云原生:拆解可观测性的五大信号支柱,对比监控与可观测性的本质区别,梳理开源/商业/SaaS 分类,以及国内互联网公司三大支柱落地现状与典型工程坑点。
【可观测性工程】可观测性全景:Metrics、Logs、Traces、Profiles、Events 五大支柱
-
土法炼钢兴趣小组的博客
- 【可观测性工程】可观测性 vs 监控:从 Zabbix/Nagios 到 OpenTelemetry 的二十年监控与可观测性不是新旧迭代,而是认知模型的根本转换。本文梳理从 1999 年 Nagios 到 2019 年 OpenTelemetry 的二十年演进时间线,对比 push/pull 模型、数据模型差异,以及国内从 Zabbix 到 Prometheus 再到 OTel 的典型迁移路径与工程坑点。
【可观测性工程】可观测性 vs 监控:从 Zabbix/Nagios 到 OpenTelemetry 的二十年
-
土法炼钢兴趣小组的博客
- 【可观测性工程】指标体系设计:USE、RED、Golden Signals 与业务 KPIUSE 方法论适用于资源,RED 方法论适用于请求,Golden Signals 适用于服务——三套方法论各有其适用对象。本文从 Brendan Gregg、Tom Wilkie、Google SRE 的原始定义出发,构建覆盖资源→服务→业务的完整指标体系,并给出 Prometheus 命名规范、基数治理策略与可抄的指标清单。
【可观测性工程】指标体系设计:USE、RED、Golden Signals 与业务 KPI
-
土法炼钢兴趣小组的博客
- 【可观测性工程】Metrics:Prometheus、VictoriaMetrics、Thanos、Mimir、M3从 Prometheus 架构与数据模型出发,系统梳理 Remote Write、PromQL 进阶、Thanos 全局聚合、Mimir 多租户、VictoriaMetrics 性能、M3DB 原理,以及五者在大规模生产场景下的对比矩阵与迁移实践。
【可观测性工程】Metrics:Prometheus、VictoriaMetrics、Thanos、Mimir、M3
-
土法炼钢兴趣小组的博客
- 【可观测性工程】时序数据库内核:TSM、TSI、倒排索引与 Gorilla 压缩深入时序数据库的存储内核:Prometheus TSDB 的 WAL 与块管理、InfluxDB 的 TSM 引擎与 TSI 倒排索引、Gorilla 压缩算法的数学原理、VictoriaMetrics mergeset 架构、ClickHouse MergeTree 作为 metrics 后端,以及国内大厂在 series churn 和 compaction 风暴上踩过的坑。