分类目录归档:PHP

PHP源码,PHP扩展,PHP程序

程序员的北京折叠:生存、焦虑与抉择

引子:从《北京折叠》说起

《北京折叠》是郝景芳的一篇著名科幻小说,最早于 2012 年 12 月发表在清华大学的学生论坛水木社区的科幻版。2016 年获得第 74 届雨果奖最佳中短篇小说奖,2018 年获得第 49 届星云赏海外部门短篇小说奖项。雨果奖介绍这篇小说「构建了一个不同空间、不同阶层的北京,可像‘变形金刚般折叠起来的城市’,却又‘具有更为冷峻的现实感’」。

《北京折叠》讲述了北京这个城市被分割成了三个空间,每个空间的人们在各自的时空中生活,彼此之间几乎没有交集。第一空间的人高高在上,掌控着资源与权力;第二空间的中产阶级维持着相对体面的生活;第三空间的人则在贫困、压抑中挣扎求生。三层空间的生活轨迹几乎不会重叠,仿佛他们生活在完全不同的世界中。

作为一名程序员,这个故事让我不禁联想到我们这个行业中的「折叠北京」,在不同的公司、岗位和城市,程序员们同样被划分成了不同的「空间」。每个人的职业轨迹、生活方式和所面临的问题大相径庭,甚至无法体验到他人生活中的酸甜苦辣。

我曾在大厂呆过,在小公司也做过,自己也曾创业。在这些不同的「空间」里,我看到了程序员群体的多样性,感受到了他们各自的焦虑与困境。今天,我想借用《北京折叠》的框架,来聊聊程序员世界中的三种「空间」,它们之间的壁垒、差异,以及偶尔交错的瞬间。

1. 第一空间:大厂程序员的「黄金时代」

在程序员的世界里,第一空间无疑是那些在头部互联网大厂工作的精英们。字节跳动、阿里巴巴、腾讯、网易等巨头公司,几乎可以说是这个行业的象征。对于很多年轻程序员来说,进入大厂意味着职业生涯的「黄金时代」——高薪酬、丰厚的福利、甚至是行业内的一些光环,仿佛一切都昭示着成功与荣耀。

1.1 高压环境中的「内卷」

在大厂工作,最直观的感受就是无处不在的竞争。这种竞争不仅来源于外部市场的技术更新、产品迭代,更深刻地体现在公司内部,尤其是在同事之间。这种现象在互联网行业尤为明显,因此,很多人用「内卷」一词来概括大厂程序员们的工作环境。

1.1.1 绩效排名和末位淘汰制

大厂程序员普遍面临着严格的绩效考核制度。像字节跳动、阿里巴巴等公司,通常实行「361」类的强制考核,即在每次考核中,前20%的员工拿到最好的绩效,而后 20% 左右则面临淘汰的风险。每半年(或者一个季度)一次的绩效考核期,几乎是程序员们最为紧张的时刻,生怕自己成为「差劲」或「末位淘汰」的一员。

这种考核机制确实激励了员工不断提升自我,但也带来了巨大的心理压力和工作负担。为了在绩效评估中脱颖而出,程序员们不得不超负荷工作,甚至牺牲健康和个人生活。许多大厂的加班文化已成常态,尤其是在实行“996”工作制度的公司,程序员们的工作时长远远超出了法律规定的标准。

更为严重的是,由于绩效考核的竞争性,团队内部的合作有时变得愈发功利化。项目的成功不仅关乎团队整体的荣誉,还直接决定了每个人的绩效评定。于是,暗中较劲、互相攀比的现象时有发生,团队协作因此变得更加复杂且微妙。

1.1.2 怎样才算「成功」?

在大厂的程序员群体中,有一种不成文的共识:成功的标志不是你是否能够完成日常的任务,而是你能否写出新技术、推动新项目,甚至在团队中成为某个领域的权威。每个人都在追求「技术大咖」的头衔,渴望在某个技术社区或者公司内部的技术分享会上崭露头角。技术的不断迭代让人们时刻保持学习的心态,但这种持续的自我提升也带来了巨大的压力。

有时我会和一些在大厂的朋友聊起他们的生活,发现他们的焦虑和我在小厂时的焦虑并没有本质区别。尽管他们拿着比普通程序员高得多的工资,但他们的时间成本、精神压力和对未来的迷茫感也不比别人少。他们的生活轨迹看上去光鲜亮丽,但其实也是在一种高强度的环境中挣扎生存。

为了在考核中脱颖而出,程序员们会拼命寻找可以量化的业绩,比如开发新功能、优化系统性能、贡献开源项目等。然而,这种短期导向的行为,往往导致大量的重复劳动。不同的团队、甚至同一团队的成员,可能都在做相似的工作,因为每个人都希望自己的成果被视为「独创贡献」。

这种过度竞争导致了资源的浪费和技术的冗余。比如,不同团队可能会开发多个功能类似的工具或系统,但由于每个团队都希望展示自己的「独立成果」,这些项目往往没有被整合,造成了效率低下。这种「重复造轮子」的现象在大厂程序员中屡见不鲜,不同的部门,甚至不同的中心各有一套技术栈或管理系统的很常见。这不仅浪费了时间和资源,也让公司的整体创新能力受到抑制。

1.2 裁员潮下的生存危机

1.2.1 大厂裁员的频发性

近年来,随着互联网行业的逐渐成熟和增速放缓,国内外的大厂频繁爆出裁员的新闻。无论是由于公司战略调整,还是市场环境的变化,裁员已经成为了大厂的一种常见操作。即使是表现优异的部门,也可能因为公司调整方向而面临裁撤的命运。

大厂裁员并不仅仅针对绩效较差的员工。很多时候,裁员是为了优化成本结构,或者是公司业务重心发生了转移。某些曾经处于风口的业务部门,一旦被认为前景不妙,整个团队可能会在短时间内被解散。例如,一些大厂在短视频、智能硬件等领域的扩张速度过快,导致后期发展遇阻,一旦业务不达预期,相关团队就可能面临大规模裁员。

