HuggingGPT,照进现实的Jarvis?

814 阅读5分钟

自从ChatGPT横空出世之后,各种GPT便层出不穷。

近期微软推出了HuggingGPT,并且在github上开源了对应的项目——Jarvis。单单这两点,就足以让勾起大众的兴趣。

今天这篇文章,就简单解读一下HUggingGPT这篇文章——HuggingGPT: Solving AI Tasks with ChatGPT and its Friends in Hugging Face

要点

  • HuggingGPT的主要目的是利用各种模型解决复杂任务(包含多个步骤、多种能力的任务)
  • HuggingGPT由大语言模型(ChatGPT)和专家模型(HugggingFace上丰富的AI模型)组成
  • 大语言模型(LLM)作为通用接口,完成任务规划、模型选择、响应生成
  • 专家模型主要负责任务执行
  • 目前主要的局限性有3点:执行效率、上下文长度、系统稳定性

简介

大语言模型(LLM)最近取得了长足的进步,展现出了强大的能力。

LLM主要交互的对象是文本,但现实世界中的任务涉及到多种模态——包括但不限于语音、图像、文本。

同时一个复杂的任务可以被分解为多个子任务,而这些子任务一般需要领域专用的模型才能取得更好的结果。

因此,一个自然而然的想法就是同时使用LLM和领域专用模型,来解决现实世界中的复杂问题。

具体到HuggingGPT上,它选用ChatGPT作为LLM,利用ChatGPT进行任务规划、模型选择、响应生成;选用HuggingFace上丰富的AI模型作为领域专用模型来负责任务执行

HuggingGPT的工作流程

HuggingGPT的工作流程包含4个部分:任务规划、模型选择、任务执行、响应生成

HuggingGPT任务流

HuggingGPT任务流

任务规划

这一步,LLM的主要作用完成任务分解以及确定各个子任务之间的依赖关系以及执行顺序。实现的基本形式就是构造基础的Prompt。Prompt的设计原则主要包含以下两点:

基于规范的指令

这里的规范其实就是将一个子任务定义为4个部分:

  • 任务ID
  • 预先定义的任务类型
  • 任务之间的依赖关系
  • 任务执行所需的参数列表

一个子任务可以表示为如下的json串:

{
 "id"0, 
 "task""image-to-text", 
 "dep": [-1], 
 "args": {"image"/examples/boy.jpg" }
}

预定义的任务类型如下图所示:

任务类型定义

任务类型定义

基于演示样例(Demonstration)的解析

这里的演示样例其实就像是few-shot learning中的few-shot,通过输入样例,激发出模型对任务的解析能力。
一个具体的样例如下:

Given an image /exp3.jpg, first generate a hed image, then based on the hed image and a prompt: a girl is reading a book, you need to reply with a new image.
[ {"task": "image-to-text", "id": 0, "dep": [-1], "args": {"image": /examples/boy.jpg" }},
{"task": "openpose-control", "id": 1, "dep": [-1], "args": {"image": "/examples/boy.jpg" }},
{"task": "openpose-text-to-image", "id": 2, "dep": [1], "args": {"text": "a girl is reading a book", "image": "-1" }}
]

模型选择

模型选择主要的功能就是根据任务分解的结果,分配一个具体的模型来处理子任务。

这里的具体做法涉及到两个步骤:

  • 根据子任务的任务类型筛选模型,并根据模型在HuggingFace上的下载次数作为排序依据对模型进行排序
  • 将筛选出排名Top-K的模型的描述,丢给ChatGPT,由大语言模型负责最后的筛选

上面这个步骤,就叫做In-Context Task-Model Assignment(基于上下文的任务模型分配)

任务执行

这一步没有太多的说的,论文中提到了两个概念——Hybrid Endpoint以及Resource Dependency。

Hybrid Endpoint意思是选用的模型接口可以在HuggingFace上(endpoints on HuggingFace),也可以部署在本地(local inference endpoints),两种接口都包含,这就叫做Hybrid

Resource Dependency是文章提出的一种解决子任务之间依赖关系的方法。具体做法很简单,相当于将具体使用到的资源,指定到一个任务的引用而非具体的资源上。表现形式就是-task_id。

响应生成

这一步骤主要是将前三个阶段(任务规划、模型选择和任务执行)中的所有信息整合到一起,生成简洁的回答,包括计划任务列表、为任务选择的模型以及模型的推理结果。

这里的推理结果其实是存在固定的格式,可以通过设计号的prompt以及前三阶段的结果生成。

文中给出的一个prompt样例如下:

With the input and the inference results, the AI assistant needs to describe the process and results. The previous stages can be formed as - User Input: {{ User Input }}, Task Planning: {{ Tasks }}, Model Selection: {{ Model Assignment }}, Task Execution: {{ Predictions }}. You must first answer the user’s request in a straightforward manner. Then describe the task process and show your analysis and model inference results to the user in the first person. If inference results contain a file path, must tell the user the complete file path. If there is nothing in the results, please tell me you can’t make it.

其他

文章的其余部分就是一些具体结果的展示与分析,具体可以参考文章中的第4章——实验。

文章的最后还提到了目前的一些局限性,主要包括执行效率、上下文长度、系统稳定性这三部分。

总体上而言,我觉得这篇文章的创新点在于给了任务一个形式化的定义,使得我们通过构造特定的Prompt使用LLM对任务的形式化定义进行填充。文章的其余部分其实更像是一个组装,没有太多的新意。
不过github上开源出来的Jarvis名字起的不错,有相关资源的朋友可以自己部署一下看看效果。建议的配置如下:

Ubuntu 16.04 LTS
VRAM >= 12GB
RAM > 12GB (minimal), 16GB (standard), 42GB (full)
Disk > 78G (with 42G for damo-vilab/text-to-video-ms-1.7b)