В последние 10 месяцев я активно использую нейросети для решения повседневных рабочих задач. Кейсов накопилось много, и я хочу начать делиться ими.
Сегодня будет первая публикация из цикла, а найти все можно будет по этим тегам:
➡️ #llm_для_работы - кейсы из моей рабочей практики, как LLM были полезны в команде ML-разработчиков и на продуктах финтеха
➡️ #llm_для_жизни - кейсы из жизни, когда использование помогало решать личные вопросы
Следующий кейс будет полезен всем, кто связан с разработкой. Речь пойдет о написании юнит-тестов на Python ⚙️.
Одна из задач, с которой я столкнулся, — написание регулярных выражений (регулярок) и тестов к ним. Если вы хоть раз пытались написать сложную регулярку, то знаете, что это может быть настоящим квестом. Нужно учесть множество нюансов, синтаксис, а еще убедиться, что выражение работает на всех возможных входных данных.
Я решил доверить эту задачу нейросети — Claude 3.5 Sonnet. После нескольких итераций и уточнений получил рабочую регулярку, которая делала именно то, что нужно. Но на этом история не закончилась.
# что я хотел найти:
# из строки: "последовательность запуска алгоритмов: [(1, 2) >> 3]"
# выделить: [(1, 2) >> 3]
# Регулярка по мнению Claude 3.5 sonnet
pattern = r'\[(?:\s*\((?:\d+(?:\s*,\s*\(\s*\d+(?:\s*,\s*\d+)*\s*\))*(?:\s*,\s*\d+)*)\)|\s*\d+)(?:\s*>>\s*(?:\((?:\d+(?:\s*,\s*\(\s*\d+(?:\s*,\s*\d+)*\s*\))*(?:\s*,\s*\d+)*)\)|\d+))*\s*\]'
Даже если регулярка работает на первых тестовых данных, это не гарантирует, что она справится со всеми возможными сценариями. Здесь на помощь приходят юнит-тесты. Они помогают проверить, что ваш код (или регулярка) работает корректно в разных ситуациях, включая краевые случаи (edge cases).
Однако придумывать такие тесты вручную — это долго и не всегда эффективно. Можно что-то упустить, особенно если проект большой и сложный. И тут я подумал: а почему бы не поручить это нейросети?
Я начал с того, что написал три базовых теста (используя few-shot технику), чтобы задать контекст. Затем попросил Claude сгенерировать дополнительные тесты. Результат меня впечатлил: нейросеть не только предложила еще десяток тестов, но и добавила краевые случаи, которые я сам мог бы и не учесть.
# мои few-shot примеры
test_cases_user = [
["алгоритмов: [1 >> 2 >> 3] этом", "1 >> 2 >> 3"],
["алгоритмов: [(1, 2) >> 3] этом", "(1, 2) >> 3"],
["алгоритмов: [(1, 2) >> (3, 4)] этом", "(1, 2) >> (3, 4)"],
["алгоритмов: [(1, 2, 3) >> (5, 6) >> 7] этом", "(1, 2, 3) >> (5, 6) >> 7"],
]
# ответ Claude 3.5 sonnet
test_cases_gpt = [
["[(1) >> (2)]", "(1) >> (2)"],
["[(1, 2)]", "(1, 2)"],
["[1 >> 2]", "1 >> 2"],
["[(1,2,3)>>4>> (5,6)]", "(1,2,3)>>4>> (5,6)"],
["[1 >> (2, 3) >> (4, 5, 6)]", "1 >> (2, 3) >> (4, 5, 6)"],
["алгоритмов: [(100, 200, 300) >> 400 >> (500, 600)] этом", "(100, 200, 300) >> 400 >> (500, 600)"],
["алгоритмов: [1000 >> (2000, 3000) >> 4000 >> (5000, 6000, 7000)] этом", "1000 >> (2000, 3000) >> 4000 >> (5000, 6000, 7000)"],
["алгоритмов: [(1) >> (2) >> (3) >> (4)] этом", "(1) >> (2) >> (3) >> (4)"],
["алгоритмов: [1 >> 2] этом", "1 >> 2"],
["алгоритмов: [(1, 2)] этом", "(1, 2)"],
["алгоритмов: [1] этом", "1"],
["алгоритмов: [(1,2,3,4,5,6,7,8,9,10) >> 11] этом", "(1,2,3,4,5,6,7,8,9,10) >> 11"],
["алгоритмов: [(1, 2) >> (3, (3, 3))] этом", "(1, 2) >> (3, (3, 3))"],
]
Вот несколько ключевых выводов, которые я для себя сделал:
1.
Экономия времени: нейросети позволяют быстро генерировать большое количество тестов, что особенно полезно при работе с большими проектами.
2.
Улучшение качества тестов: нейросети предлагают краевые случаи, которые разработчик может упустить.
3.
Дополнительная проверка: даже если тесты от нейросети не всегда идеальны, они служат хорошей отправной точкой для дальнейшей доработки.
✏️ Этот опыт очень интересен, особенно на фоне новостей о появлении различных коробочных решений, которые работают схожим образом, но с большей автономностью. (
тык 1,
тык 2)