Использование ChatGPT с помощью моделей Visual Foundation

Toolformer показал, что модели больших языков (LLM) могут легко научиться использовать такие инструменты, как API, для решения задач. Некоторыми из инструментов, которые модель научилась использовать, были калькуляторы, поисковые системы, календари и т. д.

Команда Microsoft недавно выпустила свою работу, в которой они показывают, как ChatGPT может использовать различные модели Visual Foundation, такие как ControlNet, стабильная диффузия и т. д., в качестве инструмента для решения задач, связанных с использованием изображений.

В сегодняшней статье мы рассмотрим статью Visual ChatGPT: Talking, Drawing and Editing with Visual Foundation Models. Все фрагменты кода указаны и при необходимости отредактированы из репозитория GitHub, ссылка на который приведена здесь.

Также авторы используют библиотеку LangChain, чтобы упростить взаимодействие с ChatGPT.

Авторы создают надежную структуру с различными компонентами, благодаря которой ChatGPT учится использовать разные модели видения. Введение информации из новой модальности в глубокое обучение отнюдь не является тривиальной задачей.

Visual ChatGPT не является монолитной моделью, его следует рассматривать как агента, который действует в среде/мире. Среда, в которой он существует, принимает текстовую и визуальную информацию. Он может использовать различные инструменты, такие как ChatGPT и Visual Foundation Models, для работы в среде.

Согласно LangChain:
Агенты — это системы, использующие языковую модель для взаимодействия с другими инструментами. Их можно использовать для более обоснованных вопросов и ответов, взаимодействия с API или даже выполнения действий.
https://langchain.readthedocs.io/en/latest/use_cases/agents.html

Когда мы пытаемся ввести новую модальность информации в LM, возникает множество проблем, например, как ChatGPT может понимать выходные данные визуальной модели, если они создают изображения, и многие другие. В этой статье в каждом разделе будут подробно описаны решения каждой из возникших подпроблем.

Как Visual ChatGPT принимает изображения в качестве входных данных?

Для таких задач, как редактирование изображений, визуальные ответы на вопросы и т. д., потребуется одно или несколько изображений в качестве входных данных, чтобы модель глубокого обучения могла их обработать и предоставить ответ. Однако ChatGPT работает исключительно в текстовой области и не может принимать никакие другие формы ввода.

Чтобы преодолеть это препятствие, авторы создают искусственный разговорный оборот. Когда изображение загружается пользователем, файл сохраняется с уникальным идентификатором, имя файла отправляется в качестве входных данных для ChatGPT, а ответ от ChatGPT устанавливается как Получен.

Этот ход сохраняется в истории разговоров ChatGPT, поэтому он всегда знает, какой файл использовать/на который ссылаться. Пример показан на изображении ниже:

Код для того же показан ниже:

with gr.Column(scale=0.15, min_width=0): 
  btn = gr.UploadButton(“Upload”, file_types=[“image”])

btn.upload(bot.run_image, [btn, state, txt], [chatbot, state, txt])

 def run_image(self, image, state, txt):
        image_filename = os.path.join('image', str(uuid.uuid4())[0:8] + ".png")
        print("======>Auto Resize Image...")
        img = Image.open(image.name)
        width, height = img.size
        ratio = min(512 / width, 512 / height)
        width_new, height_new = (round(width * ratio), round(height * ratio))
        img = img.resize((width_new, height_new))
        img = img.convert('RGB')
        img.save(image_filename, "PNG")
        print(f"Resize image form {width}x{height} to {width_new}x{height_new}")
        description = self.i2t.inference(image_filename)
        Human_prompt = "\nHuman: provide a figure named {}. The description is: {}. This information helps you to understand this image, but you should use tools to finish following tasks, " \
                       "rather than directly imagine from my description. If you understand, say \"Received\". \n".format(image_filename, description)
        AI_prompt = "Received.  "
        self.agent.memory.buffer = self.agent.memory.buffer + Human_prompt + 'AI: ' + AI_prompt
        print("======>Current memory:\n %s" % self.agent.memory)
        state = state + [(f"![](/file={image_filename})*{image_filename}*", AI_prompt)]
        print("Outputs:", state)
        return state, state, txt + ' ' + image_filename + ' '

Как показано выше, после загрузки изображения вызывается функция run_image. Эта функция создает новое имя изображения через uuid, выполняет некоторую предварительную обработку изображения, а затем создает искусственный поворот, который добавляется в буфер памяти.

Также видно, что описание изображения включено в качестве начального ввода вместе с именем файла. Это описание создано на основе Blip модели подписи к изображению.