以字节为例,2023 年底字节跳动官宣大规模裁撤游戏项目和人员,未上线项目几乎全部关停,已上线且表现良好的游戏也要寻求剥离; 2024 年初飞书裁员超过 20%,

这种裁员的不可预测性,给大厂程序员的职业生涯带来了巨大的不确定性。即便你今天的绩效再优秀,也无法保证明天公司不会因为战略调整而决定裁掉你所在的部门。这种生存危机,成为了大厂程序员的长期困扰。

还在某大厂的兄弟说:以前,末位淘汰了还可以增补 HC,但是现在淘汰了就是淘汰了,不会有新的人补充进来,且强制 10% 的比例。这也是一种裁员的逻辑。

1.2.2 「大龄程序员」的困境

裁员的另一大受害者群体是所谓的「大龄程序员」,即那些年龄超过 35 岁、甚至 40 岁以上的技术人员。在很多大厂的文化中,年轻意味着活力和更强的工作负荷承受能力,因此,年龄较大的程序员往往被认为「性价比不高」。

当公司需要削减成本时,首先会考虑那些薪资较高的员工。而大龄程序员由于工龄长、薪资高,往往成为了裁员的首选对象。即便这些程序员有着丰富的技术经验和项目管理能力,但在日新月异的互联网行业,他们的优势往往被削弱。

同时,技术更新日新月异,大龄程序员若无法持续跟上行业的技术潮流,便可能在职业生涯中陷入困境。很多人会在 35 岁之后面临职业发展的瓶颈,不得不思考转型的可能性。

1.3 程序员的「供需失衡」

与十几年前程序员供不应求的情况不同,如今的互联网行业已经趋于饱和。随着越来越多的人涌入这个领域,市场对程序员的需求增速放缓,导致了供需之间的失衡。

在 2024 年 8 月招生季,太原理工 2024 软件工程招 60 个班,近 2000 人,冲上热搜。想象一下,在四年之后的这些学生的就业难度会像「通货膨胀」一样飞速上涨。

这种供需失衡带来了一系列问题。在初级程序员这一级,竞争会更加激烈,很多应届毕业生发现自己面临大量竞争对手,哪怕是基础岗位,也往往需要具备极高的技术能力。

企业在招聘时可以更加挑剔,倾向于选择那些工资要求低、技术基础扎实的年轻程序员,而那些经验丰富但薪资要求较高的资深程序员,反而变得不那么受欢迎。

程序员岗位已经从一个「卖方市场」彻底转变为「买方市场」

在「卖方市场」时期,企业为了吸引优秀的技术人才,往往会提供丰厚的薪资福利和极具吸引力的职业发展机会。然而,随着越来越多的程序员涌入市场,岗位供给的增速却远远赶不上需求的增长,企业开始占据更多的主动权。

在买方市场中,企业可以更加挑剔地选择应聘者,不仅要求候选人具备扎实的技术基础,还希望他们能够适应更高的工作强度和更低的薪资要求。这种局面尤其对初级程序员和应届毕业生不利。哪怕是一些基础岗位,也往往需要较高的技术门槛和项目经验,导致很多刚毕业的学生发现自己难以找到合适的工作机会。

与此同时,资深程序员的处境也不容乐观。那些拥有多年经验的程序员,虽然在技术上更为成熟,但由于薪资要求较高,企业在招聘时往往更愿意选择年轻、成本较低的程序员。这种现象让很多资深程序员陷入了「高不成低不就」的尴尬境地。他们的技术能力虽然依然强大,但在快速变化的互联网行业中,市场对他们的需求开始减少,尤其是在裁员潮和优化成本的背景下,资深程序员的议价能力逐渐被削弱。在就业市场上常常可以看到一个岗位多个人竞争的情况。

1.4 大厂程序员的「中年危机」

1.4.1 技术更新的焦虑

程序员这个职业最大的特点之一是技术更新的快速迭代。每隔几年,行业的技术栈就会发生翻天覆地的变化。从最早的C、C++到如今的云计算、人工智能和区块链,每一波技术浪潮都要求程序员持续学习新知识,适应新的工具和框架。

对于年轻程序员来说,学习新技术可能充满了乐趣和挑战性。但对于年纪较大的程序员来说,技术更新的压力往往带来了巨大的焦虑感。随着年龄增长,学习新技术的难度和精力投入都在增加,而大厂的工作环境又要求程序员始终保持对新兴技术的敏感度。这种持续的技术更新压力,让很多大龄程序员感到力不从心。

1.4.2 顶层的天花板

对于很多大厂程序员来说,最可怕的不是眼前的压力,而是那种隐隐约约的「天花板」感。你很难在大厂中看到五十岁、甚至四十岁以上的程序员,他们的去向仿佛成了一个谜题。

大家心照不宣地知道,到了某个年龄段,技术可能已经不再是你的核心竞争力,管理岗位有限,竞争者众多,如何突破这层「天花板」成了很多大厂程序员内心深处的焦虑。

面对年龄、技术更新和职业发展的瓶颈,很多大厂程序员在 30 岁之后开始考虑职业转型。然而,转型并不是一件容易的事情。大多数程序员的职业技能都围绕技术展开,一旦离开了技术岗位,很多人发现自己在其他领域缺乏竞争力。

常见的转型路径包括转向管理岗位、创业或进入教育培训行业。然而,管理岗位有限,创业风险极大,而教育培训行业本身也在经历着调整。这使得很多程序员在转型的过程中感到困惑和无助。职业发展的瓶颈使得大龄程序员的未来看起来充满了不确定性。

1.5 黄金时代的背后是无尽的焦虑

大厂程序员的生活看似光鲜,但背后却充满了无尽的压力与焦虑。高薪的代价是长期的加班和激烈的内卷;丰厚的待遇伴随着频繁的裁员和职业发展的瓶颈。尤其是大龄程序员,他们不仅面临着技术更新的焦虑,还要应对职业转型的困惑。

在这个日新月异的行业里,大厂程序员的「黄金时代」或许并不像外界看到的那样光鲜。当「中年危机」到来,如何平衡工作与生活、如何应对技术的快速变化,成为了每一个程序员都需要思考的问题。

