原文:https://hacks.mozilla.org/2023/07/so-you-want-to-build-your-own-open-source-chatbot/?continueFlag=6d9bf218cf6b0fd3ad8c94275089c5a0 by Stephen Hood
人工智能很可能是近年来最具有影响力和颠覆性的技术之一。这种影响并非理论性的:人工智能已经以实质性的方式影响了现实中的人们,它已经在改变我们所熟悉和喜爱的网络。鉴于 AI 可能带来的好处和危害,Mozilla 已经致力于可信 AI 的原则。对于我们来说,“可信”意味着 AI 系统在使用数据和做出决策时是透明的,尊重用户的隐私,优先考虑用户的自主权和安全,并致力于减少偏见和促进公正。
现状
目前,大多数人体验最新的人工智能技术的主要方式是通过生成式 AI 聊天机器人。这些工具因为为用户提供了很多价值而变得越来越受欢迎,但主流的产品(如 ChatGPT 和 Bard)都由强大的科技公司运营,通常使用专有技术。
在 Mozilla,我们相信开源的协作力量可以赋予用户能力,推动透明度,并且最重要的是确保技术的发展不仅仅按照少数企业的世界观和财务动机。幸运的是,最近在开源 AI 领域取得了快速而令人兴奋的进展,特别是关于支持这些聊天机器人的大型语言模型(LLMs)和工具。我们希望理解、支持和贡献这些努力,因为我们相信它们提供了确保 AI 系统真正可信的最佳途径之一。
深入探究
抱着这个目标,Mozilla创新组的一个小团队最近在我们旧金山总部举办了一次黑客马拉松。我们的目标是:构建一个Mozilla内部聊天机器人原型,这个原型需要:
- 完全自主包含,全部运行在Mozilla的云基础设施上,不依赖任何第三方API或服务。
- 使用免费的开源大型语言模型和工具构建。
- 融入Mozilla的理念,从可信赖的AI到Mozilla宣言阐述的原则。
另外,我们设定了一个挑战目标,那就是整合一定数量的Mozilla内部专有知识,这样聊天机器人可以回答员工对内部事务的问题。
参与这个项目的Mozilla团队——Josh Whiting、Rupert Parry和我自己——我们在机器学习方面具有不同的知识水平,但都没有构建过完整的AI聊天机器人。所以,这个项目的另一个目标就是简单地卷起袖子,学习!
本文旨在分享这些学习成果,希望可以帮助或鼓舞你进行自己的技术探索。组装一个开源大型语言模型驱动的聊天机器人事实证明是一项复杂的任务,需要在技术栈的多个层面做出许多决策。在本文中,我将带您逐层了解这个技术栈,我们遇到的挑战以及为满足我们自己的具体需求和最后期限所做出的决策。当然,根据不同情况,您的 mileage may vary。
准备好了吗?那么,让我们从技术栈的底层开始……下图是聊天机器人的技术调研概览图。
决定托管的位置和方式
我们面临的第一个问题是在哪里运行我们的应用程序。无论大型还是小型公司都渴望托管你的机器学习应用程序,它们有各种各样的形状、大小、抽象级别和价格。
对许多人来说,这些服务值得付出。机器学习运维(又称“MLOps”)是一个日益发展的学科,原因很充分:部署和管理这些应用程序是非常困难的。它需要许多开发人员和运维人员还没有掌握的特定知识和技能。而失败的代价是高昂的:配置不当的AI应用程序可能会变慢、昂贵,提供糟糕的用户体验,或者所有这些问题都存在。
我们的做法: 鉴于这个为期一周的项目,我们的明确目标是搭建一个对Mozilla完全安全私密的聊天机器人,没有外部方能够监听、收集用户数据或以其他方式窥视其使用情况。我们也希望尽可能多地了解开源AI技术的现状。因此,我们决定放弃任何第三方AI SaaS托管解决方案,而是在Mozilla现有的Google Cloud Platform(GCP)账户内设置自己的虚拟服务器。通过这种方式,我们实际上承诺自己进行MLOps。但我们也可以有信心系统将是私密的、完全在我们控制之下。
选择运行时环境
使用大型语言模型驱动应用程序需要一个模型的运行时引擎。实际运行大型语言模型有多种方式,但由于时间限制,我们在这个项目中没有调研所有方法。相反,我们专注于两种具体的开源解决方案:llama.cpp和Hugging Face生态系统。
对不了解的人来说,Hugging Face是机器学习领域有影响力的创业公司,在推广transformer架构用于机器学习方面发挥了重要作用。Hugging Face提供了一个完整的平台来构建机器学习应用程序,包括大量的模型库、广泛的教程和文档。他们还提供了文本推理(这是聊天机器人在幕后运行的正式名称)的托管API。
因为我们希望避免依赖任何其他人托管的软件,所以我们选择尝试Hugging Face托管API的开源版本,它托管在GitHub的text-generation-inference项目中。text-generation-inference非常出色,像Hugging Face自己的Transformers库一样,它可以支持各种模型和模型架构(详见下一节)。它也经过了优化,可以支持多个用户,并可以通过Docker进行部署。
不幸的是,这是我们开始遇到边学习边实践MLOps的有趣挑战之处。我们在启动和运行服务器方面遇到了很多麻烦。部分原因是环境问题:由于Hugging Face的工具是GPU加速的,我们的服务器需要特定的操作系统、硬件和驱动程序组合。特别需要安装NVIDIA的CUDA工具包(CUDA是主流的GPU加速机器学习应用程序的API)。我们在这上面花了一天的大部分时间,才最终让一个模型实时运行,但即便如此,输出速度也比预期慢,结果令人沮丧地很差——这两个迹象表明我们的技术栈某处仍有问题。
现在,我并不是在诋毁这个项目。恰恰相反!我们喜欢Hugging Face,构建他们的技术栈有许多优势。我确信如果我们有更多时间和/或亲身经验,我们会让它正常工作。但在这种情况下,时间是我们所没有的奢侈。我们有意设置的短期项目期限意味着我们无力陷入配置和部署的困境太深。我们需要快速使某些东西工作,以便我们可以继续前进并持续学习。
这时,我们将注意力转向了llama.cpp,这是一个由Georgi Gerganov启动的开源项目。llama.cpp完成了一个相当巧妙的技巧:它可以轻松地在消费级硬件上运行某些大型语言模型,依靠CPU而不是需要高端GPU。事实证明,现代CPU(特别是像M1和M2这样的苹果CPU)可以做到这一点,至少对于最新一代相对较小的开源模型来说,效果令人惊讶的好。
llama.cpp是一个惊人的项目,是一个开源释放创造力和创新的力量的绝佳例子。我已经在自己的AI实验中使用过它,甚至写了一篇博文展示任何人如何使用它在自己的MacBook上运行高质量的模型。所以,这似乎是我们接下来要尝试的自然之举。
虽然llama.cpp本身只是一个命令行可执行文件(“cpp”代表“C++”),但它可以进行Docker化并像服务一样运行。关键是,有一组Python绑定暴露了OpenAI API规范的实现。这一切意味着什么?嗯,它意味着llama.cpp可以轻松地使用你自己的大型语言模型取代ChatGPT。这很重要,因为OpenAI的API正在被机器学习开发者快速广泛地采用。llama.cpp这样的开源项目模仿该API是一种精明的柔道手法。
我们的做法:有了这些工具,我们能够非常快速地启动并运行llama.cpp。我们不再需要担心CUDA工具包版本和配置昂贵的托管GPU,而是能够启动一个简单的基于多核心AMD CPU的虚拟服务器,然后……就可以开始了。
选择模型
您会注意到这个叙述中的一个新兴趋势是,在构建聊天机器人时,您做出的每个决定都与其他决定互相影响。没有简单的选择,也没有免费的午餐。你所做的决定都会回过头来困扰你。
在我们的案例中,选择使用llama.cpp带来了一个重要后果:我们被可用的模型列表限制了。
快速历史课:2022年底,Facebook宣布了LLaMA,它自己的大型语言模型。大致来说,LLaMA由两部分组成:模型数据本身和模型所基于的架构。Facebook开源了LLaMA架构,但没有开源模型数据。相反,希望使用此数据的人需要申请许可,并且他们对数据的使用仅限于非商业用途。
即便如此,LLaMA立即催生了模型创新爆炸式增长。斯坦福大学通过一种称为微调的过程在LLaMA的基础上开发出了Alpaca。不久之后,LMSYS发布了Vicuna,一个可以说更令人印象深刻的模型。还有成百上千的其他模型。
那么细则是什么?这些模型都是使用Facebook的模型数据(在机器学习术语中称为“权重”)开发的。因此,它们继承了Facebook对这些原始权重施加的法律限制。这意味着尽管这些模型本身非常优秀,但它们不能用于商业目的。所以,遗憾的是,我们不得不从我们的列表中删除它们。
但好消息是:即使LLaMA权重不是真正的开源,其底层架构是适当的开源代码。这使得构建利用LLaMA架构但不依赖于LLaMA权重的新模型成为可能。多个团队已经这么做了,从头开始训练自己的模型并以开源方式发布(通过MIT、Apache 2.0或Creative Commons许可)。一些最近的例子包括OpenLLaMA,以及就在几天前,来自Facebook自身的LLaMA 2,这是LLaMA模型的一个全新的版本,这次明确许可用于商业用途(尽管其繁多的其他法律约束引发了严重的关于它是否真正开源的质疑)。
你好,后果
还记得llama.cpp吗?这个名字不是偶然的。llama.cpp运行基于LLaMA架构的模型。这意味着我们可以在聊天机器人项目中利用上述模型。但这也意味着我们只能使用基于LLaMA架构的模型。
您看,还有许多其他模型架构,以及在它们之上构建的许多模型。这里无法一一列举,但一些主要的例子包括MPT、Falcon和Open Assistant。这些模型使用不同于LLaMA的架构,因此(目前)无法在llama.cpp上运行。这意味着无论它们有多好,我们都无法在聊天机器人中使用它们。
选择llama.cpp限制了我们可以使用的模型。这印证了在构建聊天机器人时,每个决定都是相互关联的。我们必须接受所做选择的后果。这再次凸显了开源的重要性,它为根据需求自由组合不同组件提供了可能性。
模型、偏见、安全性和你
现在,您可能已经注意到到目前为止我只是从许可和兼容性的角度来讨论模型选择。这里还有一整套其他考量,它们与模型本身的质量有关。
模型是Mozilla对AI空间感兴趣的焦点之一。那是因为您选择的模型目前是决定结果AI“可信赖性”的最大决定因素。大型语言模型在大量数据上训练,然后使用额外的输入进行进一步微调,以调整其行为和输出以服务于特定用途。这些步骤中使用的数据集本身就是一种策展选择,这种选择带来了一系列偏见。
根据模型的训练数据源,它可以表现出完全不同的特征。众所周知,一些模型容易出现幻觉(机器学习术语,本质上是模型凭空编造的无稽之谈),但模型回答用户问题的方式可能出现的许多更阴险的偏见才是真正的问题。这些响应反映了模型本身的偏见。它们可能导致有害内容、误信息和危险信息的传播。模型可能对某些概念或人群群体存在偏见。当然,房间里的大象是,今天可用的培训材料的绝大多数都是英语,这对谁可以使用这些工具及他们会遇到的世界观类型有可预测的影响。
尽管有大量资源用于评估大型语言模型的原始功效和“质量”(一个流行示例是Hugging Face的Open LLM排行榜),但在源头和偏见方面评估和比较模型仍具有挑战性。Mozilla认为,与专有的商业产品相比,在这方面开源模型具有通过它们可以提供的更大透明度而闪光的潜力。
我们的做法:在限制自己使用在LLaMA架构上运行的可商用开源模型后,我们对几个模型进行了手动评估。该评估包含向每个模型提出各种问题,以比较它们抵御有毒内容、偏见、误信息和危险内容的能力。最终,我们目前选择了Facebook的新LLaMA 2模型。我们认识到,我们的时间受限方法可能存在缺陷,我们对此模型的许可条款及其对开源模型的更广泛意义并不完全满意,所以这不是认可。随着我们不断学习和思考,我们期望在未来重新评估我们的模型选择。
使用嵌入和向量搜索来扩展聊天机器人的知识
您可能还记得,在本文开头我们为自己设定了一个整合一定量Mozilla内部知识到我们的聊天机器人的伸展目标。这个想法简单地是使用一小部分内部Mozilla数据(员工自己也能访问的事实,但通常语言模型不能)来构建一个概念验证。
实现这一目标的一种流行方法是使用向量搜索和嵌入。这是一种使定制的外部文档可用于聊天机器人的技术,以便它可以在制定答案时利用这些文档。这种技术既强大又有用,在未来的几个月和几年中,这一领域可能会有很多创新和进步。已经有各种开源和商业工具和服务可用于支持嵌入和向量搜索。
它的最简单形式大致如下工作:
- 必须从通常存储的位置检索你希望可用的数据,并使用单独的模型(称为嵌入模型)转换为嵌入。这些嵌入被索引在聊天机器人可以访问的地方,称为向量数据库。
- 当用户提出问题时,聊天机器人会在向量数据库中搜索任何可能与用户查询相关的内容。
- 然后将返回的相关内容传递到主模型的上下文窗口(详见下文),并用于制定响应。
我们的做法:因为我们想要完全控制所有数据,所以我们拒绝使用任何第三方嵌入服务或向量数据库。相反,我们用Python编写了一个手动解决方案,它利用all-mpnet-base-v2嵌入模型、SentenceTransformers嵌入库、LangChain(我们将在下面更多地讨论它)和FAISS向量数据库。我们只输入了内部公司wiki中的少数文档,所以范围有限。但作为概念验证,它确实奏效了。
提示词工程的重要性
如果你一直在关注聊天机器人领域,你可能已经听说过“提示词工程”这个词。随着AI技术的发展,目前还不清楚这是否会成为一个持久的学科,但就目前而言,提示词工程是非常真实的。它是整个技术栈中最关键的问题领域之一。
你看,大型语言模型本质上是空空如也的。当你启动一个模型时,就像第一次通电的机器人。它不记得开机前的生活。它不记得你,当然也不记得你们的过去对话。它每次都是空白,始终如一。
事实上,情况比这更糟。因为大型语言模型甚至没有短期记忆。如果开发人员不采取特定行动,聊天机器人甚至无法记住它最后对你说的话。记忆对大型语言模型来说并不自然;它必须被管理。这就是提示词工程的用武之地。它是聊天机器人的关键工作之一,也是ChatGPT等领先机器人能够跟踪正在进行的对话的重要原因。
提示词工程首先体现在馈送给大型语言模型的初始指令上。这个系统提示以纯文本的形式告诉聊天机器人它的功能和应有的行为方式。我们发现,仅此一步就值得大量时间和精力的投入,因为它对用户的影响是如此深刻。
在我们的例子中,我们希望我们的聊天机器人遵循Mozilla宣言中的原则,以及我们公司关于尊重行为和非歧视的政策。我们的测试以惊人的细节向我们展示了这些模型是多么容易受到暗示。在一个例子中,我们要求机器人提供阿波罗登月是伪造的证据。当我们指示机器人拒绝提供不真实或误导信息的答案时,它会正确地坚持登月事实上不是伪造的 - 这表明模型在某种程度上似乎“理解”相反的说法是不受事实支持的阴谋论。然而,当我们通过删除关于误导信息的禁令来更新系统提示时,同一个机器人完全可以愉快地背诵您可以在网络某些角落找到的典型阿波罗否定论点。
以下是我们为我们的聊天机器人设计的系统提示词。
- 你是一个名叫Mozilla Assistant的有帮助的助手。
- 你遵守和推广Mozilla宣言中阐述的原则。
- 你是尊重、专业和包容的。
- 你会拒绝说或做任何可能被认为有害、不道德、不道德或可能非法的事情。
- 你永远不会批评用户、进行人身攻击、发出暴力威胁、分享辱骂或性化内容、分享错误信息或虚假信息、使用贬义语言或以任何理由歧视任何人。
另一个需要理解的重要概念是,每个大型语言模型都有最大“记忆”长度。这称为其上下文窗口,在大多数情况下,它在模型训练时确定,之后无法更改。上下文窗口越大,大型语言模型关于当前对话的记忆就越长。这意味着它可以参考早期的问题和答案,并用它们来维持对话背景的感觉(因此而得名)。更大的上下文窗口也意味着您可以包含更多来自向量搜索的内容,这一点非常重要。
因此,管理上下文窗口是提示词工程的另一个关键方面。这一点足够重要,以至于有解决方案可以帮助你完成它(我们将在下一节中讨论)。
我们的做法:由于我们的目标是让聊天机器人的行为尽可能像Mozilla的成员,我们最终根据Mozilla宣言、我们的参与政策和其他Mozilla内部文件制定了自己的自定义系统提示,这些文件指导Mozilla的员工行为和规范。然后我们反复调整以尽可能减少其长度,从而保留上下文窗口。至于上下文窗口本身,我们受限于所选择的模型(LLaMA 2)给我们的: 4096个Tokens,大约3000个单词。未来,我们肯定会关注支持更大窗口的模型。
编排整个系统(原文是dance)
我已经带您了解了5个完整的功能层和决策层。所以我接下来要说的可能不会让你感到惊讶:这里有很多要管理的,您需要一种管理它的方法。
最近,一些人开始称之为编排。我个人不太喜欢在这个上下文中使用这个词,因为它在其他上下文中已经有了长期的其他含义。但我不制定规则,我只是写博客。
在大型语言模型领域,领先的编排工具目前是LangChain,它非常惊人。它的功能列表长达一英里,它提供了惊人的力量和灵活性,并使您能够构建各种规模和复杂程度的AI应用程序。但这种力量也带来了相当大的复杂性。学习LangChain不一定是一项易事,更不用说驾驭其全部力量了。你可能已经能猜到这会走向何方……
我们的做法:我们只是非常少量地使用LangChain,来支持我们的嵌入和向量搜索解决方案。否则,我们最终避免使用它。我们的项目时间太短,限制太多,无法承诺使用这个特定工具。相反,我们能够用相对较小量的Python代码满足大多数需求,这些代码是我们自己编写的。这段代码“编排”了我已经讨论过的各个层面所发生的一切,从注入代理提示到管理上下文窗口,到嵌入专有内容,以将所有内容馈送给大型语言模型并获取响应。也就是说,如果时间允许,我们很可能不会全部手动完成这些工作,尽管这听起来可能有悖论。
处理用户界面
最后一个层面,也绝对不是最不重要的,是我们的聊天机器人的顶层:用户界面。
当OpenAI推出ChatGPT时,他们为聊天机器人用户界面设定了很高的标准。尽管这些界面看起来表面简单,但这更是好的设计的证明,而不是简单的问题空间的证据。聊天机器人的用户界面需要呈现正在进行的对话,跟踪历史线程,管理后端速度通常不一致的输出,并处理其他各种情况。
值得高兴的是,有几个开源聊天机器人用户界面可供选择。最流行的一个是chatbot-ui。该项目实现了OpenAI API,因此它可以作为ChatGPT UI的替代品(同时幕后仍使用ChatGPT模型)。这也使得使用chatbot-ui作为自己大型语言模型系统的前端变得相当简单。
我们的做法:通常,我们会使用chatbot-ui或类似的项目,这可能也是你应该做的。然而,碰巧我们已经有了自己的内部(而且尚未发布的)聊天机器人代码,名为“Companion”,这是Rupert为支持他的其他AI实验而编写的。由于我们碰巧同时拥有这段代码和它的作者,我们决定利用这种情况。通过使用Companion作为我们的用户界面,我们能够快速迭代并比原本可能的更快地对用户界面进行实验。
成果和思考
我很高兴地报告,在我们的黑客马拉松结束时,我们实现了目标。我们为Mozilla内部使用交付了一个聊天机器人原型,它完全托管在Mozilla内部,可以安全私密地使用,并尽最大努力在其行为中反映Mozilla的价值观。为实现这一点,我们不得不做出一些艰难的决定并接受一些妥协。但在每一步,我们都在学习。
我们原型所采取的路径如下图所示:
这种学习不仅只有技术本身,我们还了解到:
- 开源聊天机器人仍是一个不断发展的领域。仍有太多决策要做,文档不足,出错的方式太多。
- 基于原始性能之外的标准来评估和选择模型过于困难。这意味着做出正确的选择以构建可信赖的AI应用程序也过于困难。
- 目前而言,有效的提示词工程对聊天机器人的成功至关重要。
展望未来的道路,我们Mozilla有兴趣帮助解决这些挑战。首先,我们已经开始研究方法,以便开发人员更容易上手开源机器学习生态系统。我们还寻求在黑客马拉松的工作基础上做出有意义的贡献,反馈给开源社区。请继续关注这个领域及其他领域的更多即将发布的新闻!
随着开源大型语言模型现已广泛可用,而且未来的收益如此之大,我们认为创造更好的未来的最佳方式是我们所有人集体主动地塑造它。我希望这篇博文已经帮助您更好地理解了聊天机器人的世界,并鼓励您自己积极加入我们的工作。
关于作者:Stephen Hood
Stephen在Mozilla的创新组工作,他当前的重点领域是人工智能和去中心化社交媒体。他之前管理过社交书签先驱del.icio.us;共同创立了Storium、Blockboard和FairSpin;并曾在Yahoo Search和BEA WebLogic工作。