标签 思考 下的文章

写作即思考:AI 时代,开发者为什么要警惕“思考外包”?

本文永久链接 – https://tonybai.com/2025/07/25/writing-is-thinking

大家好,我是Tony Bai。

最近,全球顶级的科学期刊《自然》(Nature) 发表了一篇社论,标题仅有三个词:“Writing is thinking” (写作即思考)。

这篇社论探讨的是大语言模型时代人类生成的科学写作的价值,其核心观点,对于我们技术领域的开发者、工程师和内容创作者来说,不啻为一记振聋发聩的警示。它在 AI 浪潮席卷一切的今天,迫使我们重新审视一个被我们日渐忽视,却又至关重要的行为——我们自己的思考过程。

开发者版本的“写作即思考”

对开发者而言,“写作”的形式多种多样:
* 编写一份详尽的技术设计文档 (Design Doc / RFC)。
* 撰写一篇分享经验的技术博客。
* 甚至,是构建一个结构清晰、逻辑严谨的复杂软件模块。

这些行为的本质,都和《自然》社论的观点一致:它不仅仅是“报告结果”,更是一个强迫我们将脑中混乱、非线性的想法,梳理成结构化、有意图的叙事的过程。

当你无法用清晰的语言(或代码)写下来时,通常意味着你对这个问题还没有想清楚。这个“写”的过程,本身就是发现逻辑漏洞、提炼核心思想、明确最终影响力的思考过程。正如社论所引述的科学依据:书写行为本身,就能增强大脑的连接性,并对学习和记忆产生积极影响。

AI 带来的“隐形危机”:思考外包

现在,强大的 LLM 出现了。我们似乎可以轻易地“外包”掉这个艰苦的思考过程。

“帮我生成一份关于XX系统的微服务架构设计文档。”
“为我刚才的 Go 函数编写一份详细的单元测试。”

AI 瞬间就能产出看似完美的“结果”。但在这个过程中,我们失去了什么?

  1. 效率的假象: AI 会产生幻觉。你可能需要花费更多的心力去验证、修正和编辑一份由 AI 生成的、你并不完全理解的复杂文档或代码,其成本甚至可能超过从零开始亲自撰写。
  2. 思想的归属: 社论提出了一个尖锐的问题——如果“写作即思考”,那么当你在阅读一篇由 LLM 生成的论文时,你读到的究竟是研究者的思想,还是 LLM 的“思想”?同理,当你的同事向你展示一份由 AI 生成的设计文档时,这背后真的有他深入的思考和权衡吗?
  3. 核心能力的侵蚀: 这是最危险的一点。我们跳过了最宝贵的思考整理过程,直接获取了“结果”,却失去了将知识和经验内化为自身能力的宝贵“过程”。我们放弃了锻炼自己核心思维能力的机会。

从“外包者”到“放大器”:AI 的正确使用姿势

那么,我们应该抵制 AI 吗?当然不。《自然》的社论也明确指出,AI 是一个极其有价值的辅助工具。问题的关键,不在于用不用,而在于怎么用。

我们应该警惕成为一个“思考外包者”,转而努力成为一个“思考放大器”的使用者。

这意味着,永远由人类掌握“思考”的主导权,而在特定的、非核心思考的环节,利用 AI 来提升效率。以下是一些高效的“放大器”模式:

  • 语法与可读性优化器: “这是我写的一段技术描述,请帮我润色,使其更易于理解,并修正语法错误。”
  • 信息检索与综述助理: “帮我总结一下最近关于 QUIC 协议的三篇关键论文的核心观点。”
  • 头脑风暴伙伴: “我正在设计一个高可用的缓存系统,请帮我列出可能需要考虑的 10 个潜在故障点。”
  • “破冰”与“思路转换”工具: “我对于如何向非技术人员解释‘幂等性’感到卡壳,请提供三种不同的比喻或解释方式。”

在这些场景中,AI 是你的研究助理、语法老师、灵感催化剂,但绝不是替你完成核心思考的“枪手”。

未来已来:从“代码实现者”到“思想叙事者”

这场关于“写作与思考”的讨论,最终引向了一个更宏大的问题:当 AI 越来越擅长“写作”(即编码实现)时,我们人类工程师的不可替代价值到底在哪里?

答案或许就在《自然》社论的结尾:“将整个写作过程外包给 LLM,会剥夺我们反思和塑造引人入胜的叙事的机会”。

