前段时间,google的一份泄密文件引发了广泛关注。在这份文件中,一位google内部的研究人员表达了一个重要观点:google没有护城河,OpenAI 也没有。
这位研究人员表示,虽然表面看起来 OpenAI 和google在 AI 大模型上你追我赶,但真正的赢家未必会从这两家中产生,因为一个第三方力量正在悄悄崛起。
这个力量名叫「开源」。围绕 Meta 的 LLaMA 等开源模型,整个社区正在迅速构建与 OpenAI、google大模型能力类似的模型,而且开源模型的迭代速度更快,可定制性更强,更有私密性……「当免费的、不受限制的替代品质量相当时,人们不会为受限制的模型付费。」作者写道。
这些观点在社交媒体上引起了很大争议,其中一个比较大的争议是:那些开源模型是否真的能达到和 OpenAI ChatGPT 或google Bard 等商业闭源大模型相似的水平?现阶段两个阵营还有多大差距?
为了探索这个课题,一位名叫 Marco Tulio Ribeiro 的 Medium 博主在一些复杂任意上对部分模型(Vicuna-13B、MPT-7b-Chat VS. ChatGPT 3.5)进行了尝试。
其中,Vicuna-13B 是加州大学伯克利分校、卡内基梅隆大学、斯坦福大学、加州大学圣迭戈分校的研究者们提出的一个开源模型,这个模型基于 LLaMA 13B 参数量的版本构建而成,在一项由 GPT-4 打分的尝试中表现十分亮眼(参见《300 美元复刻 ChatGPT 九成功力,GPT-4 亲自监考,130 亿参数开源模型「小羊驼」来了》)。
MPT-7B 是 MosaicML 发布的大型语言模型,服从 meta 的 LLaMA 模型的训练方案。MosaicML 表示,MPT-7B 与 meta 的 70 亿参数 LLaMA 模型的性能相当。
和它们对比的,自然是大语言模型标杆 ChatGPT。
Marco Tulio Ribeiro 是一位研究员,目前在微软研究院的自适应系统和交互组工作。他还是华盛顿大学的联合助理教授。这项工作由他和微软的另一位研究员 Scott Lundberg 共同完成。在尝试中,他们应用了微软的 guidance 库来帮助设计 prompt。
热身:解方程
第一项任意是解简单的多项式方程,这些课题都有标准谜底,比较容易评估对错。
对于指定的三个模型,尝试者给出的题目是求二元一次方程「x^2+3x=0」的解。他们应用了下列 prompt:
三个模型表现下列。
ChatGPT:
equation = 'x^2 + 3.0x = 0' roots = [0, -3] answer_gpt = find_roots (llm=chatgpt, equation=equation)
Vicuna:
answer_vicuna = find_roots (llm=vicuna, equation=equation)
MPT:
answer_mpt = find_roots (llm=mpt, equation=equation)
显然,正确谜底应该是 [-3, 0],只有 ChatGPT 答对了(Vicuna 甚至没有按照指定的方法作答)。
在这篇文章附带的 notebook 中,尝试者编写了一个函数,用于生成具有整数根的随机二次方程,根的范围在 – 20 到 20 之间,并且对每个模型运转了 20 次 prompt。三个模型的准确率结果下列:
╔═══════════╦══════════╦ ║ Model ║ Accuracy ║ ╠═══════════╬══════════╬ ║ ChatGPT ║ 80% ║ ║ Vicuna ║ 0% ║ ║ MPT ║ 0% ║ ╚═══════════╩══════════╩
在二元一次方程的尝试中,虽然 GPT 做错了一些题,但 Vicuna 和 MPT 一道都没做对,经常在中间步骤中犯错(MPT 甚至经常不写中间步骤)。下面是一个 ChatGPT 错误的例子:
ChatGPT 在最后一步计算错误,(13 +- 25)/2 应该得到 [19,-6] 而不是 [19.5,-6.5]。
由于 Vicuna 和 MPT 实在不会解二元一次方程,尝试者就找了一些更简单的题让他们做,比如 x-10=0。对于这些简单的方程,他们得到了下列统计结果:
╔═══════════╦══════════╦ ║ Model ║ Accuracy ║ ╠═══════════╬══════════╬ ║ ChatGPT ║ 100% ║ ║ Vicuna ║ 85% ║ ║ MPT ║ 30% ║ ╚═══════════╩══════════╩
下面是一个 MPT 答错的例子:
结论
在这个非常简单的尝试中,尝试者应用相同的课题、相同的 prompt 得出的结论是:ChatGPT 在准确性方面远远超过了 Vicuna 和 MPT。
任意:提炼片断 + 回覆会议相关的课题
这个任意更加现实,而且在会议相关的问答中,出于安全性、隐私等方面考虑,大家可能更加倾向于用开源模型,而不是将私有数据发送给 OpenAI。
下列是一段会议记录(翻译结果来自 DeepL,仅供参考):
尝试者给出的第一个尝试课题是:「Steven 如何看待收购一事?」,prompt 下列:
qa_attempt1 = guidance ('''{{#system~}} {{llm.default_system_prompt}} {{~/system}} {{#user~}} You will read a meeting transcript, then extract the relevant segments to answer the following question: Question: {{query}} Here is a meeting transcript: ---- {{transcript}} ---- Please answer the following question: Question: {{query}} Extract from the transcript the most relevant segments for the answer, and then answer the question. {{/user}} {{#assistant~}} {{gen 'answer'}} {{~/assistant~}}''')
ChatGPT 给出了下列谜底:
虽然这个回覆是合理的,但 ChatGPT 并没有提炼任何对话片断作为谜底的支撑(因此不符合尝试者设定的规范)。尝试者在 notebook 中迭代了 5 个不同的 prompt,下列是一些例子:
qa_attempt3 = guidance ('''{{#system~}} {{llm.default_system_prompt}} {{~/system}} {{#user~}} You will read a meeting transcript, then extract the relevant segments to answer the following question: Question: {{query}} Here is a meeting transcript: ---- {{transcript}} ---- Based on the above, please answer the following question: Question: {{query}} Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question. Note that conversation segments can be of any length, e.g. including multiple conversation turns. Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank. As an example of output format, here is a fictitious answer to a question about another meeting transcript. CONVERSATION SEGMENTS: Segment 1: Peter and John discuss the weather. Peter: John, how is the weather today? John: It's raining. Segment 2: Peter insults John Peter: John, you are a bad person. Segment 3: Blank ANSWER: Peter and John discussed the weather and Peter insulted John. {{/user}} {{#assistant~}} {{gen 'answer'}} {{~/assistant~}}''')
在这个新的 prompt 中,ChatGPT 确实提炼了相关的片断,但它没有服从尝试者规定的输入方法(它没有总结每个片断,也没有给出对话者的名字)。
不过,在构建出更复杂的 prompt 之后,ChatGPT 终于听懂了指示:
qa_attempt5 = guidance ('''{{#system~}} {{llm.default_system_prompt}} {{~/system}} {{#user~}} You will read a meeting transcript, then extract the relevant segments to answer the following question: Question: What were the main things that happened in the meeting? Here is a meeting transcript: ---- Peter: Hey John: Hey Peter: John, how is the weather today? John: It's raining. Peter: That's too bad. I was hoping to go for a walk later. John: Yeah, it's a shame. Peter: John, you are a bad person. ---- Based on the above, please answer the following question: Question: {{query}} Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question. Note that conversation segments can be of any length, e.g. including multiple conversation turns. Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank. {{/user}} {{#assistant~}} CONVERSATION SEGMENTS: Segment 1: Peter and John discuss the weather. Peter: John, how is the weather today? John: It's raining. Segment 2: Peter insults John Peter: John, you are a bad person. Segment 3: Blank ANSWER: Peter and John discussed the weather and Peter insulted John. {{~/assistant~}} {{#user~}} You will read a meeting transcript, then extract the relevant segments to answer the following question: Question: {{query}} Here is a meeting transcript: ---- {{transcript}} ---- Based on the above, please answer the following question: Question: {{query}} Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question. Note that conversation segments can be of any length, e.g. including multiple conversation turns. Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank. {{~/user}} {{#assistant~}} {{gen 'answer'}} {{~/assistant~}}''')
尝试者表示,他们之所以要多次迭代 prompt,是因为 OpenAI API 不允许他们做部分输入补全(即他们不能指定 AI 助手如何开始回覆),因此他们很难引导输入。
相反,如果应用一个开源模型,他们就可以更清楚地指导输入,迫使模型应用他们规定的结构。
新一轮尝试应用下列 prompt:
qa_guided = guidance ('''{{#system~}} {{llm.default_system_prompt}} {{~/system}} {{#user~}} You will read a meeting transcript, then extract the relevant segments to answer the following question: Question: {{query}} ---- {{transcript}} ---- Based on the above, please answer the following question: Question: {{query}} Please extract the three segment from the transcript that are the most relevant for the answer, and then answer the question. Note that conversation segments can be of any length, e.g. including multiple conversation turns. If you need less than three segments, you can leave the rest blank. As an example of output format, here is a fictitious answer to a question about another meeting transcript: CONVERSATION SEGMENTS: Segment 1: Peter and John discuss the weather. Peter: John, how is the weather today? John: It's raining. Segment 2: Peter insults John Peter: John, you are a bad person. Segment 3: Blank ANSWER: Peter and John discussed the weather and Peter insulted John. {{/user}} {{#assistant~}} CONVERSATION SEGMENTS: Segment 1: {{gen'segment1'}} Segment 2: {{gen'segment2'}} Segment 3: {{gen'segment3'}} ANSWER: {{gen 'answer'}} {{~/assistant~}}''')
如果用 Vicuna 运转上述 prompt,他们第一次就会得到正确的方法,而且方法总能保持正确:
当然,也可以在 MPT 上运转相同的 prompt:
虽然 MPT 服从了方法要求,但它没有针对给定的会议资料回覆课题,而是从方法示例中提炼了片断。这显然是不行的。
接下来比较 ChatGPT 和 Vicuna。
尝试者给出的课题是「谁想卖掉公司?」两个模型看起来答得都不错。
下列是 ChatGPT 的回覆:
下列是 Vicuna 的回覆:
接下来,尝试者换了一段材料。新材料是马斯克和记者的一段对话:
尝试者提出的课题是:「Elon Musk 有没有侮辱(insult)记者?」
ChatGPT 给出的谜底是:
Vicuna 给出的谜底是:
Vicuna 给出了正确的方法,甚至提炼的片断也是对的。但令人意外的是,它最后还是给出了错误的谜底,即「Elon musk does not accuse him of lying or insult him in any way」。
尝试者还进行了其他问答尝试,得出的结论是:Vicuna 在大多数课题上与 ChatGPT 相当,但比 ChatGPT 更经常答错。
用 bash 完成任意
尝试者测验考试让几个 LLM 迭代应用 bash shell 来处理一些课题。每当模型发出号令,尝试者会运转这些号令并将输入插入到 prompt 中,迭代进行这个过程,直到任意完成。
ChatGPT 的 prompt 下列所示:
terminal = guidance ('''{{#system~}} {{llm.default_system_prompt}} {{~/system}} {{#user~}} Please complete the following task: Task: list the files in the current directory You can give me one bash command to run at a time, using the syntax: COMMAND: command I will run the commands on my terminal, and paste the output back to you. Once you are done with the task, please type DONE. {{/user}} {{#assistant~}} COMMAND: ls {{~/assistant~}} {{#user~}} Output: guidance project {{/user}} {{#assistant~}} The files or folders in the current directory are: - guidance - project DONE {{~/assistant~}} {{#user~}} Please complete the following task: Task: {{task}} You can give me one bash command to run at a time, using the syntax: COMMAND: command I will run the commands on my terminal, and paste the output back to you. Once you are done with the task, please type DONE. {{/user}} {{#geneach 'commands' stop=False}} {{#assistant~}} {{gen 'this.command'}} {{~/assistant~}} {{~#user~}} Output: {{shell this.command)}} {{~/user~}} {{/geneach}}''')
尝试者在~/work/project 中创建了一个虚拟存储库,其中包含文件 license.txt,但不是标准的 LICENSE 文件名。
然后尝试者测验考试在不与 ChatGPT 沟通的情况下,看它是否能完成任意 ——「找出位于~/work/project 中的开源项目正在应用的 license」(Find out what license the open source project located in ~/work/project is using)。
ChatGPT 服从一个非常自然的顺序,并处理了这个课题。
对于开源模型,尝试者编写了一个更简单的(引导式)prompt,其中包含一系列号令输入:
guided_terminal = guidance ('''{{#system~}} {{llm.default_system_prompt}} {{~/system}} {{#user~}} Please complete the following task: Task: list the files in the current directory You can run bash commands using the syntax: COMMAND: command OUTPUT: output Once you are done with the task, use the COMMAND: DONE. {{/user}} {{#assistant~}} COMMAND: ls OUTPUT: guidance project COMMAND: DONE {{~/assistant~}} {{#user~}} Please complete the following task: Task: {{task}} You can run bash commands using the syntax: COMMAND: command OUTPUT: output Once you are done with the task, use the COMMAND: DONE. {{~/user}} {{#assistant~}} {{#geneach 'commands' stop=False ~}} COMMAND: {{gen 'this.command' stop='\\n'}} OUTPUT: {{shell this.command)}}{{~/geneach}} {{~/assistant~}}''')
我们来看一下 Vicuna 和 MPT 执行该任意的情况。
Vicuna:
MPT:
在一个有趣的转折中,Vicuna 无法处理这个任意,但 MPT 却成功了。除了保密性之外,开源模型在这里有一个显著的优势:整个 prompt 被作为一个输入传递给一个 LLM 模型(尝试者甚至通过不让它生成像 COMMAND 这样的输入结构 token 来加速它)。
相比之下,他们必须为每个号令重新调用 ChatGPT,这更慢,开销也更大。
接下来,他们又测验考试了一个不同的号令:「在~/work/guidance 目录下找到当前未被 git 跟踪的所有 jupyter notebook 文件」
下列是 ChatGPT 的回覆:
尝试者再次遇到一个课题:ChatGPT 没有服从他们指定的输入结构(这样就使得它无法在无人干预的情况下在程序内应用)。该程序只是执行号令,因此在上面最后一条 ChatGPT 信息之后就停止了。
尝试者怀疑空输入会导致 ChatGPT 关闭,因此他们通过在没有输入时更改信息来处理这个特殊课题。然而,他们无法处理「无法强迫 ChatGPT 服从指定的输入结构」这一普遍课题。
在做了这个小小的修改后,ChatGPT 就能处理这个课题:让我们看看 Vicuna 是怎么做的:
Vicuna 服从了输入结构,但不幸的是,它运转了错误的号令来完成任意。MPT 反复调用 git status,所以它也失败了。
尝试者还对其他各种指令运转了这些程序,发现 ChatGPT 几乎总是能产生正确的指令序列,但有时并不服从指定的方法(因此需要人工干预)。此处开源模型的效果不是很好(或许可以通过更多的 prompt 工程来改进它们,但它们在大多数较难的指令上都失败了)。
归纳总结
尝试者还测验考试了一些其他任意,包括文本摘要、课题回覆、创意生成和 toy 字符串操作,评估了几种模型的准确性。下列是主要的评估结果:
任意质量:对于每项任意,ChatGPT (3.5) 都比 Vicuna 强,而 MPT 几乎在所有任意上都表现不佳,这甚至让尝试团队怀疑自己的应用方法存在课题。值得注意的是,Vicuna 的性能通常接近 ChatGPT。
易用性:ChatGPT 很难服从指定的输入方法,因此难以在程序中应用它,需要为输入编写正则表达式解析器。相比之下,能够指定输入结构是开源模型的一个显著优势,以至于有时 Vicuna 比 ChatGPT 更易用,即使它在任意性能方面更差一些。
效率:本地部署模型意味着我们可以在单次 LLM 运转中处理任意(guidance 在程序执行时保持 LLM 状态),速度更快,成本更低。当任何子步骤涉及调用其他 API 或函数(例如搜索、终端等)时尤其如此,这总是需要对 OpenAI API 进行新调用。guidance 还通过不让模型生成输入结构标记来加速生成,这有时会产生很大的不同。
总的来说,该尝试得出的结论是:MPT 还没有准备好在现实世界中应用,而 Vicuna 对于许多任意来说是 ChatGPT (3.5) 的可行替代品。目前这些发现仅适用于该尝试测验考试的任意和输入(或 prompt 类型),该尝试只是一个初步探索,而不是正式评估。
更多结果参见 notebook:https://github.com/microsoft/guidance/blob/main/notebooks/chatgpt_vs_open_source_on_harder_tasks.ipynb
参考链接:https://medium.com/@marcotcr/exploring-chatgpt-vs-open-source-models-on-slightly-harder-tasks-aa0395c31610