class ImageCaptioning:
    def __init__(self, device):
        print("Initializing ImageCaptioning to %s" % device)
        self.device = device
        self.processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
        self.model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base").to(self.device)
 
self.i2t = ImageCaptioning(device="cuda:4")

Как убедиться, что ChatGPT использует модели Visual Foundation (VFM)?

Как видно из объявленной выше переменной Human_prompt, фраза но вам следует использовать инструменты для выполнения следующих задач, а не напрямую представлять из моего описания. задает тон ChatGPT для использования VFM. вместо произвольного ответа.

Human_prompt = "\nHuman: provide a figure named {}. The description is: {}. This information helps you to understand this image, but you should use tools to finish following tasks, " \
                       "rather than directly imagine from my description. If you understand, say \"Received\". \n".format(image_filename, description)

Кроме того, только подсказка о загрузке изображения, каждая подсказка также имеет префикс и суффикс, которые дополнительно гарантируют, что модель не будет вести себя случайным образом. Вот некоторые из ключевых инструкций, представленных в префиксе:

  • Являясь языковой моделью, Visual ChatGPT не может напрямую считывать изображения, но у него есть список инструментов для выполнения различных визуальных задач. Каждое изображение будет иметь имя файла, сформированное как «image/xxx.png», и Visual ChatGPT может вызывать различные инструменты для косвенного понимания изображений.
  • Что касается изображений, Visual ChatGPT очень строго относится к имени файла и никогда не будет создавать несуществующие файлы.
  • Visual ChatGPT может использовать инструменты в последовательности и лояльно относиться к результатам наблюдения инструментов, а не подделывать содержимое изображения и имя файла изображения. Он запомнит имя файла из последнего наблюдения инструмента, если будет создано новое изображение.
  • Visual ChatGPT имеет доступ к следующим инструментам:

Эти утверждения побуждают Visual ChatGPT использовать доступные визуальные инструменты, а также сообщают ему, как обрабатывать имена файлов и как общаться с пользователем об изображении, созданном одной из моделей VFM.

Как Visual ChatGPT узнает, какой VFM использовать?

Агенту предоставляется список всех инструментов (в данном случае VFM), которые можно использовать. Каждый из инструментов имеет описание с подробным описанием их возможностей, например:

Tool(name="Generate Image From User Input Text", func=self.t2i.inference,
      description="useful when you want to generate an image from a user input text and save 
      it to a file. like: generate an image of an object or something, or 
      generate an image that includes some objects. "
      "The input to this tool should be a string, representing the text 
      used to generate image. "),

Одним из используемых инструментов является VFM, который может преобразовывать текст в изображения, как видно, агенту предоставляется информация об имени инструмента, который суммирует то, что делает модель, вызываемая функция, а также описание с подробным описанием утилиты, входных данных. и выходные данные инструмента.

Затем агент использует описание инструмента и историю разговоров, чтобы решить, какой инструмент использовать дальше. Решения принимаются с использованием фреймворка ReAct.

self.agent = initialize_agent(
            self.tools,
            self.llm,
            agent="conversational-react-description",
            verbose=True,
            memory=self.memory,
            return_intermediate_steps=True,
            agent_kwargs={'prefix': VISUAL_CHATGPT_PREFIX, 
            'format_instructions': VISUAL_CHATGPT_FORMAT_INSTRUCTIONS, 
            'suffix': VISUAL_CHATGPT_SUFFIX}, 

Парадигма ReAct (рассуждение + действие)

ReAct можно рассматривать как расширение парадигмы рассуждений по цепочке мыслей (CoT). В то время как CoT позволяет LM генерировать цепочку рассуждений для решения задачи, тем самым снижая вероятность галлюцинаций.

ReAct гарантирует, что каждый ответ LM состоит из трех шагов:

  1. Мысль соответствует рассуждению.
  2. Действие — это когда агент выбирает действие на основе порожденной им мысли.
  3. Наблюдение — это когда агент наблюдает за результатами своих действий и может решить, что делать дальше.

Чтобы гарантировать, что ChatGPT отвечает в этом формате, в приглашение ChatGPT включено следующее:

VISUAL_CHATGPT_FORMAT_INSTRUCTIONS = “””To use a tool, please use the following 
format:
```Thought: Do I need to use a tool? Yes
   Action: the action to take, should be one of [{tool_names}]
   Action Input: the input to the action
   Observation: the result of the action```

When you have a response to say to the Human, or if you do not need to 
use a tool, you MUST use the format:
```Thought: Do I need to use a tool? No
{ai_prefix}: [your response here]```”””

Важно отметить, что результаты этапов «Мысль», «Действие» и «Наблюдение» не отображаются для конечного пользователя. Вся эта информация скрыта, чтобы конечный пользователь не был перегружен всеми промежуточными ответами, которые напрямую не решают запрос пользователя.

Вместо этого единственным фрагментом сгенерированного текста, отображаемым для пользователя, является поле [ваш ответ здесь], когда LM считает, что либо получил окончательный ответ, либо хочет задать пользователю вопрос.

Еще одним приятным эффектом парадигмы ReAct является то, что теперь мы можем связать использование нескольких инструментов вместе, потому что, увидев наблюдение, ChatGPT по умолчанию будет думать, нужно ли ему использовать инструмент. По существу Нужно ли мне использовать инструмент? это суффикс, добавляемый к каждому запросу и промежуточному ответу, сгенерированному ChatGPT.

Как Visual ChatGPT отправляет входные данные в модели VFM?

Как видно из приглашения выше, формат ответов ChatGPT заставляет ChatGPT выбирать один из инструментов из доступного списка, формат ввода инструмента можно получить из описания инструмента, которое мы видели ранее, и, наконец, вывод VFM может быть проанализировано из поля Observation.

Парсинг действия и ввод действия через библиотеку LangChain можно увидеть ниже:

def _extract_tool_and_input(self, llm_output: str) -> Optional[Tuple[str, str]]:
    if f"{self.ai_prefix}:" in llm_output:
        return self.ai_prefix, llm_output.split(f"{self.ai_prefix}:")[-1].strip()
    regex = r"Action: (.*?)[\n]*Action Input: (.*)"
    match = re.search(regex, llm_output)
    if not match:
        raise ValueError(f"Could not parse LLM output: `{llm_output}`")
    action = match.group(1)
    action_input = match.group(2)
    return action.strip(), action_input.strip(" ").strip('"')

При извлечении инструмента для использования и входных данных, которые должны быть предоставлены, делается вызов для выполнения инструмента.

Как обрабатываются выходные данные VFM?

Выходные данные каждой модели сохраняются в виде имени файла в следующем формате:

{Имя}_{Операция}_{Предыдущее имя}_{Название организации}.

  • Имя – это уникальный UUID.
  • Операция соответствует названию инструмента.
  • Предыдущее имя соответствует UUID входного изображения, используемого для создания нового изображения.
  • Название организации соответствует исходному входному изображению, предоставленному пользователем.

Следуя этому соглашению об именах, ChatGPT может легко получить информацию о вновь сгенерированном изображении.

def get_new_image_name(org_img_name, func_name="update"):
    head_tail = os.path.split(org_img_name)
    head = head_tail[0]
    tail = head_tail[1]
    name_split = tail.split('.')[0].split('_')
    this_new_uuid = str(uuid.uuid4())[0:4]
    if len(name_split) == 1:
        most_org_file_name = name_split[0]
        recent_prev_file_name = name_split[0]
        new_file_name = '{}_{}_{}_{}.png'.format(this_new_uuid, func_name, recent_prev_file_name, most_org_file_name)
    else:
        assert len(name_split) == 4
        most_org_file_name = name_split[3]
        recent_prev_file_name = name_split[0]
        new_file_name = '{}_{}_{}_{}.png'.format(this_new_uuid, func_name, recent_prev_file_name, most_org_file_name)
    return os.path.join(head, new_file_name)

Заключение

Наконец, все движущиеся части объединяются вместе, чтобы вести диалог с Visual ChatGPT, который может использовать визуальную информацию.

Эта работа является прекрасным примером важности быстрого проектирования. Подсказка позволяет агенту работать с визуальной информацией, используя имена файлов, и создавать цепочки мыслей -> действие -> ответы наблюдения, которые помогают определить, какой VFM использовать, и обрабатывать выходные данные моделей VFM.

Чтобы абстрагироваться от сложного характера решения, промежуточные ответы, включающие мысли, действия и наблюдения, скрыты от пользователя, и пользователю отображается только окончательный ответ, сгенерированный LM, как только ChatGPT считает, что ему больше не нужно использовать VFM.

Мы надеемся, что вы узнали что-то новое из этого обзора кода и статей. Дайте нам знать, нравится ли вам такой подход к просмотру исследовательских работ.

До следующего раза берегите себя и будьте добры.

СТАНЬТЕ ПИСАТЕЛЕМ на MLearning.ai