未来工程师的核心竞争力,正在从单纯的技术实现,向上游转移。以下三项“元技能”将变得至关重要:

  • 深度反思能力: 对技术领域、业务场景进行深刻的洞察和反思,理解“为什么”远比“怎么做”更重要。
  • 创造性任务处理能力: 定义正确的问题,做出关键的架构取舍,进行富有创造力的系统设计。
  • 思想叙事能力: 能够将复杂的技术决策、系统设计,用清晰、有说服力的“故事”(设计文档、技术演讲、甚至代码结构本身)讲述出来,影响和说服他人。

你看,这三项无法被 AI 替代的核心能力,恰恰都是通过“写作即思考”这个艰苦而宝贵的过程来培养和强化的。

小结:别让 AI 替你思考

AI 是一场革命性的技术浪潮,它正在重塑我们的工作方式。但我们必须保持清醒:AI 是我们手中的工具,而不是我们大脑的替代品。

我们可以,也应该,让 AI 成为我们强大的“副驾驶”,帮我们处理繁琐的事务,为我们提供新的视角。但方向盘,必须始终握在我们自己手中,谨慎和正确使用带有深度思考和推理功能的AI大模型。

因为我们写下的每一行代码,每一份文档,不仅仅是交付物,更是我们思考过程的凝结与沉淀。这个过程,才是我们作为工程师,最宝贵的财富。

资料链接:https://www.nature.com/articles/s44222-025-00323-4


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

探讨Docker容器中修改系统变量的方法

探讨完Docker对共享内存状态持久化的支持状况后,我将遗留产品build到一个pre-production image中,测试启动是否OK。很显然,我过于乐观了,Docker之路并不平坦。我收到了shmget报出的EINVAL错误码,提示参数非法。 shmget的manual对EINVAL错误码的说明如下:

EINVAL:
A  new  segment  was  to  be  created  and size < SHMMIN or size > SHMMAX, or no new segment was to be created, a segment with given key existed, but size is greater than the size of that segment.

显然我们要创建的shared memory的size很可能大于SHMMAX这个系统变量了。那么一个从base image创建出的容器中的系统变量到底是什么值呢?我们来查看一下,我们基于"centos:centos6"启动一个Docker容器,并检查其中的 系统变量值设置:

$ sudo docker run -it "centos:centos6" /bin/bash
bash-4.1# cat /proc/sys/kernel/shmmax
33554432
bash-4.1# sysctl -a|grep shmmax
kernel.shmmax = 33554432

可以看出默认情况下,当前容器中root账号看到的shmmax值我33554432, 我的程序要创建的shm size的确要大于这个值,报出EINVAL错误也就无可厚非了。我尝试按照物理机上的方法临时修改一下该值:

bash-4.1# echo 68719476736 > /proc/sys/kernel/shmmax
bash: /proc/sys/kernel/shmmax: Read-only file system

/proc/sys/kernel/shmmax居然是只读的,无法修改。

我又尝试修改/etc/sysctl.conf这个持久化系统变量的地方,但打开/etc/sysctl.conf文件,我发现我又错了,这 个文件中shmmax的值如下:

# Controls the maximum shared segment size, in bytes
kernel.shmmax = 68719476736

/etc/sysctl.conf文件 中的系统变量shmmax的值是68719476736,而系统当前的实际值则是33554432,难道是/etc /sysctl.conf中的值没有生效,于是我手工重新加载一次该文件:

-bash-4.1# sysctl -p
error: "Read-only file system" setting key "net.ipv4.ip_forward"
error: "Read-only file system" setting key "net.ipv4.conf.default.rp_filter"
error: "Read-only file system" setting key "net.ipv4.conf.default.accept_source_route"
error: "Read-only file system" setting key "kernel.sysrq"
error: "Read-only file system" setting key "kernel.core_uses_pid"
error: "net.ipv4.tcp_syncookies" is an unknown key
error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key
error: "net.bridge.bridge-nf-call-iptables" is an unknown key
error: "net.bridge.bridge-nf-call-arptables" is an unknown key
error: "Read-only file system" setting key "kernel.msgmnb"
error: "Read-only file system" setting key "kernel.msgmax"
error: "Read-only file system" setting key "kernel.shmmax"
error: "Read-only file system" setting key "kernel.shmall"

我得到了和之前类似的错误结果:只读文件系统,无法修改。于是乎两个问题萦绕在我的面前:
1、为什么容器内当前系统变量值与sysctl.conf中的不一致?
2、为什么无法修改当前系统变量值?

在翻阅了Stackoverflow, github docker issues后,我得到了的答案如下:

1、Docker的base image做的很精简,甚至都没有init进程,原本在OS启动时执行生效系统变量的过程(sysctl -p)也给省略了,导致这些系统变量依旧保留着kernel默认值。以CentOs为例,在linux kernel boot后,init都会执行/etc/rc.d/rc.sysinit,后者会加载/etc/sysctl.conf中的系统变量值。下面是 CentOs5.6中的rc.sysinit代码摘录:

… …
# Configure kernel parameters
update_boot_stage RCkernelparam
sysctl -e -p /etc/sysctl.conf >/dev/null 2>&1
… …

2、Docker容器中的系统变量在non-priviledged模式下目前(我使用的时docker 1.2.0版本)就无法修改,这 和resolv.conf、hosts等文件映射到宿主机对应的文件有不同。

$ mount -l
…. ….
/dev/mapper/ubuntu–Server–14–vg-root on /etc/resolv.conf type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/mapper/ubuntu–Server–14–vg-root on /etc/hostname type ext4 (rw,relatime,errors=remount-ro,data=ordered)
/dev/mapper/ubuntu–Server–14–vg-root on /etc/hosts type ext4 (rw,relatime,errors=remount-ro,data=ordered)
… …

那么我们该如何修改系统变量值来满足遗留产品的需求呢?

一、使用–privileged选项

我们使用–privileged这个特权选项来启动一个基于centos:centos6的新容器,看看是否能对shmmax这样的系统变量值 进行修改:

$ sudo docker run -it –privileged  "centos:centos6" /bin/bash
bash-4.1# cat /proc/sys/kernel/shmmax
33554432
bash-4.1# echo 68719476736 > /proc/sys/kernel/shmmax
bash-4.1# cat /proc/sys/kernel/shmmax
68719476736

bash-4.1# sysctl -p
net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
… …
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296

可以看出,通过–privileged选项,容器获得了额外的特权,并且可以对系统变量的值进行修改了。不过这样的修改是不能保存在容器里的, 我们stop 容器,再重启该容器就能看出来:

$ sudo docker start 3e22d65a7845
$ sudo docker attach 3e22d65a7845
bash-4.1# cat /proc/sys/kernel/shmmax
33554432

shmmax的值在容器重启后又变回了原先的那个默认值。不过重启后的容器依旧具有privileged的特权,我们还可以重新手工执行命令对系 统变量进行修改:

bash-4.1# echo 68719476736 > /proc/sys/kernel/shmmax
bash-4.1# cat /proc/sys/kernel/shmmax
68719476736

但即便这样,也无法满足我们的需求,我们总不能每次都在容器中手工执行系统变量值修改的操作吧。privileged选项的能力能否带到 image中呢?答案是目前还不能,我们无法在build image时通过privileged选项修改系统变量值。

这样一来,我们能做的只有把产品启动与系统变量值修改放在一个脚本中了,并将该脚本作为docker 容器的cmd命令来执行,比如我们构建一个Dockerfile:

FROM centos:centos6
MAINTAINER Tony Bai <[email protected]>
RUN yum install python-setuptools -y
RUN easy_install supervisor
RUN mkdir -p /var/log/supervisor
COPY ./supervisord.conf /etc/supervisord.conf
COPY ./start.sh /bin/start.sh
RUN chmod +x /bin/start.sh
CMD ["/bin/start.sh]

//start.sh
sysctl -p
/usr/bin/supervisord

这样,start.sh在supervisord启动前将系统变量值重新加载,而supervisord后续启动的程序就可以看到这些新系统变量 的值了。不过别忘了利用这个image启动容器时要加上–priviledged选项,否则容器启动就会失败。

二、使用phusion/baseimage

前面说过/etc/sysctl.conf中的值没有生效是因为docker官方提供的centos:centos6把init进程的初始化过程给精 简掉了。phusion/baseimage是目前docker registery上仅次于ubuntu和centos两个之后的base image,其提供了/sbin/my_init这个init进程,用于在container充当init进程的角色。那么my_init是否可以用于执行sysctl -p呢?我们试验一下:

我们先pull这个base image下来:sudo docker pull phusion/baseimage。pull成功后,我们先基于“phusion/baseimage”启动一个容器做一些explore工作:

$ sudo docker run -i -t "phusion/baseimage"
*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh…
No SSH host key available. Generating one…
Creating SSH2 RSA key; this may take some time …
Creating SSH2 DSA key; this may take some time …
Creating SSH2 ECDSA key; this may take some time …
Creating SSH2 ED25519 key; this may take some time …
invoke-rc.d: policy-rc.d denied execution of restart.
*** Running /etc/rc.local…
*** Booting runit daemon…
*** Runit started as PID 100

通过nsenter进去,查看一下/sbin/my_init的源码,我们发现这是一个python脚本,不过从头到尾浏览一遍,没有发现sysctl加载/etc/sysctl.conf系统变量的操作。

不过,phusion文档中说my_init可以在初始化过程中执行/etc/my_init.d下的脚本。那是不是我们将一个执行sysctl -p的脚本放入/etc/my_init.d下就可以实现我们的目的了呢?试试。

我们编写一个脚本:load_sys_varibles.sh

#!/bin/sh
sysctl -p > init.txt

下面是制作image的Dockerfile:

FROM phusion/baseimage:latest
MAINTAINER Tony Bai <[email protected]>
RUN echo "kernel.shmmax = 68719476736" >> /etc/sysctl.conf
RUN mkdir -p /etc/my_init.d
ADD load_sys_varibles.sh /etc/my_init.d/load_sys_varibles.sh
RUN chmod +x /etc/my_init.d/load_sys_varibles.sh
CMD ["/sbin/my_init"]

phusion/baseimage是基于ubuntu的OS,其sysctl.conf默认情况下没啥内容,所以我们在Dockerfile中向这个文件写入我们需要的系统变量值。构建image并启动容器:

$ sudo docker build -t "myphusion:v1" ./
Sending build context to Docker daemon 13.12 MB
Sending build context to Docker daemon
Step 0 : FROM phusion/baseimage:latest
 —> cf39b476aeec
Step 1 : MAINTAINER Tony Bai <[email protected]>
 —> Using cache
 —> d0e9b51a3e4f
Step 2 : RUN echo "kernel.shmmax = 68719476736" >> /etc/sysctl.conf
 —> Using cache
 —> 2c800687cc83
Step 3 : RUN mkdir -p /etc/my_init.d
 —> Using cache
 —> fe366eea5eb4
Step 4 : ADD load_sys_varibles.sh /etc/my_init.d/load_sys_varibles.sh
 —> a641bb595fb9
Removing intermediate container c381b9f001c2
Step 5 : RUN chmod +x /etc/my_init.d/load_sys_varibles.sh
 —> Running in 764866552f25
 —> eae3d7f1eac5
Removing intermediate container 764866552f25
Step 6 : CMD ["/sbin/my_init"]
 —> Running in 9ab8d0b717a7
 —> 8be4e7b6b174
Removing intermediate container 9ab8d0b717a7
Successfully built 8be4e7b6b174

$ sudo docker run -it "myphusion:v1"
*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh…
No SSH host key available. Generating one…
Creating SSH2 RSA key; this may take some time …
Creating SSH2 DSA key; this may take some time …
Creating SSH2 ECDSA key; this may take some time …
Creating SSH2 ED25519 key; this may take some time …
invoke-rc.d: policy-rc.d denied execution of restart.
*** Running /etc/my_init.d/load_sys_varibles.sh…
sysctl: setting key "kernel.shmmax": Read-only file system
*** /etc/my_init.d/load_sys_varibles.sh failed with status 255

*** Killing all processes…

唉,还是老问题!即便是在my_init中执行,依旧无法逾越Read-only file system,查看Phusion/baseimage的Dockerfile才知道,它也是From ubuntu:14.04的,根不变,上层再怎么折腾也没用。

换一种容器run方法吧,加上–privileged:

$ sudo docker run -it –privileged  "myphusion:v1"
*** Running /etc/my_init.d/00_regen_ssh_host_keys.sh…
No SSH host key available. Generating one…
Creating SSH2 RSA key; this may take some time …
Creating SSH2 DSA key; this may take some time …
Creating SSH2 ECDSA key; this may take some time …
Creating SSH2 ED25519 key; this may take some time …
invoke-rc.d: policy-rc.d denied execution of restart.
*** Running /etc/my_init.d/load_sys_varibles.sh…
*** Running /etc/rc.local…
*** Booting runit daemon…
*** Runit started as PID 102

这回灵光了。enter到容器里看看设置的值是否生效了:

root@9e399f46372a:~#cat /proc/sys/kernel/shmmax
68719476736

结果如预期。这样来看phusion/baseimage算是为sysctl -p加载系统变量值提供了一个便利,但依旧无法脱离–privileged,且依旧无法在image中持久化这个设置。

在Docker github的issue中有人提出建议在Dockerfile中加入类似RUNP这样的带有特权的指令语法,但不知何时才能在Docker中加入这一功能。

总而言之,基于目前docker官网提供的base image,我们很难找到特别理想的修改系统变量值的方法,除非自己制作base image,这个还没尝试过,待后续继续研究。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats