Промпты ChatGPT для программистов - как промптить для написания кода

Если вы хотите писать код с LLM (большими языковыми моделями) то не обязательно ставить себе IDE, специализированное API копилота и т.д.

Писать код умеет более-менее любая инструктивная LLM (Chat Gpt, Clode, Gigachat, LLAMA, Mistral, Qwen и др.). Они все видели исходники гитхаба, stackoverflow, quora и другие популярные ресурсы с кодом, вопосами к коду и ответами на вопросы по коду.

Если вы подключите себе копилота это конечно приятно, вы получите inline режим внутри вашей IDE. И программирование для вас превратится в написание 1-2 символов, секунду ожидания - и ваша строчка кода, а порой и сразу все следующие 5 строчек кода будут уже предложены копилотом. Причем в 90% случаев правильно - он напишет весь цикл, спользует переменные, которые есть в коде выше, подставит правильные значения констант. В общем удобно и быстро. Вы нажмете кнопку TAB, предложенный код подставится в редактируемый файл. И останется его только отредактировать в 1-2 местах. Скорость работы так вырастает раза в 2-3 точно.

Если хотите использовать копилота - это хорошо и правильно. В России сейчас бесплтано доступно решение от Сбера gigacode. Ставится в PyCharm и другие IDE, поддерживает разные языки программирования. Можете найти его и документацию по подключению на сайте https://gigacode.ru/

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

Чтобы модель стала хорошим кодером ее надо об это попросить. Поэтому все промпты будем делать вида:

<роль> 

<задача>

<формат>

Например

Ты эксперт по написанию чистого кода, на Python3. Ты выступаешь ментором для начинающих программистов и пишешь ясный, хорошо откомментированный код. 
По каждому вопросу ты стараешься дать макимально развернутый и исчерпывающий ответ.

<тут идет ваш вопрос>

<тут пожелания к формату вывода>

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

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

Пожелания к формату - важная штука. В общем-то что вы попросите, то и получите. И соответственно, можно просить:

  • написать код с комментариями
  • написать только код без комментариев
  • ответить на вопрос с примерами кода
  • дать несколько вариантов решения вопроса
  • дать наиболее эффективный вариант решения и объяснить почему
  • дать наиболее понятный вариант решения
  • дать наиболее лаконичный варинт решения
  • и так далее.

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

Думаем о том как писать код

Я бы условно разделил сценарии на несколько типов. И начнем с самого верхнеуровневого сценария.

Исследовательский сценарий

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

Например

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

Напиши код записи и отправки звука на сервер

Или

Какие библиотеки для распознавания звука в текст есть в Python? Покажи примеры перевода файла mp3 в текст. 

Дай несколько вариантов и напиши для каждой библиотеки ее плюсы и минусы

Или

У меня задача по распознанному голосовому сообщению находить названные товары. 
Я умею хорошо превращать голосовое сообщение в текст. 
Как мне сделать поиск по номенклатуре товаров?

Опиши подходы к решению данной задачи на языке python3

или

мне нужно на сайте отображать прогресс исполнения пайплайна обработки на сервере по шагам.
какой способ есть выводить на сайте уведомления, приходящие с сервера?

и т.д.

Таким образом вы в общем-то в состоянии написать прототип почти любого сервиса, обладая базовыми навыками программирования.

Обучение

Модели могут вам прекрасно объяснять что-то. Например вы не сильны в Javascript, т.к. видите его раз в год по рабочим задачам, а плотно занимались с ним 10 лет назад в универе на лабах. Используя модели вы можете отлично отвечать для себя на самые разные вопросы

  • как в javascript сделать обновление страницы если не удалось установить подключение к потоку событий?
  • объясни что такое BERTscore
  • Как устроен протокол wsgi. Объясни по шагам с примерами
  • и т.д.

Можно показывать куски кода и просить из объяснить. Например:

что означает в CSS
.reason_toggle:checked + .reason_content-visible + .reason_content-hidden {
    display: block;
}

или

почему такой код на python3 не меняет значение переменной в модуле

