Пишем умный поиск по коду с Open AI
В этой статье мы кратко рассмотрим технологию, которая лежит в основе ChatGPT — эмбеддинги, и напишем простой интеллектуальный поиск по кодовой базе проекта.
Эмбеддинг (от англ. embedding) — это процесс преобразования слов или текста в набор чисел – числовой вектор. Векторы можно сравнивать между собой, чтобы определить насколько два текста или слова похожи по смыслу.
К примеру, возьмем два числовых вектора (эмбеддинга) слов «отдать» и «подарить». Слова разные, но смысл схож, т.е. они взаимосвязаны, и результатом обоих будет передача чего-то кому-то.
В контексте кодовой базы проекта эмбеддинги можно использовать для поиска по коду или документации. Например, можно векторизовать функции, классы, методы и документацию, а затем сравнивать их векторы с вектором запроса поиска, чтобы находить релевантные функции или классы.
На старте дают $18 — мне этого хватило, чтобы сделать пример для этой статьи (ниже) и провести дальнейшее тестирование сервиса.
Выберите какой-нибудь проект на TypeScript в качестве кодовой базы. Рекомендую взять небольшой, чтобы не томить себя в ожиданиях генерации векторов. Или можете воспользоваться уже готовым. Еще нам нужен Python 3+ версии и библиотека от Open AI. Не пугайтесь, если не знаете какой-то язык — примеры будут простыми и не требуют глубокого понимания TypeScript и Python.
Приступим. Для начала напишем код для извлечения различных фрагментов кода из проекта, например, функции. TypeScript предоставляет удобный API компилятор для работы с AST деревом, что упрощает задачу. Установим csv-stringify библиотеку для генерации CSV:
Пишем извлечение информации из кода:
Скрипт собирает все нужные нам фрагменты и выдает CSV таблицу в консоль. CSV файл состоит из колонок file_name, name, code, docs, combined.
- file_name - здесь будет содержаться путь до файла в проекте,
- name - название фрагмента, к примеру, «имя функции»,
- code - код сущности,
- docs - описание из комментариев к фрагменту,
- combined - это сложение контента code и docs колонок — мы будем использовать эту колонку для генерации векторов.
Запускать его не нужно.
Переходим к Python.
Установим библиотеку от Open AI и утилиты для работы с эмбеддингами:
Создаем файл create_search_db.py со следующим кодом:
Скрипт запускается code-to-csv.js(1), загружается результат в датафрейм(2) и генерирует векторы для контента в колонке combined(3). Векторы записываются в embedding колонку. Итоговая таблица со всем нужным для поиска сохраняется в файл search_db.csv(4).
Для работы скрипта понадобится API токен. Библиотека openai автоматически может брать токен из переменных окружения, поэтому мы напишем удобный скрипт, чтобы не записывать токен в окружение вручную:
Сохранить его куда-нибудь, к примеру в env.sh, и запустим:
Все готово для генерации базы поиска.
Запускаем скрипт create_search_db.py и ждем пока появится CSV файл с базой. Это может занять пару минут. После можно приступать к написанию поисковика.
Создаем новый файл search.py и пишем следующее:
Разберем работу скрипта. Данные из search_db.csv загружаются в датафрейм(1), в объектно-ориентированное представление таблицы. Потом строки с векторами из таблицы конвертируются в массивы с числами(2), чтобы с ними можно было работать. В конце запускается функция поиска по базе со строкой запроса(3).
Функция поиска генерирует вектор для запроса(4), сравнивает этот вектор с каждым вектором из базы и сохраняет степень схожести в similarities колонку(5).
Степень схожести определяется числом от 0 до 1, где 1 означает максимальная подходящий вариант. Данные в таблице сортируются по similarities(6).
В заключении извлекаются первые три строки из базы и выводятся в консоль.
Поисковик готов, можно протестировать.
Для теста запускаем команду с запросом:
Пробуем ввести запрос на другом языке:
Как вы видите, поиск осуществляется с учетом значения слов в запросе, а не просто по ключевым словам.
Инструмент не ограничен только этим случаем и одним проектом. Можно организовать более масштабный поиск по всем проектам сразу. Это полезно, если вы каждый год разрабатываете по нескольку схожих в функционале приложений и хотели бы быстро находить готовые решения. Или у вас много документации, а поиск по ключевым словам не всегда эффективен. Все зависит от задач и сферы применения.
Благодарю за внимание!
Полезные ссылки:
Очень любопытно. Как раз на днях делал полнотексттвый поиск по базе sqlite3. Было бы интересно и это попробовать.
Я только изучаю python. Не понял зачем здесь нужен Type Script?
Просто для примера