如 will 老板所说:始终要思考的是如何在大厂活下去!,更进一步:其实更焦虑的是如何靠自己活下去

2. 第二空间:小厂程序员的迷茫与抉择

2.1 资源、团队与技术的困境

在小公司工作的程序员面临的第一个现实问题是资源的匮乏。与大厂程序员相比,小厂程序员的开发环境和资源往往十分有限。预算紧张使得小公司无法购买先进的开发工具,也没有大厂那样完善的基础设施和支持团队。很多时候,程序员需要用「土办法」去解决问题,甚至自己搭建和维护服务器、数据库等基础设施。

虽然现在云服务的使用已经很普遍了,但是能用好云服务的公司不多,甚至在常见的 CI/CD 流程都没有实施。

团队情况也是一个重要因素。小公司里,团队人员往往较少,职责分工不如大公司细致,很多程序员需要身兼数职,既要写代码,还要负责运维、测试,甚至参与产品设计和业务讨论。这种「多面手」的工作方式虽然能让个人能力得到快速锻炼,但也意味着专注度较低,无法在某一个领域深入钻研,导致技术积累不够扎实。

技术的硬门槛是另一大挑战。小公司通常专注于短期业务目标,项目进度往往比技术本身更加重要。这导致程序员在开发过程中可能会放弃对代码质量、性能优化等技术细节的追求,而更多地采用快速上线的策略。这种方式虽然能让产品迅速推向市场,但也限制了程序员的技术视野和思维,长期下去,很容易陷入技术瓶颈

2.2 平台、资源与局限

2.2.1 资源的限制

与大厂相比,小厂程序员的工作环境显得更加局促和紧张。他们没有大公司那样强大的技术团队或前沿的技术工具支持,很多时候只能依赖现有资源,甚至是开源工具来解决问题。

公司往往没有足够的预算去支持技术创新,项目的重点更多地放在如何快速满足客户需求上,而不是技术实现的完美度。因此,小厂程序员的工作更多的是一种「打补丁」的过程,解决眼前的问题,而不是从根本上提升系统的架构或性能。

由于缺少大厂的技术资源和系统流程,小厂程序员在面对复杂问题时只能依赖个人经验和有限的知识储备。这种资源的匮乏,让他们在遇到需要深入技术实现或复杂系统优化的问题时力不从心,也限制了他们的职业发展。

2.2.2 多面手的隐患

小公司经常要求程序员成为「全栈开发者」,不仅要负责前端、后端的开发,还要参与运维、测试,甚至是产品设计。这种「多面手」的角色虽然能在短时间内提升程序员的综合能力,但长期来看,专精度的不足是显而易见的。程序员往往在多个领域都有所涉及,却缺乏一个深耕的方向,导致在某些关键技术上与大厂程序员相比存在明显的差距。

这种现象尤其体现在一些高精尖的领域,比如分布式架构、性能优化、大规模数据处理等。小公司项目的局限性使得程序员鲜有机会接触这些高端技术,即便遇到相关问题,也往往是通过快速修补的方式解决,而不是深入理解和优化。多面手的广度虽然让小厂程序员具备了应对不同问题的能力,但缺乏深度的劣势在面对更高的技术挑战时显露无遗。

2.2.3 重复与瓶颈

小公司项目的重复性也是一个常见的问题。许多小公司专注于某些特定的业务场景,程序员在开发过程中,往往是在重复类似的增删改查操作。长时间在这种环境中工作,程序员容易陷入一种技术思维的局限,觉得自己的工作仅仅是完成客户需求,而忽视了技术本身的提升。这种局限让他们在面对更复杂的项目或系统时,缺乏应对的思路和方法。

在这种环境下,程序员可能会感到希望突破但找不到方向。他们渴望接触更复杂、更有挑战性的技术,但小公司的项目和资源限制了他们的视野,无法提供足够的成长空间。很多程序员在小公司工作多年后,逐渐意识到,自己的技术积累始终停留在某个水平,无法突破。

2.3 对未来的迷茫与期待

2.3.1 稳定性的假象

小厂程序员的处境,常常在稳定与成长之间徘徊。对于很多在小公司干了多年的人来说,工作内容虽然相对稳定,压力小,甚至在某些场合下还能当上小领导,但这种「舒适区」并不一定带来长久的安全感。

尽管有些程序员在小公司工作多年,积累了一定的业务经验,甚至在团队中占据了重要的角色,但这并不意味着未来的职业道路是一片坦途。小公司的抗风险能力差,经济波动或行业萎缩时,很多小公司会迅速陷入困境,甚至倒闭。对于很多 30 岁上下的程序员来说,一旦失去这份相对稳定的工作,他们可能会发现自己在技术上并没有明显优势,面临再就业的难题。

这种不稳定性让很多小厂程序员产生了焦虑感。他们担心公司倒闭后,自己所积累的业务经验和技术能力无法顺利转化到其他公司。尤其是在面对大厂的面试要求时,很多小厂程序员会发现自己的项目经验和技术广度远远不足以应付大厂的高标准。进退两难的局面让他们陷入迷茫,不知道未来的职业发展该何去何从。

2.3.2 突破的渴望与现实的差距

尽管如此,很多小厂程序员依然保持着突破现状的愿望。他们希望自己的公司能够做大做强,从而拥有更多的资源和技术成长的机会。然而,现实往往并不如人意。小公司能做到一定规模的并不多,很多公司最终还是会因为市场竞争激烈、资金不足等原因被淘汰。

因此,跳槽到中型公司或大厂历练,成为了不少小厂程序员的另一种理想选择。他们希望通过进入更大平台,接触到更多的技术挑战和行业资源,打破在小公司中「打转」的局面。但这种跳槽并不容易,尤其是对于长期习惯了小公司开发模式的程序员来说,想要进入大厂不仅需要提升技术硬实力,还需要适应大厂的工作节奏和文化。

2.4 跳槽到大厂:进阶还是冒险?

对于那些在小公司工作了多年,并且已经进入到领导层的程序员来说,最大的问题往往是:现在跳槽到大厂,值得吗?