from module1.submodule import stat, call_stat
call_stat = True

а такой код меняет
module1.submodule.call_stat = True

в чем причина?

или

как раскрывается в python3 @rate_limiter(5) - как это написать без значка декоратора?

Вы можете просить модель реализовать вам конкретный алгоритм, про который вы смутно представляете что он должен сущетвовать.

напиши алгоритм экстрактивной суммаризации на основе вхождения общих слов

и когда модель вам напишет свои мысли вы можете с ней уточнять реализацию задачи, например

а если я хочу использовать матрицу схожести предложений? когда близость предложений вычисляется как количество общих слов, деленное на объединение слов предложений. И оставлять предложения которые имеют наибольший вес как схожие с другие по словам в больше степени?
какой тут правильный алгоритм?

И так в диалоге картина для вас проясняется. Это отлично работает, когда вы помните что-то смутно и гуглить это придется часа 2, тк вы забыли в каком источнике видели, какой правильный поисковый запрос сформулировать и т.д. С моделью эта ситуация разрешается обычно минут за 10-15 вместо 2-3 часов.

Написание отдельной функции

Тут вы просите написать отдельную функцию или часть функции. Например ЛЛМ хорошо пишут и дебажат регулярки, в отличие от людей. Например можно спрашивать так

напиши регулярное выражение на python чтобы выделить текст вначале строки написанный большими буквами
например для АВАРИЙНО-СПАСАТЕЛЬНОЕ ОБСЛУЖИВАНИЕ ОРГАНИЗАЦИЙ ПО ДОБЫЧЕ (ПЕРЕРАБОТКЕ) УГЛЯ (ГОРЮЧИХ СЛАНЦЕВ) комплекс мероприятий, направленных на осуществление профилактических работ по противоаварийной и противопожарной 
надо выделить АВАРИЙНО-СПАСАТЕЛЬНОЕ ОБСЛУЖИВАНИЕ ОРГАНИЗАЦИЙ ПО ДОБЫЧЕ (ПЕРЕРАБОТКЕ) УГЛЯ (ГОРЮЧИХ СЛАНЦЕВ)

или

почему не срабатывает регулярное выражение на python3
t = 'людей. На первый '
re.sub(r'([a-zа-яё]{2,}\s*[.?!]+)\s*([A-ZА-ЯЁ])', '\g<1><sep>\g<2>', t)
оставляет текст как есть, тогда как должно быть 'людей.<sep>На первый '

Вы можете просить систему написать функцию целиком. И прекрасно то, что модель владеет полным стеком технологий. Например вы можете попросить что-то сверстать

сверстай блок который отображает текст и часть текста скрыта. 
в конце первого текста стоит элемент, например якорная ссылка, при клике на которую оторажается второй текст.
а при повтрном клике второй текст скрывается снова.

таких элементов будет много, целый список и у каждого свой скрытый текст.

как это сделать без javascript, только на css

или

у меня есть блок 
<div>
<p class="part">text1</p>
<p class="part">text2</p>
<p class="part">text3</p>
</div>

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

 только средствами css без javascript

или

document.addEventListener('DOMContentLoaded', continueSearch);

я хочу запускать такую функцию при загрузке страницы.
я верно написал?

или

напиши на javascript отправку данных на сервер методом пост

function(){
    var text = document.getElementById("search");

}

допиши функцию отправлять надо на endpoint /search

Рефакторинг

Вы можете попросить переписать кусок кода, обяснив в каком стиле это нужно сделать. Например, если вы, как и я, не очень дружите с javascript, то вполне можете писать свой некрасивый и корявый код как в 90-е, а потом просить переписать код на современный и лаконичный TypeScript. Или наоборот не очень понятные вам примеры на TypeScript с кучей функциональщины и коллбэков попросить переписать на чистом javascript по рабоче-крестьянски и с комментрариями.

Просить модель оптимизировать или откомментировать ваш код - хорошо и полезно.

Какого размера кусок кода подавать в промпт - в целом можно и довольно много. Контекст современных LLM порядка 32 тыс. токенов, это более 100 тыс символов. Понятно, что большой контекст может запутывать модель и качество снижается, но пару страниц кода вполне себе подавать можно и модели работают с этим корректно.

