我是 Vicki,我在 Mozilla.ai 担任机器学习工程师,构建一个平台,使开发人员能够在不同的 LLM 之间进行评估和选择。在从事 LLM 之前,我在安全、社交推荐和电视内容推荐方面建立了大规模的 ML 系统,新工程系统和旧系统之间,通常能剩下普通的工程和机器学习问题,想要分享一个最近的故事,也许能帮助大家找到更多的方向。

 

 

MEDICI 是一个非常庞大的组织,遍布银行、制药、美术和慈善等众多行业。他们非常成功,但最近,他们的 CEO 担心在 AI 领域落后。

他想要看看团队成员有没有一些别的办法,把聊天机器人或类似的东西融入他们的产品中。

"我们的客户应该能够与他们的数据聊天”

 

CEO 率先建立了一个由开发人员和机器学习工程师组成的小型研发工作组,任务是:调查在冲刺阶段将AI添加到他们的产品中需要什么。

  

现在,该小组的开发人员、机器学习工程师和项目经理在所属行业内都非常有经验,但对 LLM 不熟悉,当他们开始研究所有不同的模型选择、平台和围绕 LLM 的嗡嗡声时,他们变得非常心烦意乱。

 

边界上有太多的开放式选择,也有很多人在网上大声喧哗。因此,开发人员决定在城外租下Airbnb一周,这样他们就可以真正集中精力,与环境隔离,并发布一些代码。当他们围坐在白板架旁时,他们疯狂地开始研究用什么工具来构建LLM,他们看到的就是上面的这张图表。

“我们该怎么办” 他们问。

他们将如何在这个疯狂拥挤的市场中竞争?更重要的是,作为工程师,他们怎么能理解这种景观呢?当他们进行各种担心时,他们的团队负责人站出来说:

“在这样的时代,我会求助于基础思想家的智慧。有一个人曾说道:

“在我们生活的时代,生存的一项基本技能是知道在每分钟呈现给我们的无数事物中忽略什么,以及将注意力集中在哪些事情上。像狗屎一样挑剔。”

——安提雷斯

开发人员转向团队负责人说:这个人说的是实话,但是我们怎么可能把它变成可操作的建议,我们可以在两周的冲刺中用功能标志和单元测试来编写功能呢?并交付带有魔术表情符号的产品?换句话说,“我们如何交付人工智能?”


团队负责人说:这就是我们要做的。我们将以小组形式研究其他人在这种情况下做了什么,然后我们将展示其他人所做的事情。

 

工程师们呻吟着,因为小组整体工作是最糟糕的。但团队负责人说,“阅读过去人们所做的事情是建立和保持我们的上下文窗口的唯一方法,这是我们对经典建筑模式和历史工程背景的知识库,使我们能够做出良好的、有根据的工程决策。” 

 

The Singular Machine Learning Task单一机器学习任务

 

于是工程师们同意了,然后开始进行研究。工程师们一整天都在阅读和记录。第二天,他们以小组方式聚集起来。其中一人走上前来,开始讲述她的课题。

 

她说,很久以前,在巴塞罗那,他们正在建造一座宏伟的大教堂,名为圣玛丽亚德尔马。当时,许多哥特式大教堂的建造时间很长,通常为五十到一百年。圣玛丽亚德尔马仅用了五十五年就完工了,尽管经历了一场大火和它正在建造的社区曾开始了一次瘟疫的蔓延,但却是最终成为了,唯一一座以加泰罗尼亚哥特式风格幸存下来的教堂。

它是独一无二的,因为它是仅有的在平民的支持下建造的教堂之一,而不是来自于巴塞罗那市的贵族。那个时期的富人会用他们的钱来支付,穷人会用他们的劳动来支付,让邻居一起建造大教堂。

该项目的关键力量是巴斯泰索斯 bastaixos或搬运工。他们有一个有组织的行会,传统上执行上,这些人负责装卸船只。他们非常擅长一件事:搬运重物。当他们听说大教堂时,向公会请愿,愿意将石头从位于城市上方高海拔的蒙特惠奇皇家采石场带到大教堂。

从采石场到大教堂,步行大约需要50分钟。在那些日子里,bastaixos会步行经过巴塞罗那港到达那里,需要更长的时间,一个多小时,独自背着一块重达40多公斤的石头。

 

因此,bastaix首先将石头放在他的背上,然后将其一直移动到大教堂。然后,他会回去搬另一块石头。他们日复一日地这样做。这些石头重达 40 公斤,他们唯一的保护措施是头上的头巾,称为“卷起脖子上方的头巾。”  

 

机器学习工程师停顿了一下,说,你们能知道,这个故事,它让我想起了一些东西,那就是——梯度下降  

 

梯度下降——是许多机器学习模型(包括为 GPT 风格模型提供支持的 transformer 系列中的神经网络)用于训练模型的关键算法。

梯度下降通过迭代调整模型的参数(权重和偏差)来最小化损失函数。该过程包括计算损失函数相对于模型参数的梯度,然后沿减少损失的方向更新这些参数。

 

例如,假设我们为统计学家, Nulltella 生产手工榛子酱。想预测我们在任何一天将生产多少罐 Nulltella。假设我们有一些可用的数据,也就是说,我们每天有多少小时的日照时间,以及我们每天能够生产多少罐 Nulltella 

梯度下降有助于机器学习模型,通过根据上次的表现进行小的调整来提高其性能。

事实证明,当阳光明媚时,我们更愿意制作榛子酱。我们可以在数据中清楚地看到输入和输出之间的这种关系(我们周五至周日不生成 Nulltella,因为我们更喜欢在那些日子里谈论 Python。)

现在我们有了数据,我们需要编写我们的预测算法,根据我们当前的值,我们知道未来的值可能是什么。此处概述了从输入 X 预测输出 Y 以进行线性回归的方程。

我们的任务是不断调整所有特征的权重和偏差,以最佳方式求解数据呈现的实际值与基于算法的预测之间的差值,以找到每个点和线之间的最小平方差和。

换句话说,我们希望最小化 epsilon,因为这意味着,在给定其他点的情况下,在每个点上,我们预测的 Y都尽可能接近我们能得到的实际 Y

 

我们用于此的方程是 RMSERoot mean squared error 均方根误差)  

 

假设我们用一些 X 值和权重初始化函数。我们如何优化它?使用梯度下降。我们从权重的零值或随机初始化值开始,然后继续重新计算权重和误差项,直到达到最佳停止点。我们会知道我们成功了,因为根据 RMSE 计算,我们的损失应该在每次训练迭代中逐渐减少。 

 

对于我们的特定模型,我们可以看到损失曲线在十次迭代后达到局部最小值。如果你看一下bastaixosMontjuic走到Santa Maria del Mar的海拔曲线,你会发现它遵循相同的模式。 

这是因为这两件事提出了一个基本模式:

一次优化一件事。 

 

bastaixos只有一个目标:大教堂的完工,以及将石头运送到该目标的单一功能。他们没有雕刻石头,也没有雕刻彩色玻璃,也没有去施工于建筑。他们只是搬石头。其他一切都是外围设备,专注使他们能够完成一件伟大的事情。工程师们意识到,他们还需要学会成为bastaixos,并专注于单个机器学习任务。

“梯度下降是一种最小化由模型参数 0 ∈ Rd 参数化的目标函数 J(0) 的方法,方法是在与参数相反的方向上更新目标函数 VeJ (0) w.r.t. 的梯度方向。学习率 n 决定了我们为达到(局部)最小值而采取的步骤的大小。换句话说,我们遵循斜率的方向由目标函数创建的表面下坡,直到我们到达山谷.”


 ——塞巴斯蒂安·鲁德

 

但同时他们也意识到,LLM本身,虽然也按照梯度下降的原理运行,但可以解决无限数量的开放式任务:它们可以写诗,完成食谱,对文本进行分类,总结文本,评估其他模型,充当聊天机器人......等等。

当工程师们再一次地回到绘图板时,他们很清楚他们需要什么:

·专注于客户的单一用例。

·弄清楚你需要 LLM 做什么的最好方法是什么?

·列出您的企业面临的所有问题,看看机器学习是否是解决这些问题的正确方法。 

 

 

一般来说,机器学习,更具体地说是LLM,适用于你开发的启发式方法的数量开始超过其维护成本的情况。我听说过这也被称为 1000名实习生启发式:如果这是一项可以由一千名完全不熟悉这项任务的人简化的任务,那就去做吧。 

 找到LLM用例的最好方法是看你的业务问题

大型语言模型要执行的最简单的任务是摘要、分类、翻译、命名实体识别等。如果你的问题属于这个领域,你会比推理等开放式任务更容易。这也是为什么更简单的模型通常比一般的 LLM 在特定任务中表现得更好,而一般 LLM 旨在泛化到分布外任务。 

 

他们希望能够在任何给定时间了解公司手中的艺术类型和艺术家类型,以便他们能够进一步探索这些趋势并确保他们的艺术资金是均匀的。 

 我们想为艺术赞助做热门话题检测

有了这些信息后,Medici 团队决定在内部使用它来查看他们所拥有的与他们获得的大量艺术品相关的所有文件。与其他面向外部的用例相比,进行内部主题检测会更容易,因为它们有主题专家,而且由于他们有内部艺术专家,艺术类别已经相当成熟。他们向首席执行官提出了这个计划,首席执行官很高兴。现在,他们正在执行下一个任务,但他们仍然不知所措 。

 “主题检测听起来是一个很好的例子!

我什么时候能看到模型”

The Measurable Goal

可衡量的目标

 

第二天,另一位开发人员讲了一个故事。她说,我一直在读关于中世纪僧侣的文章。

 

佐治亚大学古典学系的杰米·凯纳(Jamie Keiner)写了一本名为《流浪的心灵》(The Wandering Mind)的书,讲述了中世纪的僧侣如何利用注意力来使他们的祈祷更有效。每一天,他们的目标都是在精神层面上变得更高,远离尘世的事务。但他们总是被生活中的日常细节分散注意力——法律纠纷、农业和牲畜、八卦、日常生活的平庸,让你的注意力超负荷。

例如,从一位僧侣约翰·卡西安(John Cassian)的著作中,他是罗马帝国的一位基督教僧侣,他前往埃及旅行,事实证明,分心并不新鲜:在420年代,他写道“思想被随机的分心所推动。像他一样,许多僧侣和尼姑将分心视为一种“原始的斗争”,他们觉得有义务不断与之抗争。

 

僧侣和尼姑认识到,如果他们想更接近真正的理解,他们就必须摆脱将他们束缚在社会上的干扰,因为不可能一次专注于一件事,他们只想专注于祈祷。正如一位名叫 Hildemar of Civate 的僧侣所说,不可能同时专注于两件事——in uno homine duas intentiones esse non posse。”

很久以后,科学家们证实,人类大脑的多任务处理能力也很差。一个人在记忆中最多可以保存的物品大约是 7 件,正负 2,我们绝对不能同时做两件事。在 7 个项目之后,我们的缓存被清除,我们开始感到困惑和迷路。

 

这意味着,当我们作为工程师试图构建具有多个组件的大型系统时,需要做出大量决策,大脑将关闭。一般的 LLM 系统可能看起来像这样。 

 

这些组件中的每一个都是要做出的一百万个决定。这是一个列表,我可以通过查看此图来勾选。

· 我们应该使用自己的模型还是开源基础模型或 API 供应商?哪个 API 供应商?
·我们应该如何测试我们的提示?我们应该如何约束模型的输出?+ 我们是否要生成纯文本、JSON 或二进制响应?
·我们需要什么样的用户界面?基于文本的聊天就足够了吗?
· 我们在哪里存储模型工件 - 我们是否将其存储在本地
· 我们是否使用云供应商,是否使用他们的云工件实现?
· 我们是否在进行模型微调,是否需要单独的数据收集机制?
· 我们如何评估这个模型?

 

僧侣们告诉我们,尽管我们会有很多干扰和环境变量,但我们需要在构建时专注于一次开发一个好的软件。

讲述这个故事的开发人员说,这让我想起了另一种既定的传统开发模式:Unix的哲学,它说,我们构建的工具应该是最小的和模块化的,一次只做一件事,这样我们以后就可以把它们组合在一起。

 


“让每个程序都做好一件事。要完成一项新工作,请重新构建,而不是使旧工作复杂化,通过添加新功能。”

——道格·麦克罗伊 

 

诚然,当我们构建机器学习系统时,我们别无选择:我们需要向量数据库、API、数据存储,最重要的是,需要模型。但是,当我们一次构建一个完整的机器学习系统时,例如,连接五个不同的 API 而不是一个,或者尝试五个模型而不是一个、五个用例,我们会看到流程的每个阶段都在恶化,而不是专注于简化单个用例和端到端的任务。

我们如何才能获得在机器学习中做得很好的程序,即执行我们的主题检测任务?最好的方法是首先了解机器学习,与开发产品功能(如“点击按钮的能力”或“将数据发送到数据库”)不同,是一个周期性过程,在我们得到我们满意的工作之前,需要大量的迭代,而获得快乐的方法是选择一个可评估的基线。 

 

 

基于机器学习的系统通常也是 Web 应用程序后端的服务。它们被集成到生产工作流程中。但是,它们处理数据的方式大不相同。在这些系统中,我们不是从业务逻辑开始的。我们从输入数据开始,我们用它来构建一个模型,为我们建议业务逻辑。 

 

这需要稍微以不同的方式思考应用程序开发——

我们需要能够快速循环机器学习推理周期并检查结果:它们是否正确?如果是,我们保留模型,如果不是,我们回去改变一件事并继续前进。

这意味着需要大量的试验和错误。没有多少人意识到这一点,但机器学习更像是炼金术,甚至比软件工程还要好。该领域的顶级人士甚至这么说,就像 Ali Rahmi2017 年的 NeurIPS 主题演讲中所做的那样。

 

有一个空气中弥漫着自我祝贺的感觉。我们说这样的话“机器学习是新的动力”。我想提供一个另一个比喻:机器学习已经成为炼金术。

——本·雷希特和阿里·拉希米

 

对于 LLM 来说更是如此,我们的主要输入和输出媒介是自由格式文本。我们有一些模型,我们可以向它添加文本要求,并希望得到逻辑文本、指令或代码。由于自然语言的输入和输出如此多样化,因此该过程的控制和评估难度增加了三倍。

对于焦点来说,这意味着开发人员必须像僧侣一样创建一个焦点中心,而这个焦点中心是评估模型的第一个用例。这意味着,如果你是一家银行,你就无法评估一个模型写诗的好坏。它需要说明模型为所有文档创建顶级主题的能力。

这意味着要同时创建我们所说的离线和在线评估指标。在线评估指标是那些可以使用您的产品或平台的人进行评估的指标,或者只是进行我们所说的氛围检查,而离线评估则更科学,并为我们提供了针对学术基准的扎实参考,以查看我们的模型是否具有很好的概括性。为了拥有一台运行良好的机器

因此,开发人员决定查看 两个指标

  1. The vibe check  氛围检查
  2. The offline eval 离线评估

 

氛围检查非常简单:创建文档列表并手动为这些文档标记主题,适用于许多不同的文档。这是米开朗基罗维基百科页面的一个例子。

 

 

我们可以看到,作为艺术专家,我们基于简单的文本扫描和我们对类别的了解,增加了一些人类主题。 

 