2.4.1 跳槽的机遇

跳槽到大厂意味着能够接触到更复杂的技术栈和更具挑战性的项目。在大厂中,程序员不仅可以学习到前沿的技术(如微服务架构、Kubernetes、分布式系统等),还能够获得更为完善的职业晋升通道。大厂的技术氛围和资源整合能力,也意味着程序员能够更快地成长,跳出小公司单一业务的限制。

此外,大厂的品牌效应也不容忽视。即使是普通开发,拥有大厂背景的程序员在未来的求职市场上,无论是跳槽还是创业,都具有更高的含金量。

2.4.2 跳槽的风险

然而,跳槽到大厂并非没有风险。大厂的竞争激烈,程序员需要面对年轻一代的强大竞争压力。大厂的工作节奏快、加班文化重,许多 30 岁左右的程序员可能会发现,自己在体力和精力上难以与年轻人抗衡。

进入大厂后,之前在小公司积累的业务经验和管理经验未必能够直接转化为优势。大厂的岗位分工更加明确,很多程序员在跳槽后可能需要从普通开发做起,甚至重新适应新的工作流程和技术要求。

跳槽到大厂对于 30 岁上下的程序员来说,是一个双刃剑。如果能够抓住机会快速提升技术能力,则职业生涯将迎来新的突破;但如果无法适应大厂的节奏,则可能面临事业的再次迷茫。

2.5 技术能力和学习能力是立足之本

小厂程序员的迷茫和焦虑,归根结底源于技术成长的瓶颈和职业发展的不确定性。面对快速变化的行业环境,程序员们需要不断提升自我,不仅要在技术上有所突破,还应当具备长远的职业规划。

无论是在小公司继续发展,还是跳槽到大厂,程序员都应当意识到,技术能力和学习能力是立足于这个行业的根本。唯有不断学习和进步,才能在程序员的职业道路上走得更远、更稳。

3. 第三空间:外包与自由职业者的「生存游戏」

3.1 外包的世界

在大厂和小厂之外,还有一群程序员,他们生活在外包公司中。外包程序员的生活与大厂和小厂截然不同,他们的工作内容往往由客户决定,技术栈也不是自己可以随意选择的。一些外包程序员可能会长期为某个大厂或者知名企业提供服务,但他们并不属于这些公司,他们的身份始终是「外包」。

外包程序员的收入通常与大厂程序员有较大差距,工作内容也更加琐碎。与大厂和小厂的开发者相比,外包程序员的职业发展路径更为模糊。很多人觉得外包是一个「临时的选择」,但一旦进入外包行业,往往很难轻易跳出来

3.2 自由职业者的自由与孤独

与外包程序员类似,自由职业者也是程序员群体中的一个独特存在。他们没有固定的公司和老板,依靠接项目为生。自由职业者的生活看似自由,但实际上他们承担了巨大的生活压力:项目的来源、项目的质量、客户的付款周期,这些都直接决定了他们的收入。

我有一位朋友曾辞职做过一段时间的自由职业者,他的经历让我对这一群体有了更深的了解。他曾告诉我,自由职业的最大挑战不是技术,而是如何维持客户关系、如何接到稳定的项目。自由职业者的生活往往充满了不确定性,每天都是一次新的「生存游戏」。

4. 结语:折叠的程序员世界

程序员的世界如同《北京折叠》中的三个空间:大厂、小厂,外包与自由职业者,各自有着截然不同的生活方式与职业挑战。大厂程序员在高薪与内卷中挣扎,小厂程序员在资源匮乏和职业迷茫中徘徊,外包和自由职业者则在充满不确定性的项目中谋生。每个空间都有其独特的焦虑与困境,而这些困境往往是外界无法轻易察觉的。

然而,这些看似完全隔绝的空间并非毫无交集。在某些时刻,程序员们的职业轨迹会短暂交错:大厂的程序员可能因职业倦怠转而投身小厂,或选择成为自由职业者;小公司的程序员也可能抓住机会进入大厂,体验另一种生活。外包和自由职业者也常常通过项目合作,与大厂程序员产生联系。

折叠的背后,是程序员们面对的共同挑战:快速变化的技术浪潮、工作与生活的平衡、未来职业发展的不确定性。

无论身处哪个空间,程序员不仅要面对代码和产品,还要面对生活的选择与妥协。技术的迭代让人时刻保持危机感,职场的竞争让人不断追逐更高的目标,但归根结底,程序员们都在寻找如何掌控自己的命运,在压力与选择中找到一条适合自己的道路。

或许,正是这种多元的职业轨迹和复杂的生存环境,构成了程序员世界中的「折叠北京」。每个空间的故事,都在提醒我们:技术人的真正挑战,不仅在于掌握技术,更在于如何在折叠的世界中找到属于自己的平衡与方向

5 块钱,就可以给娃训练一个专属的 AI 模型

上周末花了 5 个小时,从零开始给娃训练了一个基于 flux1_dev 的 lora,用于生成娃的照片。

以下为详细(保姆级)的过程记录,有想法又没有自己训练过 lora 的程序员爸爸或妈妈们可以尝试一下。

可能的时间成本:2 ~ 5 小时,资金成本:5 ~ 10 块。

环境准备

因为我们会用到 GPU 机器,去类似于阿里云这种云平台租,太贵。

这里我们选择的是 audodl ,一个比阿里云便宜 60% 的可按小时租 GPU 服务器的算力平台。autodl 基于容器实现,在使用上有一些局限性,但是对于我们当下的需求来说,还是非常匹配的。

我们选择如图 1 所示的配置:

图1

4090D + 50 G 额外的空间

尽量选择空闲 GPU 多的主机或所在区,因为可能会存在主机 GPU 不够的情况。

下单付款,等待容器启动。

容器启动后,直接使用官方提供的 web 的终端,这个终端有一个好处是当你关掉浏览器以后,终端还在,有点类似于 nohup 的执行状态。

需要说明一下,autodl 的存储分为系统盘和数据盘,在 /root/autodl-tmp 下为数据盘空间。我们要下载的模型、项目等都放到数据盘下。