Можно например попросить модель переписать предложенный код или отдельную большую функцию в более тестируемом виде. Можно просить упростить код и т.д.

Когда вы подаете в промпт код, то можно выделять кода тремя тиклями: ``` - заключать код в такие тройные обратные кавычки. Это стандарт разметки маркдаун и модели очень хорошо с ним знакомы: ```some code here...```

исправь функцию на javascript

сейчас она работает со ссылками вида [link]
надо чтобы она начала работать со ссылками вида [link|link_text] и превращала их в ссылки вида <a href="link">[link_text]</a>

function setLinks(text) {
    text = text.replace(/\[([^\]]+?)\]/g, function(match, p1) {
        let links = p1.split(',').map(link => link.trim());
        let linksHTML = links.map(link => '<a target="_blank" href="' + link + '">' + link + '</a>').join(' ');
        return linksHTML;
    });

    return text;
}

Написание тестов

Вы можете подать целый модуль на 1000 строк кода и попросить покрыть его тестами. И модель это качественно сделает.

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

Вам останется поместить написанный код в отдельный модуль, немного приладив его по месту.

Такое написание тестов экономит часы, далая работу по написанию тестов эффективнее в 2-3 раза минимум.

Исправление ошибок и дебаг

Вы всегда можете показать модели код функции в которой вылезла ошибка, кинуть баг-трейс ошибки и попросить объяснить что может быть не так. По коду и стек трейсу вы можете просит модель изменить код, чтобы убрать ошибку, можете пробовать объяснить почему получается ошибка. Если код предложенный моделью, вы снова можете ей кинуть код и стек трейс и спросить, почему не работает. И так в 2-3-5 итераций вы вполне можете вместе с моделью пофиксить баг.

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

Пример

Traceback (most recent call last):
  File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
  File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.10/threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "/home/alex/project/api/web_app/models.py", line 66, in read_pipe
    self.run()
  File "/usr/lib/python3.10/threading.py", line 953, in run
    data = pipe.read()
  File "/usr/lib/python3.10/codecs.py", line 322, in decode
    self._target(*self._args, **self._kwargs)
  File "/home/alex/project/ali/web_app/models.py", line 66, in read_pipe
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 8191: invalid continuation byte
    data = pipe.read()
  File "/usr/lib/python3.10/codecs.py", line 322, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb4 in position 0: invalid start byte

почему такая ошибка при чтении из именованного пайпа?

Инфраструктурные задачи

Плюс LLMок в том что они видели огромное количество документации. И вы можете спокойно просить их исправить конфиги nginx, apache, caddy и любого другого инфраструктурного софта. Они отлично ответят на вопрос типа

  • nginx location в точности равно url - как записать?
  • вы можете кинуть ему текущий конфиг и спросить "почему не покзываются файлы из директори при пути /data/" - и он детально разберет что не так может быть в конфиге
  • вы можете кинуть ему лог ошибок и спросить, что может быть не так "вот лог обновления сертификата lets encrypt ... почему сейчас не обновилось?"

Поэтому вопросы докеров, сетевой инфраструктуры, сборки образов и много чего еще перестали быть сложными, даже если вы просто фронтендер, но вам надо срочно где-то что-то развернуть.

Резюме

Любите общаться с моделями. Модели очень умные и эрудированные собеседники, гораздо эрудированее вас. Они прочитали документацию ко всему популярному софту, видели все основные формуы с вопросами-ответами по теме.

Как и вы модели могут ошибаться или не очень хорошо вас понимать. Но на это у вас и голова, чтобы задавать вопросы, хотеть докопаться до ответов и проверять написанное.

Для успеха достаточно - уметь писать и более менее понимать написанное, ну если не понимаете, всегда можно спросить модель. А если модель ошиблась и оно не работает, всегда можно спросить модель почему оно не работает и попросить исправить.

А если совсем страшно и не понятно с чего начать - опишите задачу и спросите модель с чего начать.