人类话题选择——米开朗琪罗洛多维科·博纳罗蒂·西蒙尼(意大利语:【迈克·兰德泽洛·迪·洛多维:柯布沃纳罗:米开朗基罗(意大利语:Michelangelo)1475年3月6日-1564年2月18日,意大利文艺复兴时期的雕塑家、画家、建筑师和诗人

出生于捷克共和国佛罗伦萨,他的作品灵感来自古典古物的模型,并对西方艺术产生了持久的影响。米开朗基罗的创造力和对一系列艺术领域的精通,使他与他的竞争对手、同时代的长者莱昂纳多一样,成为典型的文艺复兴人物。

考虑到现存的大量信件,素描和回忆,米开朗基罗是16世纪文献记载最丰富的艺术家之一。他被当代传记作家称赞为他那个时代最有成就的艺术家。

米开朗基罗很早就出名了。他最著名的两件作品《圣母怜子报》《大卫》都是在30岁之前雕刻的。虽然米开朗基罗并不认为自己是画家,但他创作了两幅西方艺术史上最具影响力的壁画:《创世纪》中天花板上的场景罗马的西斯廷教堂,以及祭坛墙上的《最后的审判》。他设计的劳伦图书馆开创了风格主义建筑。71岁时,他接替小安东尼奥·达·桑加洛,成为圣彼得大教堂的建筑师。米开朗基罗改变了计划,使西端完成了他的设计,穹顶也完成了,但后来他去世了。

米开朗基罗是第一位在世时出版传记的西方艺术家。在他的一生中出版了三本传记。其中一个是乔治·瓦萨里(Giorgio Vasari)提出的,米开朗基罗的作品超越了任何活着或死去的艺术家的作品,“不仅在一种艺术中是至高无上的,而且在所有三种艺术中都是如此”

在他的一生中,米开朗基罗经常被称为“神”。

同时代的人钦佩他的可怕--他向艺术的观众灌输敬畏感的能力。后来的艺术家试图模仿米开朗基罗风格的表现力、物理性,这推动了礼仪主义的兴起,这是在文艺复兴时期和巴洛克时期之间西方艺术的一个短暂的运动。

现在的比较是将它与我们的 LLM 进行比较,看看它生成了哪些主题。我们在本地使用 llamafile,并使用本地量化模型在提示和响应之间快速迭代,而无需使用外部模型。 

 

 

现在,我们可以比较我们自己生成的结果和模型生成的结果。 

 

我们可以看到结果还可以,但可能没有我们想要的那么低水平?例如,“文艺复兴”对我们根本没有帮助,因为我们所有的艺术家都来自文艺复兴时期。文学不是艺术中的一个范畴。因此,我们的下一步是修改提示。 

 

我们可以手动进行这种提示调整,或者使用自动提示调整库,但是我们可能会发现我们的模型本身没有足够的艺术信息,在这种情况下,我们可能希望使用与文艺复兴时期艺术特别相关的文本样本对其进行微调,然后重试。 

 

一旦我们完成了这个手动循环,我们还可以执行离线指标评估,这使我们能够根据商定的学术基准更系统地评估模型。主题对齐是一门不精确的科学,因为它是基于人类认为的类别的好主题,但我们可以使用余弦相似度等指标来查看给定主题对的匹配程度。 

 

开发人员这样做了并调整了模型,首席执行官再次感到高兴。但是,现在团队遇到了一个不同的问题,也是一种成功的诅咒。他们需要将此模型部署到生产环境中。

 

“我喜欢这些生成的主题!

我们什么时候能在产品中看到这个”

 

现在,该团队有一个用于趋势主题检测的用例,还拥有了一个评估指标:手动共鸣和重新缩放的点积,用于人类分配和机器分配的主题之间的相似性。

不过,他们也遇到了问题。他们正在构建的系统庞大而复杂。他们目前涉及模型以及称为 LLM 操作的可怕东西,还涉及更新、监控系统、存储提示、监控模型输出、监控延迟、安全性、软件包更新。他们已经用LLM构建了一个产品,可以产生摘要输入,但现在,每当一有东西坏掉了,他们就不知道该去哪里寻找。

 

The Reproducible Example

可重复的例子

 

因此,在最后一天,最终开发人员分享了一个故事。他说:“这个故事是关于艾伦·乌尔曼的。她是一名软件工程师,从 1970 年代后期开始从事复杂系统的工作,包括在初创公司和大公司工作,写了许多关于计算机科学实践艺术的论文。她的最新著作名为《代码生活》(Life in Code),在书中,她描述了程序员在编写程序时的思维。这就把我们目前所讨论的一切联系在一起。

她写道,跟踪人类逻辑和代码逻辑之间的转换是很困难的。“当你写代码时,你的脑海里充满了细节,数以百万计的知识。这种知识是以人的形式存在的,也就是说相当混乱。例如,试着想想你所知道的关于发票这样简单的事情的一切。现在试着告诉一个外星人如何准备一个。那就是编程......编程就是在人类生活的混乱和计算机语言的逐行世界之间进行转换。“

她说,“为了做到这一点,开发人员不能失去注意力。当人类世界的知识在你的脑海中翻滚时,你必须不停地打字,打字。你不能被打断。”

在这种环境中,你受到信息限制,但很专注。克服错误更难,但更容易找到它并测试可能的解决方案,因为反馈周期相当短。之所以会出现这种情况,是因为在早期,开发人员的工作更接近机器,更接近金属,更接近计算源,即使有中断和阻塞,它们也是不同的。

大多数程序都是用 C 等语言在本地编写和编译的。第三方库要少得多。实现是从头开始编写的,主要的信息来源是书籍、手册页和 Usenet。近似的用户体验类似于编写 python,只能访问 python.org

Ullman 在本书的另一部分描述了这种现象,她描述了与一位名叫 Frank 的开发人员合作的情况。弗兰克以前做过铁杆技术贡献者,但是当他和乌尔曼一起工作时,他已经转向了财务报告,他个人很痛苦,他也讨厌乌尔曼,因为她“十分接近金属”。 


“为了表达更接近机器的想法,工程师参考了低级代码。在日常生活中,低通常意味着不好的事情。在编程中,低是好的,低是更好的。如果你想要钱和声望,你需要编写只有机器或其他程序员才能理解的代码。你越接近心脏问题,你做的越多,那很重要。”

——艾伦·乌尔曼

如今,要接近金属化是非常困难的,因为当我们使用分布式系统、机器学习和云时,它们中的每一个都是建立在以前的开发人员构建的海龟级别之上的,并且更容易分心。当你把非确定性的 LLM和用于训练和服务它们的分布式系统混合在一起时,你就会想出一种特殊的地狱,使得不可能有良好的开发人员体验。

我们能做的就是人们一直在做的事情:创建reprex。reprex 是一个可重现的示例,它来自 R 社区。在 R 中,这相当容易,因为它是一个独立的软件,但我们也可以为同样的事情而努力。

下面是 Python 中的 reprex 示例,这是我们在第一节中刚刚回顾的 RMSE 代码。我们可以知道它将在审阅者的计算机上以与我们的计算机相同的方式运行,我们可以进行故障排除和检查。

当您处理复杂的分布式系统时,Reprex 会派上用场。例如,这是开发人员在尝试为他们的模型提供服务时正在处理的一个实际问题:尝试对 Ray 进行故障排除。

Ray 是一个基于 PythonC++ 的分布式框架,用于训练和服务机器学习模型,供培训 LLM 的公司使用。它的前身包括 HadoopSpark。它还从其他分布式库中汲取灵感。Ray 很酷的一点是,它很容易在本地运行,并且启动单个实例是开箱即用的东西,这意味着我们已经更接近金属了。

但是,如果您遇到问题,由于架构非常复杂,可能需要一段时间才能找到问题的根源。Ray 有几种正交模式协同工作。首先,您可以在远程集群和 actor 上执行一些任务,这些任务是有状态任务。这来自计算机科学中的 actor 模式,该模式从其环境中接收消息并可以发送回消息。 

我们还有集群级别的通信模式,全局控制存储管理事务,如果你在 Kubernetes 上运行它,还有 Kubernetes 原语,还有任务执行图、各种模块:仪表板、ray trainRay serve。为了将你的思想包裹起来,你必须理解的模式数量确实令人震惊。

但别忘了,人类在追踪复杂性时只能将几件事保留在记忆中!

 

在构建趋势主题应用程序时,该团队遇到了一个问题,他们希望使用 Ray serve 测试其模型的主题检测管道。Ray Serve 获取您的本地可部署代码,并使用 Ray 客户端将其发送到您的 Ray 集群,Ray 客户端是一个将 Python 脚本连接到远程 Ray 集群的 API

Ray Serve 允许您使用使用捆绑的 Ray Actor (称为部署)发送的代码为模型提供服务。部署通常在 Kubernetes 之上,在 Ray 之上,在某种云集群中提供。它由多个 Ray Actor 组成,这些 Ray Actor 是由 Ray 控制平面运行和管理的有状态服务。Controller 充当部署的入口点,绑定到 Ray 集群头节点上的代理,并将其转发到副本,这些副本使用实例化模型为请求提供服务。

为了提供部署,您可以使用指定 YAML 基础配置的模式。

这里的一个关键部分是工作目录,它指定在运行时将代码下载到集群的位置:这是 ray 指定 RuntimeEnv 的方式的一部分。

copyworking_dir 的副本将在运行时下载到集群中,每个远程 Ray worker 的当前工作目录将更改为该working_dir副本

 

在生产级部署中,建议working_dir来自提供的 zip 可执行文件,该可执行文件通常固定到 GitHub 中的哈希。因此,该团队的配置文件设置如下: 

但是,YAML 文件中有几个故障点,它看起来简化了,但实际上在代码本身中读取和实现配置的方式向我们隐藏了复杂性。但是这个模型没有启动或运行。为什么?如果你看一下所有的故障点,至少有三四个可能会绊倒你。首先,Ray 处理导入路径的方式可能与我们通常假设的 uvicorn 路由它们的方式不同。然后,还有运行时环境的问题:当我们的可部署资产托管在 github 上时会发生什么。然后,我们遇到了 Python 依赖性的问题:当您使用 transformers torch 等快速移动的库时,总是可以保证您会有冲突,有时即使您将它们固定到特定版本。最后,还有 Ray 部署逻辑本身:当我们指定 CPUGPU 选项时会发生什么,以及这些选项如何与我们的 Kubernetes 集群配合使用?

Whew. 是时候开始调试了。

从这里开始的方法是开始读取日志和堆栈跟踪。当你有一个非常大的分布式系统时,这里有一个你可能会得到的堆栈跟踪的示例,它可能非常令人沮丧,因为它没有指出问题所在。

这里发生了很多事情,它似乎来自 importlib 而不是 Ray 本身,但 Ray 使用 importlib 作为依赖项。因此,为了隔离它,团队进入了 Ray 中调用 importlib 的模块,该模块位于 python/ray/_private/utils.py 中 。

 

然后,团队所做的是找到打开导入路径的方法,并为该问题创建一个 reprex,他们将调用importlib.import_module的确切方法放入笔记本中,然后直接调用代码。 

这直接不起作用,他们在不使用任何外部依赖项或 Ray 本身的情况下证明了这一点——他们找到了问题的根源。这意味着,在他们的情况下,他们不能使用嵌套路径来构建他们的模型部署,但为了简单起见,他们可以从根级别提供它。事实证明,问题出在import_attr中,这意味着他们必须包含配置文件和脚本才能在存储库的同一根级别启动集群。 

不过,他们还没有完成。当他们尝试部署它时,当他们尝试从 Git 哈希下载可部署文件时,他们也遇到了 404 错误。这是因为他们试图启用资产下载,也就是我们的主题趋势检测代码,从私有 GitHub 存储库到集群中的头节点以运行代码。最初,他们尝试使用细粒度的 PAT:这不起作用,因此他们不得不使用旧版 GitHUB 令牌。在此过程中,他们了解到 Ray 使用一个名为 smart_open 的库来流式传输来自 S3/GitHub 的文件,这有助于他们解决进一步的问题。 

所有这些都被 YAML、快速变化的文档和系统的多个部分从我们身边抽象出来。为了从中得到你需要的信息,团队需要无情地剥离所有细节领域并专注于问题,并希望得到一个可重复的例子。这越来越接近金属,这就是注意力。

最后,该团队有一个原型在生产中运行。解决了这个问题后,团队继续前进,并成功地部署了主题检测应用程序,这让 CEO非常高兴。每个人都得到了加薪,从此在佛罗伦萨自己的城堡里过着幸福的生活。

直到他们开始开发更多产品。

“我喜欢这个正在生产中!

我们什么时候能做得更多?”

Conclusion

结论


开发人员庆祝,他们已经将一些东西投入生产,设法摆脱了LLM领域的炒作,并专注于对他们公司很重要的用例。

他们现在聚在一起,回顾他们所取得的成就,以及他们为什么能够这样做。他们首先在应用程序中为生成式 AI 选择一个用例,并评估可用于该用例的模型。然后,他们选择在线和离线评估指标来继续评估循环。最后,当涉及到构建系统时,他们专注于尽可能小的可组合部分,而不是从顶部开始,并分解代码,直到他们理解它。 

All of this helped them concentrate, focus on what was most important and stay close to the metal.

感谢 Davide Eynard、Guenia Izquierdo、James Kirk 和 Ravi Mody 


编者按

图标: Freepik
布朗齐诺,托莱多的埃莱奥诺拉肖像,约 1539 年
《十日谈》,弗朗茨·泽弗·温特豪德 1837 年
巴塞罗那景观,安东·范登·温加尔德 (Anton van den Wyngaerde) 著,1563 年
梯度下降