把 commfy UI flux 跑起来

1. 创建 comfyUI 的环境并跑起来

cd ~/autodl-tmp

git clone https://github.com/comfyanonymous/ComfyUI
cd ComfyUI
conda create -n comfyui python=3.12 -y

conda init
source ~/.bashrc

conda activate comfyui
pip install -r requirements.txt 

在 git clone 时可能会遇到克隆失败的情况,此时需要使用 autodl 的学术资源加速:https://www.autodl.com/docs/network_turbo/

另外,在 conda create 后无法直接 conda activate,需要先 conda init,然后 source ~/.bashrc 或重新启动一下终端

接下来是启动 ComfyUI

python main.py

启动是启动了,但是如何访问了,这台机器又不在我本地,难道要启一个外网端口监听,此时就需要启动自定义服务,当然我们也可以使用 ssh 的通道能力,让本地电脑能访问远程的服务,在本地命令行中执行如下的命令:

ssh -CNg -L 8188:127.0.0.1:8188 -p 49027 root@connect.westb.seetacloud.com

以上的 -p 后的参数对于不同的机器不同,请参考控制台上的登录指令,如图2:

图2

输入后会提示:root@connect.westb.seetacloud.com’s password:

当时将控制台的密码复制出来,粘贴即可,回车。此时,可能没有啥反应,嗯。这是正常的。不用管他,除非报错告诉你连接失败或者密码错误,再重新输入。

在浏览器中输入:http://localhost:8188/

就可以看到 ComfyUI 的界面了。

2. 下载并运行 flux

在 ComfyUI 的 flux1 的 Demo 界面中:https://comfyui-wiki.com/tutorial/advanced/flux1-comfyui-guide-workflow-and-examples

可以把 Flux Dev ComfyUI workflow example 那张美少女的照片下载下来,直接拖到 ComfyUI 的界面上,或者下载 json 文件加载进来。如下图所示:

图3

要把示例跑起来,我们有 4 个文件要下载,分别是:

  • 放到 models/unet 目录下的 flux1.dev fp8 模型:https://hf-mirror.com/camenduru/FLUX.1-dev/resolve/main/flux1-dev-fp8.safetensors
  • 放到 models/vae 目录下的 VAE 模型:https://hf-mirror.com/camenduru/FLUX.1-dev/resolve/main/ae.safetensors
  • 放到 models/clip 目录下的 clip 编码器:https://hf-mirror.com/camenduru/FLUX.1-dev/resolve/main/clip_l.safetensors
  • 放到 models/clip 目录下的 T5XXL 文本编码器:https://hf-mirror.com/camenduru/FLUX.1-dev/resolve/main/t5xxl_fp8_e4m3fn.safetensors

在 hf 下可能会存在下载失败的情况,这里我们选择 hf-mirror: https://hf-mirror.com/camenduru/FLUX.1-dev/tree/main

下载可能会持续个 20 分钟左右,视网络情况,早上下载可能会快一些。

接下来就比较简单了,在本地浏览器中打开,点击运行 Queue Prompt 按钮

第一次运行会慢一点,因为需要加载模型这些,后面再次执行就大概 10 秒多一点。

图4

把 lora 加到管线并跑起来

1. 下载 lora 模型在类似于 liblib.art 之类的网站下载一个你觉得不错的 lora 模型,将其放到 ComfyUI 的 models/loras 目录中。

在 ComfyUI 的界面中增加一个 lora 的节点,这里我选择的是纯粹的 lora 节点,如图 5 所示

图5

点击 Queue Prompt 按钮,等一会儿就能看到生成的图片了,如果图片不符合预期,可以调整一下 prompt 试试,如你选择的 LoRA 是一个美女明星的 LoRA,简单点的:a girl,portrait, professional portrait

2. 调整 LoRA 强度与权重在 LoRA 节点中,你也可以调整 LoRA 的权重,以影响生成图片时对 LoRA 的依赖程度。通常,权重值可以设置在 0.5 到 1.0 之间,这取决于你希望模型生成的图片与 LoRA 模型的契合度。权重越高,生成的图片越接近 LoRA 模型的风格;而权重越低,则越依赖于你输入的 prompt

调整 LoRA 节点的参数后,再次点击 Queue Prompt 按钮,等待生成的新图片。如果生成的图片依然不符合预期,可以继续调整 LoRA 权重,或者尝试修改 prompt 来更好地引导模型。

打标

在 LoRA 跑起来并生成合适的图片后,下一步就是准备训练数据集。数据集的质量对模型的效果至关重要,因此我们需要对数据集进行打标。打标的目的是为每张图片生成准确的描述标签,使模型能够理解图片的内容,以便在未来生成类似的图像时能够参考这些标签。

打标工具

选择合适的打标工具或方案可以帮助我们生成高质量的标签。以下是一些常用的打标工具或方案:

  1. Florence 2:Florence 2 是一个强大的自动打标工具,能够为图片生成高精度的标签。它的优点是标签的细节和准确性较高,适合用于需要精确描述的图片场景。
  2. JoyCaption:JoyCaption 是 WD14 的替代工具,提供了更细致的标签生成能力。它能够为每张图片生成更详细的描述,适合用于生成具备复杂场景或人物的标签。不过,它也有一定的出错概率,因此需要额外的人工检查。
  3. MiniCPM:MiniCPM 是一个轻量级的打标工具,适合小规模数据集的快速打标。它的优点是操作简便,生成速度快,缺点是生成的标签可能不够详细,适合用于简单场景的图片。
  4. WD14:WD14 是一个非常流行的打标工具,特别适合用于文生图任务。它的标签生成能力较强,能够根据图片生成与文本 prompt 相关性较高的标签。特别适用于需要高质量和一致性的图片生成任务。

打标策略

为了确保数据集的质量,打标时可以采用以下策略:

  1. 多工具结合使用:如果你的图片集包含不同类型的图片,可以使用多个打标工具来生成初步标签,然后对标签进行合并和校对。比如:使用 Florence 2 生成的标签作为基础,再用 WD14 生成补充标签。
  2. 人工校对:虽然自动打标工具能够节省大量时间,但是人工校对是必不可少的环节。检查和修正错误标签,确保每张图片的标签描述都准确无误。
  3. 标签标准化:在打标过程中,确保使用一致的标签格式和风格。比如:尽量使用标准化标签(如 “portrait”, “landscape”, “girl”, “cityscape” 等)来确保不同图片的标签一致性。
  4. 使用特定的标签:对于我们当前这个场景,对每个图片在 AI 打标的基础上增加额外的一个标签来代表娃,比如我在这里使用的是 bbdr,具体参考打标的脚本。

WD 打标

在这里我选择的是 https://huggingface.co/SmilingWolf/wd-swinv2-tagger-v3 来实现的打标,在其 web demo 的基础上做了一点小改造,具体代码见:https://github.com/phppan/wd-swinv2-tagger-v3-script/blob/main/wd_tag.py

git clone https://github.com/phppan/wd-swinv2-tagger-v3-script

cd wd-swinv2-tagger-v3-script/

conda create -n wds python=3.12 -y
conda activate wds
pip install -r requirements.txt 
mkdir data

export HF_ENDPOINT=https://hf-mirror.com

可能会存在克隆失败的情况,如:

fatal: unable to access 'https://github.com/phppan/wd-swinv2-tagger-v3-script/': GnuTLS recv error (-110): The TLS connection was non-properly terminated.

多试几次。

最后的 export HF_ENDPOINT=https://hf-mirror.com 要执行,我们从镜像网站下载模型,hf 有时候无法直接访问。

如果嫌麻烦,可以 vim ~/.bashrc,在此文件中添加后 source ~/.bashrc

上传数据集并生成打标内容

将前面准备好的 10 张照片上传到上面创建的 data 目录。执行

python wd_tag.py

在上面的打标脚本中,我将特定的标签 bbdr 加到标签中,后续在生成的时候都会带上这个标签。你也可以改成你自己的标签,赖博说这里:最好几个辅音叠加,不容易冲突

等待模型下载完成,并执行完打标工作,在 output 目录中可以看到生成和图片名称同名的 txt 文件,这就是我们打好了的标签。

开始训练模型

模型训练,这里我选择的是 ai-toolkit:https://github.com/ostris/ai-toolkit

git clone https://github.com/ostris/ai-toolkit
cd ai-toolkit/
git submodule update --init --recursive

conda create -n aitool python=3.12 -y
conda activate aitool

pip3 install torch
pip3 install -r requirements.txt

修改配置文件并执行训练

cp config/examples/train_lora_flux_24gb.yaml ./config/bbdr.yaml
vim ./config/bbdr.yaml

一些参数的修改可以参考视频:https://www.youtube.com/watch?v=HzGW_Kyermg 主要是修改:name(名字)、training_folder(训练生成的目录)、folder_path(训练集路径)

python run.py ./config/bbdr.yaml

接下来就是等待训练完成。

训练完成后,在上面参数中设置的生成目录中可以看到你想要的 lora 模型文件,如我们设置的名字是 bbdr,则生成的模型名为:bbdr.safetensors

将其复制到前面我们已经部署好了的 ComfyUI 项目的 models/loras 目录下,在界面中选择你要的 lora 模型,在 prompt 中把你自定义的标签加上,如我们这里是 bbdr,一个简单的示例:bbdr,a girl,cute,perfect body,standing,street

等一下,就能看到专属于娃的 AI 模型生成的图片了。

其它

  1. 如果在编写/调试代码、上传下载数据到实例、给他人做代码展示等不需要GPU卡场景时,可以关机后使用无卡模式开机,无卡模式开机的区别在于对于这次开机会使用0.5核;2GB内存;无GPU卡的配置,价格统一为¥0.1/小时
  2. 如果不想等训练完成,可以设置定时关机。
  3. 照片请准备同一时期的照片,不同时期的照片,特别是小朋友,可能相貌差别较大,会导致最终生成的效果不好

以上是程序员逻辑,主打一个学习和挑战。

不想整这么复杂的,可以选择在类似于 liblib 的 lora 训练平台上生成:https://www.liblib.art/pretrain 或者类似于 https://www.mimicpc.com/ 这样的平台。

强哥说:看了这么久的理论,这次终于破天荒来了篇工程的。

以上。

最后感谢赖博的指导

技术管理者必备技能之解决问题的 3 个层次

作为一名技术管理者,面对日常工作中的各种问题和挑战,我们需要具备出色的问题解决能力。技术团队管理本身就是一项充满挑战的任务,而解决问题的能力更是推动团队向前的关键。当一个技术管理者拥有极强的解决问题的能力后,他大概能应对挑战、降低风险、提高团队绩效、增强领导力并提升个人职业发展。

在解决问题的过程中,我们可以将问题分为三个层次。了解这三个层次将帮助我们更好地应对不同场景下的问题,成为更优秀的技术管理者。

1 应急响应类

应急响应类问题的处理是通过快速反应和短期改进措施来修复问题的反应性流程。其主要作用是停止损害,防止蔓延

应急响应通常是一种反应式行为,并不研究根本性的问题以及背后的原因。应急响应不会导致理想状态的实现,但是仍然可以满足即时需求、保护客户,为更加深入地挖掘和调查重要细节赢得宝贵时间。有效的应急响应有助于企业产品获得更好的稳定性。

应急响应类问题涉及到系统或产品出现紧急故障时,需要立即采取行动以避免进一步影响。这种解决方式专注于快速应对问题,暂时稳定状况,但可能不会深入探讨问题的根本原因。例如,服务器宕机导致网站无法访问,技术管理者需要立即组织团队快速评估问题的严重性,制定并实施紧急应对措施,进行故障排查,找出问题根源并进行修复,以保障系统正常运行。

