![Картинка сгенерирована Stable Diffusion Картинка сгенерирована Stable Diffusion](https://habrastorage.org/getpro/habr/upload_files/eb9/ec6/026/eb9ec602683ff46a62d6ec9aea9a119e.png)
А Вы когда‑то задумывались о том, как классно было бы хакнуть собеседование? Создать себе цифрового помощника, который ответит на все вопросы интервьюера.
Вот и я задумался. В этой статье предлагаю создать небольшое приложение на основе Whisper для распознавания речи и ChatGPT для генерации текста. Также добавим простой пользовательский интерфейс, чтобы облегчить себе наше «списывание».
![Демо приложения Демо приложения](https://habrastorage.org/getpro/habr/upload_files/622/f16/2b5/622f162b535ca6896135a74d8ff8052d.gif)
Дисклеймер: Я настоятельно рекомендую не использовать созданное приложение в прямом его назначении. Цель этой статьи - продемонстрировать, как за один вечер можно создать прототип ассистента для ответов на вопросы, что еще год назад казалось чем-то немыслимым.
Как это работает
![Диаграмма приложения Диаграмма приложения](https://habrastorage.org/getpro/habr/upload_files/691/4a5/bf4/6914a5bf4a05d0648c3c870ce41eee1b.png)
Приложение, при нажатии на кнопку (главное вовремя нажать), начинает записывать голос интервьюра. После чего с помощью модели Whisper мы переводим аудио в текст. А затем просим чатгпт ответить на поставленный вопрос и отображаем его на экране. При этом, всё это не займёт много времени, так что вы сможете отвечать на вопросы интервьюера практически без задержек.
Несколько замечаний, прежде чем мы начнем:
Я намеренно использовал готовые API, чтобы решение не требовало много ресурсов и могло работать даже на слабых ноутбуках.
Я проверил функциональность приложения только на Linux. Может потребоваться изменить библиотеки записи аудио или установить дополнительные драйверы для других платформ.
Вы можете найти весь код в репозитории GitHub.
Я надеюсь, у меня получилось вас заинтриговать, поэтому давайте уже начнём!
Запись вопросов интервьюера
Поскольку наша цель — разработать приложение, которое будет работать независимо от платформы, через которую проводятся звонки — будь то Google Meet, Zoom, Skype и т. д., мы не можем использовать API этих приложений. Поэтому нам нужно записывать аудио напрямую на нашем компьютере.
Важно отметить, что мы будем записывать аудиопоток не через микрофон, а через динамики. После небольшого поиска я нашел библиотеку soundcard. Её авторы утверждают, что она кросс‑платформенная, поэтому у вас не должно возникнуть с ней проблем.
Единственным недостатком для меня была необходимость точно указать диапазон времени, в течение которого будет производиться запись. Однако эту проблему можно решить, так как функция записи возвращает аудиоданные в формате массива numpy, которые можно объединить.
Итак, простой код для записи аудио через динамики будет выглядеть так:
import soundcard as sc
RECORD_SEC = 5
SAMPLE_RATE = 48000
with sc.get_microphone(
id=str(sc.default_speaker().name),
include_loopback=True,
).recorder(samplerate=SAMPLE_RATE) as mic:
audio_data = mic.record(numframes=SAMPLE_RATE * RECORD_SEC)
После этого мы можем сохранить его в формате .wav
с использованием библиотеки soundfile:
import soundfile as sf
sf.write(file="out.wav", data=audio_data, samplerate=SAMPLE_RATE)
Здесь вы найдете код, связанный с записью аудио.
Распознавание речи
![](https://habrastorage.org/getpro/habr/upload_files/e30/a0a/f27/e30a0af27a49d35ceb9b135fe19b1fde.png)
В этом шаге мы будем использовать модель Whisper от Open Ai, которая умеет работать с несколькими языками. Во время моих тестов она показала хорошее качество распознавания текста, поэтому я решил остановиться на ней. Её также можно использовать через API:
import openai
def transcribe_audio(path_to_file: str = "out.wav") -> str:
with open(path_to_file, "rb") as audio_file:
transcript = openai.Audio.translate("whisper-1", audio_file)
return transcript["text"]
Если вы предпочитаете не использовать API, вы можете запустить его локально. Я бы порекомендовал использовать whisper.cpp. Это высокопроизводительное решение, которое не требует много ресурсов (автор библиотеки запускал модель на устройстве iPhone 13).
Здесь вы найдете документацию по API Whisper.
Генерация ответа
Для генерации ответа на вопрос интервьюера мы будем использовать ChatGPT. Хотя использование API кажется простой задачей, нам нужно решить еще две дополнительные задачи:
Редактирование распознанного текста - транскрипты могут быть некачественными. Например, если плохо слышно интервьюера, или кнопка записи активирована слишком поздно.
Ускорение генерации ответа - для нас важно получить ответ как можно быстрее, чтобы поддерживать бесперебойный ход разговора и предотвращать сомнения.
Улучшение качества транскриптов
Чтобы справиться с этим, мы явно укажем в системном промпте, что мы используем потенциально несовершенные транскрипции аудио:
SYSTEM_PROMPT = """You are interviewing for a {INTERVIEW_POSTION} position.
You will receive an audio transcription of the question.
Your task is to understand question and write an answer to it."""
Ускорение генерации текста
Для ускорения генерации мы будем делать два одновременных запроса к ChatGPT. Эта концепция близка к подходу, описанному в статье Skeleton-of-Thought, и визуально представлена ниже:
![Схема двусторонней связи с ChatGPT Схема двусторонней связи с ChatGPT](https://habrastorage.org/getpro/habr/upload_files/e12/c2a/63b/e12c2a63b8628c63380e2a95738eb83a.png)
Первый запрос сгенерирует быстрый ответ, не более 70 слов. Это поможет продолжить интервью без неловких пауз:
QUICK = "Concisely respond, limiting your answer to 70 words."
Второй запрос вернет более подробный ответ. Это необходимо для поддержания более глубокого вовлечения в разговор:
FULL = """Before answering, take a deep breath and think step by step.
Your answer should not exceed more than 150 words."""
Стоит отметить, что в запросе используется структура «take a deep breath and think step by step» («сделайте глубокий вдох и думайте шаг за шагом»), метод, который, как показали недавние исследования, обеспечивает наиболее высокое качество ответов.
Здесь вы найдете код, связанный с API ChatGPT.
Создание простого графического интерфейса
![Демо управления приложением с помощью кнопок Демо управления приложением с помощью кнопок](https://habrastorage.org/getpro/habr/upload_files/b66/d77/8ee/b66d778ee8ce18458ad849fab526adce.gif)
Чтобы визуализировать ответ от ChatGPT, нам нужно создать простое приложение с графическим интерфейсом. После изучения нескольких фреймворков я решил остановиться на PySimpleGUI. Он позволяет создавать графические приложения легко с обширным набором виджетов. Кроме того, мне была нужна следующая функциональность, которую получилось найти в этой библиотеке:
Возможность быстро написать рабочий прототип без долгих углублений в документацию проекта.
Поддержка выполнения длительных функций в отдельном потоке.
Управление клавишами клавиатуры.
Вот пример кода для создания простого приложения, отправляющего запросы к API OpenAI в отдельном потоке с использованием perfrom_long_operation
:
import PySimpleGUI as sg
sg.theme("DarkAmber")
chat_gpt_answer = sg.Text( # we will update text later
"",
size=(60, 10),
background_color=sg.theme_background_color(),
text_color="white",
)
layout = [
[sg.Text("Press A to analyze the recording")],
[chat_gpt_answer],
[sg.Button("Cancel")],
]
WINDOW = sg.Window("Keyboard Test", layout, return_keyboard_events=True, use_default_focus=False)
while True:
event, values = WINDOW.read()
if event in ["Cancel", sg.WIN_CLOSED]:
break
elif event in ("a", "A"): # Press A --> analyze
chat_gpt_answer.update("Making a call to ChatGPT..")
WINDOW.perform_long_operation(
lambda: generate_answer("Tell me a joke about interviewing"),
"-CHAT_GPT ANSWER-",
)
elif event == "-CHAT_GPT ANSWER-":
chat_gpt_answer.update(values["-CHAT_GPT ANSWER-"])
Здесь вы найдете код, связанный с приложением с графическим интерфейсом.
Собираем всё вместе
Теперь, когда мы рассмотрели все необходимые компоненты, пришло время собрать наше приложение. Вот схематичная архитектура, как это будет выглядеть:
![Логика работы кнопок в графическом интерфейсе Логика работы кнопок в графическом интерфейсе](https://habrastorage.org/getpro/habr/upload_files/435/bad/93d/435bad93db390ebd7da1552620ea7369.png)
Чтобы лучше понять, как все это работает, я записал демонстрацию:
Дальнейшая работа
Если вы хотите усовершенствовать это решение, вот несколько советов для улучшения:
Ускорьте ответы от LLM: Для этого вы можете использовать модели с относительно меньшим количеством параметров, такие как LlaMA-2 13B, чтобы ускорить время ответа. А также использовать разные техники дополнительного ускорения, о которых я писал тут.
Используйте NVIDIA Broadcast: Эта модель позволяет вашим глазам всегда смотреть в камеру, даже, если вы решите отвести взгляд. В этом случае интервьюер не заметит, что вы читаете ответ.
Демо NVIDIA Broadcast. Создайте расширение для браузера: Это может быть особенно полезно, если вас просят пройти лайв-кодинг. В таком случае, вы просто сможете выделить задачу и отправить её на решение.
Заключение
Итак, с использованием Whisper и ChatGPT мы создали себе помощника для собеседований.
Разумеется, не рекомендуется использовать его в подобных целях, ведь это как минимум не этично. Нашей основной задачей была попытка расширить границы возможностей ИИ, а так же показать глубину этого мира, ведь мы стоим на пороге новой эры, и совсем немного приоткрыли эту дверь. Кто знает, какие невероятные инновации ждут нас впереди.