Вопросно-ответные системы в области кода: часть 1
Всем привет, желаю вам хорошего дня и настроения
Было ли когда-то у вас желание получить документацию к своему проекту в пару кликов?
У меня — регулярно. Жила была проблема, которая преследует меня с начала жизни — я понятия не имею, что происходит и зачем тут написано так много букв которые делают какие-то умные штуки. И я не только про код, с квантовой физикой да и с жизнью в целом такая же проблема.
Контекст, а не реклама
Так уж получилось, что большую часть жизни я в итоге занимаюсь кодом и после прорыва LLM, первая вещь которую мы попытались сделать — документацию к коду. Простая идея: жмешь 2 кнопки и у тебя готова документация к проекту. Собственно https://nextdocs.ai/ пытается это сделать. Тут пример готовой документации для: фронтовой библиотеки html2pdf, тут мы задокументировали Docker Compose, а это проект про который дальше пойдет речь — codeqai.
Но самое забавное, что мы поняли во время разработки, что мы сделали инструмент для исследования кода, и ничто не мешает нам, использовать проект как инструмент для описания вообще любого неизвестного нам кода.
Проще говоря, перед вами поставили задачу, и вы, прежде всего вы пойдете искать уже готовые решения, тут и происходят регулярные проблемы связанные с тем, что даже если на словах проект решает обозначенную проблему, запустили и проверили проект — тоже решает заявленную проблему, но чего-то не хватает. Количество усилий которые нужно потртаить на исправления одной мелочи иногда не соразмерно больше чем написать с нуля, хотя основная проблема именно в понимании.
Теперь, мы можем к любой заинтересовавшей нас библиотеке создать документацию за пару кликов и 5 минут ожидания, но что не мало важно, теперь у нас больше контекста для кода. Можете думать об этом как об обучении большой языковой моделью маленькую с целью решение более узкой и специфичной задачи более эффективным и дешевым способом.
Да, описание проекта, это хорошо, но как правило, угадать, что конкретно в определенный момент времени хочет человек от проекта довольно сложно, хоть и стараемся это сделать, более простой вариант — дать пользователю возможность спросить о коде используя контекст который у нас есть.
codeqai
Исходный код доступен по ссылке.
Дальше разберем, как codeqai устроен внутри
CodeQAI использует Python >=3.9, <3.12 как основной язык. Для того, чтобы обрабатывать код на различных языках, он использует библиотеку Treesitter. Тут общая документация, а тут для python.
Treesitter — это инструмент для создания парсеров и библиотека инкрементального парсинга, простой пример, где вы могли встречаться с результатом его работы — подсветка синтаксиса. Статья с примерами на эту тему, с визуальным объяснением того, как tree-sitter уже влияет на нашу жизнь.
Из коробки Treesitter поддерживает:
Также библиотеки, которые используются в codeqai:
LangChain — это фреймворк для разработки приложений на основе больших языковых моделей (LLM). Благодаря этому фреймворку, можно работать с большим количеством различных языковых моделей. Например OpenAI, Azure, Google, Anthropic и другие. Streamlit — это библиотека Python для построения интерактивных веб-приложений, управляемых данными. Она используется для создания приложения, которое позволяет более удобно общаться с ботом. Запускается так:
codeqai app
FAISS — это библиотека для эффективного поиска сходства и кластеризации плотных векторов. В данном случае, для codeqai, FAISS выступает в роли базы данных для векторов, то есть локально хранит вектора, которые извлек treesitter
Несмотря на большую поддержку различных языков, моделей удаленных чатов и т.п. CodeQAI поддерживает далеко не все, а именно:
OpenAI, Azure OpenAI и Anthropic удаленные модели, а также такие языки программирования как: Python, Typescript, Javascript, Java, Rust, Kotlin, Go, C++, C, C#, Ruby.
Этапы работы
1. Сперва весь репозиторий разбивается на векторы с помощью treesitter.
2. Далее результаты разбития сохраняются локально в векторную базу данных FAISS с использованием либо трансформаторов предложений, либо инструкторов-эмбеддингов, либо OpenAI’s text-embedding-ada-002. Все это позволяет преобразовывать текст в векторные представления, для использования в приложениях, как поиск, рекомендации и кластеризация.
3. Вся база будет сохранена в файловой системе компьютера и при следующем запуске, будет подгружаться.
4. Для общения можно использовать локальные варианты LLM, например llama.cpp или Ollama, а также удаленные модели чата, которые перечислялись выше.
5. Чтобы синхронизировать изменения в репозитории, codeqai сохраняет хэши коммитов, если данные устарели (хэши не совпадают), то они удаляются и создаются заново с обновленной информацией.
6. Если используется локальный контейнер Ollama, то его нужно запустить заранее на порту 11434
Можно сказать, что необходимые ресурсы сильно зависят от той технологии, что будет использована в конечном итоге. Например, можно локально разворачивать llama модель, которая есть в открытом доступе и спокойно работает без вложений (но не все версии). То есть, в таком случае, нужна только машина достаточной мощности, которая сможет все это обрабатывать. Если же использовать платные модели для чата, то тут все зависит от объема и сложности запросов, к платной модели.
Одна из машин на которой мы тестировали:
Intel® Xeon® CPU E5–2640 0 @ 2.50GHz 2.50 GHz; 16 gb ddr3; RTX 2060 Super
можно развернуть локальную модель, а также запустить codeqai.
Пример чата
Тестировали на проекте, который сам публикует видео в TikTok, да, мы ленивые, а про остальное лучше не спрашивать.
cli.py -> get_auth_args
112 def get_auth_args():
113 │ """
114 │ Generates a parser which is used to get all of the authentication information
115 │ """
116 │ parser = ArgumentParser(
117 │ │ description='TikTok Auth is a program which can log you into multiple accounts sequentially'
118 │ )
cli.py -> get_auth_args
120 │ # authentication arguments
121 │ parser.add_argument('-o', '--output', default='tmp',
122 │ │ │ │ │ │ help='The output folder to save the cookies to')
123 │ parser.add_argument('-i', '--input', help='A csv file with username and password')
124 │ # parser.add_argument('-h', '--header', default=True,
125 │ # help='The header of the csv file which contains the username and password')
126 │ parser.add_argument('-u', '--username', help='Your TikTok email / username')
cli.py -> get_auth_args
67 │ parser.add_argument('-u', '--username', help='Your TikTok email / username')
68 │ parser.add_argument('-p', '--password', help='Your TikTok password')
auth.py -> login
134 def login(driver, username: str, password: str):
135 │ """
136 │ Logs in the user using the email and password
137 │ """
138 │ assert username and password, "Username and password are required"
139 │
140 │ # checks if the browser is on TikTok
141 │ if not config['paths']['main'] in driver.current_url:
142 │ │ driver.get(config['paths']['main'])
В общем, мы проверили — работает. Но нам не подходит, по нескольким причинам:
Потребленние оперативной памяти, 1.6 GB только для небольшого проекта и весь индекс будет занимать оперативной памяти. Мягко говоря на сервер в 64 RAM много проектов не поместится.
Блокирующая система индексации, очень долго, мы писали свой парсер кода и приложили усилия к тому, чтобы этот процесс был эффективным и быстрым, хотим продолжить в том же духе, тут нам прийдется и долго ждать и много отдать памяти.
Код внутри не плохой, но сильно «про код», да, мы делали MVP основываясь только на коде, но есть огромное желание эксперементировать с дополнительным контекстом: существующая документация, таск-трекеры, вообщем все что может ответить на вопрос «почему» тут эта функция, а не только на вопрос «что делает». Вот запускают подкаст на основе GitHub репозитория, идея не плохая, сам бы с радостью на пробежке слушал бы про новые коммиты или ядро Linux, но пока рано, к чему я — хочется гибкости, хочется иметь возможность эксперементировать, чтобы работало как конструктор.
Личные выводы, codeqai может быть хорошим для локального и собственного использования, но нас куда сильнее привлект проект textai давая ту гибкость которую бы мы хотели получить от семантического поиска.
Про textai речь пойдет в следующей статье.