针对此类问题,常规处理流程如下:

  1. 确认问题:在故障发生时,第一步是确认问题的具体表现和影响范围。
  2. 快速定位:尽快找到故障发生的关键环节或设备。
  3. 制定应急措施:为了防止问题扩大,制定临时应对措施,如切换备用设备或临时修复。
  4. 实施解决方案:采取相应的技术手段和方法解决故障。
  5. 验证修复:确认故障已被解决,系统恢复正常运行。
  6. 总结复盘:分析故障原因,制定预防措施,避免类似问题再次发生。

以某个互联网产品的后台服务出现异常,导致用户无法正常登录。为解决该问题,我们可以采取以下步骤:

  1. 确认问题:收集用户反馈,查看日志和监控数据,确定问题的具体表现和影响范围。
  2. 快速定位:分析日志和监控数据,找出异常发生的关键服务或代码模块。
  3. 制定应急措施:为防止问题扩大,可以临时限制新用户注册,或者启用备用服务器等。
  4. 实施解决方案:针对定位到的问题,进行相应的代码修复或配置调整,然后重新部署服务。
  5. 验证修复:测试修复后的服务,确认用户可以正常登录,系统恢复正常运行。
  6. 总结复盘:分析故障原因,制定预防措施,优化代码质量和监控预警机制,避免类似问题再次发生。

在职场中,经常会出遇到此类的问题,一个技术管理者也经常需要作为发言人去回复此类问题,可能是对业务方或者上级等等。一般我们回复此类问题可以按以下逻辑来讲:

  1. 问题描述:首先,简洁明了地描述问题的现象,包括故障发生的时间、影响范围以及涉及的系统或模块。
  2. 原因分析:接下来,阐述经过团队排查后发现的问题根源,以及问题产生的原因。
  3. 解决措施:说明已经采取的解决措施以及恢复情况,包括故障处理时间以及目前系统恢复的程度。
  4. 防范措施:提出针对此次故障,团队将采取哪些预防措施,以避免类似问题再次发生。
  5. 跟进计划:最后,描述团队将如何跟进并持续关注问题的后续处理,以确保问题得到妥善解决。

示例:

问题描述:今日上午 10:00,我们的网站出现了访问故障,影响了所有用户对网站内容的访问。
原因分析: 经过团队紧急排查,我们发现问题出在流量爆涨,导致服务器负载过高,从而让部分服务无法正常响应用户请求。
解决措施: 我们迅速扩展了服务器资源,同时优化了负载均衡策略。截止目前,网站访问已恢复正常,全部用户可以正常访问。
防范措施:为防止类似问题再次发生,我们将加强服务器负载监控,提前预警潜在风险。同时,我们将对现有负载均衡策略进行评估和优化,确保系统稳定性。
跟进计划:我们将在未来一周内密切关注网站运行状况,并定期向您汇报服务器性能数据。如有任何问题,请随时联系我们。

2 深度分析类

深度分析类问题和应急响应类问题相比有一个不同点,在于速度。应急响应类的方式以一种快速而急切的方式处理紧急问题,深度分析的方式则遵循更加严谨的结构,通常包括数据收集、多方分析和深度研究,可能需要以一种更科学的方式花费几小时、几天、几周,甚至更长时间来完成。

深度分析类不会每次出现问题就触发,仅在以下场景下发生:

  1. 重复发生的问题。
  2. 对安全、质量、交付、成本、士气、生产率或者其他关键绩效指标产生负面影响,且不知道根本原因与解决方案的任何问题。

深度分析类问题的解决是通过确定一个明确的目标,以及与之对应的衡量和管理流程来实现的。深度分析类的问题解决是重复的,直到人们清楚地了解问题,解决问题,并且防止问题再次出现为止。

针对此类问题,常规处理步骤如下:

  1. 界定问题:在这个阶段,技术管理者需要充分了解问题的背景,并使用事实和数据来描述现状与期望标准之间的差距。这包括明确问题的目的、范围、影响和紧迫性。问题描述应遵循 SMART 原则(具体、可衡量、可实现、相关、时限)。
  2. 分解问题:分解问题是第一步的延续,但是更加细化,为了更好地理解问题,技术管理者需要将问题分解成更小的部分。可以采用逻辑树、鱼骨图等工具来实现问题的分解。在分解过程中,应确保各部分之间的关系符合 MECE 原则(互斥且完全穷尽)。然后,针对每个子问题进行深入的分析、量化和细化。
  3. 建立目标和成功判断:在明确了问题的具体表现和原因后,技术管理者需要设定一个清晰的目标,以便于团队集中精力解决主要问题。目标应具有明确的完成标准和时间节点,并遵循 SMART 原则。此外,管理者还需要确保目标与公司战略目标保持一致。同时,为了衡量解决方案的成功程度,需要确定一些关键成功指标。
  4. 根因分析:根因分析是指根本原因分析,技术管理者需要深入挖掘问题的根本原因,以便于制定针对性的解决方案。可以采用 5W、因果图等工具来进行根本原因分析。找到根本原因后,管理者需要验证这些原因,确保它们是问题产生的关键因素。
  5. 制定解决方案:根据根因分析的结果,技术管理者需要制定相应的解决方案。解决方案是能够防止问题再次发生的应对措施,并不是指实施你感觉正确或者你希望奏效的行动。对于任何实施措施而言,能否防止问题再次发生和达成前几个步骤所确定的目标,是验证解决方案是否有效的主要检查点。解决方案应具有可行性和可持续性,以确保长期效果。同时,解决方案应具有创新性,以提高团队的问题解决能力。
  6. 里程碑:为了确保解决方案的实施过程井然有序,技术管理者需要设定一系列里程碑。每个里程碑都应与特定的任务或目标相关联,有助于监控项目进度和实现预期结果。里程碑除了监控项目进度,还有一个作用是对外或对上的汇报,以大的时间节点同步项目的进展
  7. 工作计划:在这个阶段,技术管理者需要为团队制定详细的工作计划,包括任务分配、时间表和预期结果。工作计划应确保各个团队成员清楚自己的职责和期望,以提高执行效率。同时,管理者需要与团队成员保持密切沟通,确保计划的实施过程中能够及时调整和改进。在工作计划中预期结果一定要体现必须的交付物,让预期结果是有能落地的点。
  8. 风险判断:在实施解决方案的过程中,技术管理者需要关注可能出现的风险和问题。这包括对潜在风险进行识别、评估和分类,以便于采取适当的预防和应对措施。管理者应与团队成员共同讨论可能的风险,制定风险应对策略,确保项目的顺利进行。
  9. 未来改进:问题解决并非一次性事件,而是一个持续的过程。在解决方案实施后,技术管理者需要关注其效果,并根据实际情况进行调整和改进。同时,管理者还应从这个过程中总结经验教训,为未来解决类似问题提供借鉴。

