Video thumbnail

    生产环境中的氛围编码

    Valuable insights

    1.即兴编码的真正含义: 即兴编码超越AI代码生成,核心在于“忘记代码存在”,完全沉浸于AI构建产品的体验中。它使非工程师也能参与代码创建。

    2.AI的指数级发展: AI能力呈指数级增长,任务长度每七个月翻倍,编程范式需适应AI生成大规模代码的趋势,否则将无法跟上进度。

    3.负责任的即兴编码: 负责任的即兴编码强调信任AI实现细节,同时通过可验证的输入输出和测试来确保产品质量和符合预期,类似经理管理专家。

    4.工程师的角色转变: 软件工程师需从关注底层细节转向更高层次的产品经理角色,指导AI完成任务,而非编写或审查每行代码,以提高生产力。

    5.聚焦代码库叶节点: 建议将即兴编码应用于代码库中的“叶节点”功能,这些功能依赖性低,即使存在技术债务也更易于控制和管理,不影响核心架构。

    6.成为AI的产品经理: 成功即兴编码的关键是像产品经理一样思考,为AI提供详尽的需求、规范和背景信息,而非仅仅发出简单指令,从而显著提高成功率。

    7.可验证性至关重要: 设计系统时需考虑可验证性,确保在不阅读所有底层代码的情况下,也能通过压力测试、输入输出检查来验证系统的正确性与稳定性。

    8.显著的效率提升: 即兴编码能显著缩短开发周期,使原本耗时数周的任务在短时间内完成,从而赋能团队实现更大规模的功能开发,降低软件边际成本。

    9.并非人人适用: 即兴编码不适合完全非技术人员用于关键生产系统,因为缺乏提出正确问题和有效管理AI的能力可能导致安全和稳定性风险。

    10.新的学习范式: 未来的学习将更侧重于高层次的设计和架构,AI工具将作为强大的学习伙伴,帮助开发者更快地掌握新知识,从更多案例中学习。

    11.面向未来的产品设计: 未来的产品和框架应设计为“可证明正确”的系统,例如将核心安全和支付模块内置,让用户专注于UI层面的即兴编码,以保障安全。

    12.测试驱动开发的重要性: 在即兴编码中,测试驱动开发(TDD)仍至关重要。鼓励AI编写简洁的端到端测试,作为验证代码质量和正确性的有效手段。

    13.拥抱指数级增长: 拥抱指数级增长意味着接受AI能力将以远超想象的速度提升,开发者需为未来模型能处理百万倍复杂任务做好准备,避免成为瓶颈。

    引言:什么是即兴编码?

    各位好,欢迎来到本次分享。今天我将探讨一个大家普遍关注的话题——即兴编码(Vibe Coding),以及如何在生产环境中负责任地应用它。我是Eric,一名来自Anthropic的研究员,专注于编码智能体。我与Barry Zang合著了《构建高效智能体》一书,书中详细阐述了创建各种应用智能体的最佳科学实践。这个话题对我个人意义深远。去年,我在骑行上班途中不慎摔断了手,打了两个月的石膏,而在这期间,我所有的代码都由Claude代劳。因此,如何高效地实现这一目标对我至关重要,我很幸运地找到了方法,并通过我的研究将此经验推广到Anthropic的许多其他产品和模型中。

    即兴编码的真正含义

    许多人将即兴编码简单地等同于广泛使用AI生成代码,但这并不完全准确。尽管许多开发者在使用如CursorCopilot等工具时,大部分代码确实来自AI,但如果开发者仍与模型保持紧密的反馈循环,那并非真正的即兴编码。安德烈·卡帕西(Andrej Karpathy)对此有更准确的定义:即兴编码是完全顺从直觉,拥抱指数级增长,并忘却代码本身的存在。其中的核心在于“忘记代码甚至存在”。这一概念之所以重要,是因为它让工程界之外的人们开始对代码生成感到兴奋。尽管Copilot和Cursor对工程师大有裨益,但即兴编码让不懂编程的人也能独立编写整个应用程序,这无疑是一个巨大的突破。

    “即兴编码是你完全顺从直觉,拥抱指数级增长,并忘却代码甚至存在。”

    即兴编码的弊端

    当然,即兴编码也伴随着诸多弊端。初次接触编码的人,在完全不了解其运作原理的情况下,可能会遇到各种问题,例如API密钥使用量超限、订阅被绕过、数据库中产生随机数据等。这些都是即兴编码初期可能出现的负面影响。而即兴编码的积极方面,通常体现在一些风险较低的项目中,例如:

      为何关注即兴编码:AI的指数级发展

      那么,既然即兴编码在真实产品中风险极高,而其最成功的案例也仅限于那些风险极低的玩具项目,我们为何还要关注它呢?答案在于AI能力的指数级增长。AI能完成的任务长度,每七个月就会翻倍。目前,AI能独立完成的工作量大约是一小时。这当然很好,你不需要即兴编码,你可以让Cursor为你工作,让Claude编写一个需要一小时完成的功能。你可以检查所有代码,并持续深度参与AI生成代码的过程。但明年呢?后年呢?当AI足够强大,能够一次性为你生成一整天甚至一整周的工作量时,如果我们仍然需要循规蹈矩,我们将无法跟上这种速度。这意味着,为了利用这种指数级增长的优势,我们必须找到一种负责任的方式来顺应这一趋势,并充分利用AI完成任务的能力。

      编译器的类比

      我最喜欢的一个类比是编译器。我相信在编译器早期,许多开发者并不完全信任它们。他们可能会使用编译器,但仍然会阅读其输出的汇编代码,以确保它符合他们自己编写汇编代码的方式。但这无法扩展。在某个时候,你开始需要处理足够大的系统,以至于你不得不信任整个系统。问题在于,如何负责任地做到这一点?我认为未来几年对整个软件行业的挑战是:我们如何安全地在生产环境中进行即兴编码?

      如何安全地在生产环境中即兴编码

      我的答案是:我们可以忘记代码的存在,但不能忘记产品的存在。再次回到编译器的类比,我们都知道底层有汇编代码,但大多数人不需要真正去思考汇编代码的细节。然而,我们仍然能够构建出色的软件,而无需理解底层的汇编。我认为我们将在软件开发中达到相同的水平。我想强调的是,这不是一个新问题。

      软件工程师的挑战

      CTO如何管理其不具备专业知识领域的专家?产品经理如何评审一个工程功能,而他们自己无法阅读所有相关代码?CEO又如何检查会计的工作,而他们本身并非财务会计专家?这些都是存在了数百甚至数千年的问题,并且我们已经有了解决方案。CTO可以为专家编写验收测试,即使他们不理解底层实现,也可以通过验收测试的通过来确保工作的高质量。产品经理可以通过使用工程团队构建的产品来确保其按预期工作,即使他们不编写代码。CEO可以抽查他们理解的关键事实和数据片段,从而对整体财务模型建立信心,即使他们本身并非整个流程的专家。

      以下表格展示了不同角色如何在不完全理解底层实现的情况下管理和验证工作:

      因此,从这些例子可以看出,管理自己不理解的实现,实际上是一个与文明一样古老的问题。世界上每一位经理都在处理这个问题,只是我们作为软件工程师对此并不习惯。我们习惯于作为纯粹的个人贡献者,深入了解整个技术栈。但是,为了实现更高的生产力,我们将需要放弃这种习惯,就像每一位经理为了提高生产力需要放弃一些细节一样。正如我们软件工程师放弃了理解底层汇编的细节一样,如何在保持安全和负责任的同时做到这一点,关键在于找到一个抽象层,即使不了解底层实现,也能够对其进行验证。

      抽象层与技术债务

      然而,今天我有一个例外要提出,那就是技术债务。目前,在不阅读代码本身的情况下,还没有很好的方法来衡量或验证技术债务。在生活中大多数其他系统,比如会计或产品经理的例子,你都有办法验证你关心的事项,而无需了解其实现细节。技术债务我认为是少数几种,除了成为实现本身的专家之外,没有好的方法来验证的事情。

      “目前,没有好的方法可以在不阅读代码本身的情况下衡量或验证技术债务。”

      即兴编码的实践与策略

      尽管如此,这并不意味着我们完全无法进行即兴编码。它只是要求我们非常明智和有针对性地利用即兴编码的优势。我的答案是专注于代码库中的“叶节点”。我所说的叶节点,是指代码和系统中不被其他部分依赖的部分,它们是最终的功能,是最终的“锦上添花”。与那些核心分支或主干(如这里白色所示的部分)不同,图中橙色的点就是这些叶节点。老实说,如果你的系统中有这样的叶节点,即使它们存在技术债务也无妨,因为它们不被其他部分依赖,不太可能改变,也不太可能在其上构建新的功能。而这里白色的部分,即系统的核心架构和底层分支,是我们工程师仍然需要深入理解的,因为它们会发生变化,其他功能将构建在它们之上,因此保护它们并确保其可扩展性、可理解性和灵活性至关重要。

      值得一提的是,模型一直在不断进步,我们可能会进入一个越来越信任模型编写可扩展且没有技术债务代码的世界。在Anthropic过去一两周内使用Claude 4模型,是一个非常令人兴奋的经历,我给予了它们比Claude 3.7更多的信任。因此,我相信这种情况将不断演变,我们将能够以这种方式处理更多的技术栈。

      如何成功进行即兴编码

      现在,让我们谈谈如何成功进行即兴编码。我的主要建议是:不要问Claude能为你做什么,而是问你能为Claude做什么。我认为在即兴编码时,你实际上是扮演着Claude的产品经理。因此,你需要像产品经理一样思考:团队中的新员工需要什么指导或上下文才能成功完成这项任务?我们常常习惯于与AI进行非常快速的来回对话,比如“实现这个功能”、“修复这个bug”。但是,如果是一个第一天上班的人类员工,你绝不会期望他们仅仅通过一句“嘿,实现这个功能”就能成功完成任务。你需要向他们介绍代码库,告诉他们需要理解的实际要求、规范和限制。我认为,当我们进行即兴编码时,将这些信息提供给Claude,确保它拥有相同的上下文并能成功完成任务,就成为了我们的责任。

      当我与Claude一起开发功能时,我经常会花费15到20分钟将所有指导信息收集到一个单一的提示中,然后让Claude开始“烹饪”。这15到20分钟不仅仅是手动编写提示,这通常是一个与Claude来回对话的过程。它会探索代码库,查找文件。我们一起构建一个计划,捕捉我想要的核心内容,哪些文件需要修改,以及应该遵循代码库中的哪些模式。一旦我有了这个包含了所有信息的“神器”,我就会将其提供给Claude,要么在一个新的上下文中,要么说“嘿,让我们执行这个计划”。我通常发现,一旦我投入了收集这些信息的工作,Claude在以非常好的方式完成任务方面的成功率非常非常高。

      另外一点是,你需要能够提出正确的问题。尽管我的演讲标题如此,但我认为在生产环境中进行即兴编码并非适用于所有人。我并不认为完全非技术背景的人应该尝试从零开始建立一家企业。我认为这很危险,因为他们无法提出正确的问题。在即兴编码时,他们无法成为Claude的有效产品经理,因此他们不会成功。

      实际案例与效益

      我们最近将一个22,000行的更改合并到我们的生产强化学习代码库中,其中大部分代码由Claude编写。那么,我们是如何负责任地做到这一点的呢?是的,这是GitHub上PR的实际差异截图。首先,我们考虑了我们能为Claude做什么。这不仅仅是一个简单的提示,然后我们就合并了。这背后是数天的人工工作,包括制定需求、指导Claude以及确定系统应该是什么样子。我们真正地将自己定位为Claude在这个功能中的产品经理。

      负责任的实现

      这次更改主要集中在代码库的叶节点上,我们知道即使这些部分存在一些技术债务也无妨,因为我们不期望这些代码在近期内需要更改。而那些我们认为很重要、需要可扩展的部分,我们进行了大量的人工审查。最后,我们精心设计了稳定性压力测试,并设计了整个系统,使其具有非常容易通过人工验证的输入和输出。最后这两点使我们能够创建这些可验证的检查点,从而确保代码的正确性,即使我们不理解或不阅读完整的底层实现。我们最大的担忧是稳定性,我们甚至在不阅读代码的情况下,通过创建这些压力测试并长时间运行它们来衡量稳定性。我们能够根据我们设计的系统的输入和输出来验证其正确性。基本上,我们将这个系统设计成即使我们不阅读所有代码,也能被理解和验证。

      • 变革主要集中在代码库的叶节点上。
      • 对核心和可扩展部分进行大量人工审查。
      • 精心设计了稳定性压力测试。
      • 系统设计具备易于人工验证的输入和输出。

      因此,通过结合这些方法,我们对这次变更的信心达到了与我们对代码库中任何其他变更相同的水平,但交付的时间和精力却仅是手动编写和审查每一行代码所需的一小部分。我认为,这次经历真正令人兴奋之处,不仅在于它为我们节省了一周的人力时间,更在于我们知道可以做到这一点,从而让我们对工程实践和能力有了不同的思考。现在,当某个任务的成本从两周变为一天时,你就会意识到你可以去实现更宏大的功能和更大的改变。这使得软件的边际成本更低,从而允许你消费和构建更多的软件。因此,我认为最令人兴奋的不是节省了时间,而是现在感觉“哦,那些需要两周才能完成的事情,就去做吧!它只需要一天。”这就是即兴编码带来的激动人心之处。

      负责任的即兴编码:核心原则

      最后,关于如何在生产环境中负责任地进行即兴编码,我想给大家留下一些思考。首先,要成为Claude的产品经理,不要问Claude能为你做什么,而是问你能为Claude做什么。其次,将你的即兴编码集中在叶节点上,而非核心架构和底层系统,这样即使存在技术债务,也能将其限制在非关键区域。第三,思考可验证性,以及如何在不阅读代码本身的情况下,知道这次更改是否正确。最后,记住指数级增长。今天不即兴编码或许没关系,但在一两年内,如果你仍然坚持要求阅读或编写每一行代码,你将处于巨大的劣势。你将无法利用最新一代模型为你生成大量工作的优势,并且如果你不善于此,你将成为瓶颈。总而言之,这就是负责任的生产环境即兴编码,我相信这将在未来几年成为软件工程行业面临的最大挑战之一。

      • 成为Claude的产品经理:为其提供充分的指导和上下文。
      • 聚焦代码库的叶节点:将即兴编码应用于非核心、依赖性低的模块,以控制技术债务。
      • 设计系统的可验证性:确保即使不阅读代码,也能验证其正确性和稳定性。
      • 铭记AI的指数级发展:认识到未来AI能力将迅速提升,并适应新的开发范式。

      过去,我们花费大量时间处理语法问题、库的使用或代码组件之间的连接,这就是我们通过编码学习的方式。但现在我们如何学习呢?我们如何成为更好的即兴编码者?我们如何更深入地了解以成为AI智能体的优秀产品经理?

      问答:学习、安全与未来

      如何通过即兴编码学习和提升?

      这是一个非常有趣的问题,我认为既有令人担忧的理由,也有令人非常乐观的理由。令人担忧的原因正如你所说,我们不会再经历那样的挣扎和磨练。但我认为这实际上是可以接受的。我的一些大学教授会说:“哎呀,现在的程序员不如以前了,因为他们不必手动编写汇编代码,他们体会不到如何让程序跑得飞快的痛苦。”而乐观的一面是,我发现通过使用这些AI工具,我能够更快地学习新事物。很多时候,当我和Claude一起编码时,我会审查代码,然后说:“嘿,Claude,我以前没见过这个库,给我讲讲它,它是什么?你为什么选择它而不是别的?”拥有这样一个随时随地的结对程序员,我认为未来的变化是,那些懒惰的人将不会学习,他们只会随波逐流。但如果你愿意花时间去学习,有许多令人惊叹的资源,而且Claude会帮助你理解它为你即兴编写的代码。

      另外,我想说的是,对于学习一些更高层次的项目成功要素,比如哪些功能能实现产品市场契合度,哪些会失败,我们将能够进行更多的尝试。我感觉,尤其是系统工程师或架构师,通常需要两年时间才能在代码库中做出重大改变,并真正理解这是否是一个好的架构决策。如果我们将这个时间缩短到六个月,那么那些投入时间和精力学习的工程师,在相同的时间内,将能够从四倍多的经验中学习。

      如何平衡信息量与效果?

      回到你的预规划流程,关于提供过多信息和过少信息之间的平衡是怎样的?你会提供一份完整的产品需求文档吗?在实际进入即兴编码之前,是否有某种标准的模板?我认为这很大程度上取决于你关心什么。我会说,对于我不太关心具体实现方式的事情,我完全不会提及实现细节。我只会说这些是我的要求,这就是我最终想要的结果。而有时,当我非常了解代码库时,我会深入探讨更多细节,比如“嘿,你应该使用这些类来实现这个逻辑,看看这个类似功能的例子”。最终,这一切都归结于你最终关心的是什么。不过,我会说我们的模型在不过度限制它们的情况下表现最佳。所以,你不需要投入太多精力去创建一个非常严谨的格式或任何东西。你只需像对待一个初级工程师那样,考虑你需要给他们什么才能让他们成功。

      即兴编码与网络安全

      你是如何在有效性和网络安全之间取得平衡的?几个月前有报道称,排名前十的即兴编码应用存在严重漏洞,许多重要信息被泄露(并非主动发布,而是被证实可以被获取),而实施者甚至不是专业的黑客。那么,你如何平衡在叶节点级别保持安全与有效性,因为有些东西可能有效但不安全?这是一个很好的问题,我认为这都归结于第一点:作为Claude的产品经理,你需要对上下文有足够的理解,才能基本了解什么是危险的,什么是安全的,以及在哪里需要小心。是的,很多关于即兴编码的报道都集中在那些根本不应该编码的人身上。这对于游戏或创意项目来说很好,能够让人们进行创造。但对于生产系统,你需要足够了解需要提出哪些问题来引导Claude走向正确的方向。就我们内部的这个例子而言,它是一个完全离线的系统。所以我们非常有信心不会出现任何安全问题。我们的情况是,它运行在一个完全离线的环境中。所以这更多的是指你提到的那些“不应该”在重要生产系统中进行即兴编码的人。

      未来产品如何促进安全即兴编码?

      现在,如果我们看数据,全球只有不到0.5%的人口是软件开发者,而软件是扩展想法的绝佳方式。那么,你认为产品需要如何改变才能让人们更容易地进行即兴编码和构建软件,同时避免诸如API密钥泄露等问题?这是一个很好的问题,我非常期待看到更多“可证明正确”的产品和框架出现。我的意思可能是,我相信人们可以构建一些后端系统,其中重要的身份验证部分、支付部分都已为你构建好,你只需填充UI层即可。然后你可以即兴编码UI层,它基本上为你提供了一些很好的填空式沙盒来放置你的代码。我觉得有很多这样的东西可以存在。

      最简单的例子可能是Claude Artifacts,其中Claude可以帮助你编写直接托管在Claude AI中用于显示的代码。这当然是安全的,因为它功能非常有限,没有认证,没有支付,它只是前端。但这可能是一个很好的产品创意,有人应该在这里做一些事情,那就是构建一个可证明正确的托管系统,它可以有一个安全的后端,无论前端发生什么“恶作剧”,后端都能保持安全。是的,我希望人们能构建出与即兴编码相辅相成的优秀工具。

      即兴编码中的测试驱动开发

      关于测试驱动开发(TDD),你有什么建议吗?因为我经常看到Claude直接吐出整个实现,然后才编写测试用例。有时它们会失败,我希望它先编写测试用例,但我又不想自己去验证它们,因为我还没看到实现。那么你有没有尝试过针对测试驱动开发的迭代方法呢?是的,我肯定会说测试驱动开发在即兴编码中非常非常有用,只要你能够理解测试用例,即使你自己不查看测试,它也能帮助Claude保持一致性。但很多时候,我会说Claude很容易陷入编写过于实现特定测试的死胡同。当我尝试这样做时,很多时候我都会鼓励Claude,我会给它例子,比如“嘿,只需编写三个端到端测试,包括正常路径、一个错误情况和另一个错误情况”。我对此非常具体。我希望测试是通用且端到端的。我认为这有助于确保我能够理解它,并且Claude能够在不深入细节的情况下完成。

      • 鼓励Claude编写少量、简洁的端到端测试。
      • 明确指定测试类型,例如一个“快乐路径”测试和一到两个错误情况测试。
      • 优先审查测试代码,确保其符合预期。
      • 通过确保测试覆盖关键场景,即使不完全理解所有实现细节,也能对代码质量保持信心。

      拥抱指数级增长的深层含义

      非常感谢您带来如此引人入胜的演讲。我也很欣赏您做了许多人未曾做过的事情,尝试解释卡帕西(Karpathy)原始帖子中那些看似奇特的句子之一——“拥抱指数级增长”。我想更深入地问您,我如何才能知道自己是否已经“拥抱了指数级增长”?具体来说,遵循这条建议意味着什么?也许更进一步地,您认为这是否暗示着模型会变得更好,但这不意味着它们会在我们想象或希望的每一个维度上都变得更好?是的,我认为你已经接近了,它不仅仅是假设模型会持续变好,而是它们会以我们无法想象的速度变得更快。这就像你在这里看到的点的形状一样,它不仅仅是稳步提升,而是会变得疯狂。我听到的另一个有趣的说法是,达里奥和迈克·克鲁格在他们的演讲中提到:“爱之机器(Machines of Loving Grace)不是科幻小说,而是一个产品路线图。”尽管听起来非常遥远,但当你处于指数级增长曲线上时,事情会非常非常快地变得疯狂,而且比你预期的更快。

      如果你和90年代从事计算机工作的人交谈,他们会说“好吧,我们有几KB的RAM,我们还有几KB的RAM”。但如果你快进到我们现在所处的位置,我们会说“我们有TB的RAM”。它不仅仅是好两倍,而是好几百万倍。这就是指数级增长在20年间发生的情况。所以,我们不应该思考20年后如果这些模型好两倍会怎样。我们应该思考如果这些模型比今天聪明和快一百万倍会怎样,这太疯狂了!我们甚至无法想象那意味着什么。就像90年代从事计算机工作的人,我认为他们无法想象如果一台计算机比他们当时使用的快一百万倍,社会会发生什么。但这却真实发生了。所以,这就是我们所说的指数级增长,它会变得非常疯狂。

      即兴编码的工作流程

      关于即兴编码,我有两种不同的工作流程。一种是在终端中,另一种是在VS Code或Cursor中。你使用哪种工作流程?如果你在终端中使用Claude Code,你多久压缩一次上下文?因为我发现,随着我即兴编码的时间越长,我的函数名会变新,或者事情会偏离轨道。如果我压缩上下文,这种情况仍然会发生。如果我创建一个文档来指导它,我仍然需要让它回到正轨。这是一个很好的问题。我两种都用。我经常在VS Code的终端中打开Claude Code进行编码。我会说Claude Code完成了大部分编辑工作,而我则在VS Code中审查代码。这并非严格意义上的即兴编码,或者我可能只是审查测试。我喜欢在Claude达到一个良好的停止点时,就像人类程序员会停下来休息、吃午饭然后回来一样,我会选择压缩上下文或开始一个新的会话。所以,我可能会先让Claude找到所有相关文件并制定一个计划,然后我会说“好的,把这些都写成一个文档”,然后我再压缩上下文。这样可以去除创建计划和查找文件所消耗的100k token,将其精简到几千个token。

      结合其他工具与探索新代码库

      有没有使用其他工具配合Claude Code来提高速度?比如同时运行多个Claude Code,使用git工作树,然后合并一些东西或堆叠PRs?这是你个人遵循或建议的做法吗?第二个问题是,当你对代码库的某个部分不熟悉,但又想快速提交一个PR,并且以一种非常优雅的工程方式而非即兴编码的方式完成时,你通常如何结构化地、以一种非常好的工程方式处理?是的,我确实同时使用Claude CodeCursor。我通常会用Claude Code来开始一些任务,然后用Cursor来修复问题。如果我有非常具体的更改,如果我确切知道要对这个文件进行哪些更改,我就会自己用Cursor直接操作,精准地修改我需要更改的行。

      至于你问题的第二部分——如何快速熟悉代码库的新部分。在我尝试编写功能之前,我会使用Claude Code来帮助我探索代码库。所以我可能会说“告诉我这个代码库中身份验证在哪里发生?”或者“这个代码库中某个特定功能在哪里实现?”“告诉我与此类似的有哪些功能?”并让它告诉我文件名,告诉我应该查看的类。然后,我利用这些信息来建立一个心理模型,确保我能够完成这项任务而不仅仅是即兴编码,确保我仍然对正在发生的事情有一个很好的理解。然后,我再和Claude一起开发功能。

      Useful links

      These links were generated based on the content of the video to help you deepen your knowledge about the topics discussed.

      Building Effective Agents
      Andrej Karpathy's blog post on Vibe Coding
      Cursor AI Code Editor
      GitHub Copilot
      Anthropic Claude AI
      GitHub
      This article was AI generated. It may contain errors and should be verified with the original source.
      VideoToWordsClarifyTube

      © 2025 ClarifyTube. All rights reserved.