通过以上九个步骤,技术管理者可以结构化地解决复杂问题,提高团队的问题解决能力。这种方法论强调了问题的分析和解决过程的重要性,有助于确保解决方案的有效性和可持续性。

这九个步骤可以作为深度分析类问题的规划方案文档的一级标题。

3 追求卓越类

追求卓越类问题和深度分析类问题相比,通常都以检查关键指标开始,但是有一些差别。 深度分析类是要对趋势显示出来的与已设定目标的差距进行反应,而追求卓越类的这种机制则是通过建立新的、更具挑战性的未来状态而主动发起。

深度分析类问题解决方式聚焦在澄清问题及其直接原因上,要尽可能明确和具体。其思维和流程在本质上是调查性的,通过发现与标准之间的偏差,并将关键项目恢复到正常工作状况,围绕着恢复到已知标准或者之前的绩效水平而展开。深度分析类的思维接受现有标准

相比之下,追求卓越类思维会从根本上对现状提出质疑:「理想状态是怎样的,有没有更好的状态,或者应该是怎样的?」。刚开始的时候你可能没有明确的答案,你必须构想一种改进后的目标状态或未来状态。在聚焦到具体明确的个体问题之前,追求卓越类的问题解决者要拓宽思维宽度,去思考多个备选状态和路径以实现构想。

针对此类问题,常规处理步骤如下:

  1. 背景:列出受众和参与者可能需要知道的信息。提供项目的背景信息,例如组织环境、历史、市场情况等。确保所有相关人员对项目有充分了解,为后续步骤打下坚实基础。
  2. 现状定义:以图表等可视化的方法描述现状,让受众能更好地接收信息。例如,绘制价值流图,展示当前流程的关键环节、瓶颈和效率。通过直观地呈现现状,帮助团队成员更好地理解问题所在。
  3. 现状分析:全面地检验不同要素的改善潜力,比如前置时间、服务、绩效、成本和特性等。运用数据分析、用户反馈和内部评估等手段,找出现有流程中可以改进的地方。
  4. 设定目标:明确要在什么时候完成什么,并确定改善的具体水平。设定有挑战性且可实现的目标,为后续改进提供方向。
  5. 目标状态的定义:可视化地展示改进后的新状态,通过想象图、流程图或数据等方式,形象地呈现预期的目标状态。这有助于团队成员清晰地了解改进的方向和目的。
  6. 制定执行计划:列出具体的细节,比如姓名、责任、日期和预期产出结果等。明确具体的细节,确保团队成员清楚自己的职责和期望。如果需要,可以将执行计划与其他项目计划相结合进行管理。
  7. 检查结果:检查改进后的绩效水平是否达到预期。通过定期评估和数据分析,了解实施情况及效果,确保改进措施取得实际成果。
  8. 跟进与标准化:制定行动清单,确保改进结果在长期运行中是可维持的。对改进措施进行持续跟踪,评估其有效性,确保新的标准在组织内得到广泛应用和推广。

以一个互联网 SaaS 产品在高峰时段用户体验下降,页面加载速度变慢为例来描述整个过程:

  1. 背景:我们的 SaaS 产品面向企业客户,提供在线办公协作功能。近期我们发现,用户在高峰时段访问产品时,页面加载速度减慢,影响了用户体验。
  2. 现状定义:通过监控系统收集数据,绘制访问速度和用户活跃度随时间变化的图表。在图表中标注高峰时段,突出问题所在。
  3. 现状分析:分析服务器资源、带宽、前端优化等多个方面的因素,找出可能导致页面加载速度变慢的原因。例如,检查服务器响应时间、CDN 服务情况、代码优化等。
  4. 设定目标:在高峰时段将页面加载速度提高到行业标准水平。为实现这一目标,我们将设定一个合理的实施时间,例如 3 个月。
  5. 目标状态的定义:绘制改进后的访问速度和用户活跃度随时间变化的图表,展示目标状态。同时,列出在服务器资源、带宽和前端优化等方面需要达到的具体指标。
  6. 制定执行计划:为实现目标状态,我们需要分配任务给团队成员。例如:张三负责服务器资源优化,如升级硬件、调整负载均衡策略等。李四负责带宽和 CDN 服务调整,以确保高峰时段能应对流量需求。王五负责前端优化,如代码压缩、图片资源优化等。
  7. 检查结果:在实施改进措施后,持续监控页面加载速度和用户活跃度。通过数据分析,检查改进后的绩效水平是否达到预期。
  8. 跟进与标准化:为确保改进效果的持久性,我们需要:对实施过程进行总结,提炼经验教训。将改进措施纳入团队的日常工作流程,确保新的标准得到长期执行。定期回顾和评估改进效果,以便在未来进一步优化。

4 小结

本文主要探讨了技术管理者在应对日常工作中不同类型问题时,如何运用有效的问题解决能力来提升团队绩效。文章将问题分为三个层次:应急响应类、深度分析类和追求卓越类。对于应急响应类问题,例如服务器宕机等紧急故障,技术管理者需迅速评估并实施紧急应对措施。深度分析类问题则需要更加严谨和系统的方法,如面对重复发生或对关键绩效指标产生负面影响的问题,技术管理者要深入挖掘根本原因并防止问题再次出现。而在追求卓越类问题解决过程中,技术管理者需要勇于挑战现状,设定更具挑战性的未来目标,从而实现技术团队的持续进步。

通过了解这三个层次的问题解决方式,技术管理者能更加从容应对各种问题和挑战,为团队创造一个更高效、卓越的技术环境,推动团队不断向前发展。