Я очень рад поделиться этой статьей со всеми вами. Первоначально написанный Дэвидом Кроушоу, нам любезно разрешили перепечатать его здесь.
В этой статье представлен краткий обзор моего годового путешествия по изучению генеративных моделей в программировании. Речь шла не только о том, чтобы сидеть сложа руки и наблюдать; Я активно искал возможности применять модели изучения языка (LLM) во время программирования, чтобы получить понимание. Теперь я регулярно включаю программы LLM в свой рабочий процесс, считая их полезными для моей производительности. Попытка написать код без них вызывает дискомфорт.
За время своего путешествия я обнаружил распространенные задачи, которые можно автоматизировать, и мы находимся в процессе создания специального инструмента для программирования на Go под названием Sketch.dev. На данном этапе дела идут гладко и позитивно.
Фон
Будучи поклонником технологий, мое любопытство часто побуждает меня исследовать новые технологии. Увлечение моделями большого языка (LLM) зажгло во мне искру, заставив меня жаждать раскрыть их практическое применение. Есть что-то захватывающее в технологии, которая может, по крайней мере иногда, давать продуманные ответы на сложные запросы. Но что меня по-настоящему волнует, так это то, что компьютер пытается создать фрагмент кода в соответствии с инструкциями и добиться ощутимого прогресса в этом процессе.
Что касается технологических преобразований, то то, что меня больше всего впечатляет, произошло в 1995 году, когда мы настроили мою локальную сеть (LAN) с маршрутом по умолчанию. Я заменил компьютер в другой комнате, на котором работал Trumpet Winsock, на компьютер, способный маршрутизировать коммутируемое соединение, и внезапно Интернет оказался у меня под рукой. Постоянный доступ к Интернету был ошеломляющим и ощущался как взгляд в будущее. Вероятно, это имело для меня большее значение, чем для многих, кто был в сети дольше из-за связей с университетом, поскольку меня толкнули прямо на территорию высоких технологий Интернета: веб-браузеры, JPEG и обширное онлайн-сообщество. Доступ к мощной модели большого языка (LLM) очень похож на этот опыт.
Будучи технически подкованным человеком, я часто задавался вопросом, может ли инструмент, способный давать наиболее точные результаты, повысить мою повседневную продуктивность. И ответ кажется утвердительным: генеративные модели оказываются весьма полезными в моих усилиях по программированию. Это путешествие не обошлось без проблем. Мой неослабевающий интерес к этой новой технологии стал движущей силой ее понимания, поэтому я сочувствую коллегам-инженерам, которые считают модели изучения языка «бесполезными». Однако, учитывая количество раз, когда меня спрашивали, как я эффективно их использую, этот пост — моя попытка поделиться своими выводами на данный момент.
Обзор
Я использую LLM в своем повседневном программировании тремя способами:
- Автозаполнение. Это делает меня более продуктивным, поскольку я выполняю большую часть более очевидной для меня работы. Оказывается, нынешнее состояние здесь можно улучшить, но это разговор в другой раз. Для меня даже стандартные продукты, которые можно купить с полки, лучше, чем ничего. Я убедился в этом, попытавшись отказаться от них. Я не мог прожить и недели, не расстраиваясь из-за того, сколько рутинной работы мне пришлось напечатать, прежде чем у меня появилась модель FIM. Это первое место для экспериментов.
- Поиск. Если у меня возникнет вопрос о сложной среде, например: «Как мне сделать кнопку прозрачной в CSS», я получу гораздо лучший ответ, задав любой потребительский LLM — o1, sonnet 3.5 и т. д. — чем используя старомодную поисковую систему в Интернете и пытаюсь проанализировать детали любой страницы, на которую я попадаю. (Иногда LLM ошибается. Как и люди. На днях я надел туфлю на голову и спросил свою двухлетнюю дочь, что она думает о моей шляпе. Она справилась с этим и отругала меня как следует. Я могу сталкивайтесь с тем, что LLM тоже иногда ошибаются.)
- Программирование через чат. Это самое сложное из трех. Именно здесь я получаю наибольшую пользу от программ LLM, но это также беспокоит меня больше всего. Это предполагает многому учиться и корректировать свое программирование, и в принципе мне это не нравится. Чтобы извлечь пользу из чата LLM, требуется как минимум столько же возни, сколько и для того, чтобы научиться использовать логарифмическую линейку, с дополнительным раздражением, поскольку это недетерминированный сервис, который регулярно меняет свое поведение и пользовательский интерфейс. Действительно, долгосрочная цель моей работы — устранить необходимость в программировании с помощью чата, чтобы донести до разработчика возможности этих моделей таким образом, чтобы это не отталкивало. Но на данный момент я посвятил себя постепенному подходу к проблеме, что означает выяснение того, как лучше всего использовать то, что у нас есть, и улучшить это.
Обсуждая искусство кодирования, мне сложно подходить к нему со строго числовой точки зрения из-за его качественной природы. Хотя я не могу предоставить точные данные, мои наблюдения показывают, что примерно за два часа программирования я обычно принимаю более десяти предложений автозаполнения, использую языковую модель (LLM) для задачи, похожей на поиск, по крайней мере один раз, и участвую в чате. сеанс программирования на основе хотя бы один раз.
Остальное — это извлечение пользы из программирования, управляемого через чат.
Зачем вообще использовать чат?
Я хотел бы убедить сомневающихся среди вас в преимуществах, которые я получаю от программирования на основе чата. Значительная часть его ценности заключается в том, что к концу дня я четко понимаю, что нужно закодировать, могу это сформулировать, но не хватает сил создать новый файл, начать печатать, а затем искать нужное. необходимые библиотеки. (Поскольку я являюсь ранней пташкой, у меня это обычно происходит после 11 часов утра, хотя это также может произойти в любое время, когда я переключаю контекст на другой язык/фреймворк и т. д.) На этом этапе моего программирования вступают в действие модели изучения языка (LLM). Они предоставляют предварительный проект с некоторыми инновационными идеями и многими необходимыми мне зависимостями – и часто с некоторыми ошибками. Интересно, что Я считаю, что исправлять эти ошибки зачастую менее сложно, чем начинать с нуля.
Кажется, что программирование на основе чата может не подойти вашему стилю, учитывая разнообразный и динамичный характер вашей работы по программированию. В первую очередь вы сосредоточены на разработке продуктов, что включает в себя создание программного обеспечения для пользователей с надежным интерфейсом. Это означает, что вы часто создаете, отбрасываете и перемещаетесь между разными средами. В некоторые дни вы глубоко поглощены TypeScript, а в другие дни вы погружаетесь в Go. Недавно вы углубились в кодовую базу C++, чтобы изучить одну идею, а также изучали формат событий на стороне сервера HTTP. Ваша работа довольно разрознена и часто требует частого вспоминания и повторного изучения.
Если вы в основном тратите время на обеспечение устойчивости вашего криптографического алгоритма к атакам по времени, а не на само кодирование, то идеи, представленные здесь, могут оказаться для вас бесполезными.
LLM в чате лучше всего справляются с вопросами в стиле экзамена.
Предоставьте студенту магистра права (LLM) четкую цель — составить комплексный и организованный пакет проверки кода. Предоставьте им все необходимые справочные материалы, необходимые для выполнения этой задачи. LLM должен иметь возможность адаптировать свою работу по мере того, как вы задаете вопросы или предоставляете дополнительную информацию, гарантируя, что конечный продукт будет соответствовать вашим ожиданиям. По сути, задача включает в себя составление исчерпывающего пакета проверки кода, адаптированного к вашим конкретным потребностям.
- Избегайте создания настолько сложных и двусмысленных ситуаций, в которых LLM запутается и даст плохие результаты. Вот почему я не добился большого успеха в чате внутри своей IDE. В моем рабочем пространстве часто беспорядок, репозиторий, над которым я работаю, по умолчанию слишком велик и наполнен отвлекающими факторами. Одна вещь, в которой люди кажутся намного лучше, чем LLM (по состоянию на январь 2025 года), — это не отвлекаться. Вот почему я до сих пор использую LLM через веб-браузер — мне нужен чистый лист, на котором можно создать четко сформулированный запрос.
- Попросите работу, которую легко проверить. Ваша работа как программиста, использующего LLM, состоит в том, чтобы прочитать код, который он создает, подумать о нем и решить, хороша ли работа. Вы можете попросить магистра права сделать то, о чем никогда бы не попросили человека. «Перепишите все ваши новые тесты, введя <промежуточную концепцию, призванную облегчить чтение тестов>» — ужасная вещь, которую можно спросить у человека; у вас будут дни напряженных споров о том, стоит ли стоимость работы выгоды. LLM сделает это за 60 секунд и не заставит вас бороться за это. Воспользуйтесь тем, что работы по переделке обходятся крайне дешево.
Оптимальная задача для LLM включает ситуации, когда ему необходимо широко использовать многочисленные общие библиотеки (количество которых превышает объем памяти человека, что требует от него проведения мини-исследовательских проектов от вашего имени). Эта работа должна основываться на интерфейсе, который вы разработали или который можно быстро разработать и который вы можете легко проверить как логичный. Кроме того, LLM способен писать тестируемый и читаемый код, и в некоторых случаях вам может потребоваться выбрать для него библиотеку, если вам нужно что-то необычное (хотя его умение работать с открытым исходным кодом делает это менее сложной задачей).
Очень важно прогнать код LLM через компилятор, выполнить тесты и только потом приступать к его чтению. Иногда их выходные данные не компилируются, что я нахожу удивительно похожим на человеческие ошибки — я часто думаю: «Это мог быть я, если бы я просто допустил ошибку». Однако первоклассные студенты LLM умеют быстро исправлять свои ошибки; обычно все, что вам нужно, это поделиться в чате сообщением об ошибке компилятора или сбое теста, и они оперативно исправят код.
Дополнительная структура кода обходится намного дешевле.
В нашей повседневной деятельности мы часто сталкиваемся с неясным выбором между расходами на написание кода, его чтение и его пересмотр или рефакторинг. Чтобы проиллюстрировать это, давайте в качестве примера рассмотрим границы пакетов Go. Стандартная библиотека предлагает пакет под названием «net/http», который включает в себя основные типы для обработки кодирования проводного формата, типов MIME и т. д. Этот пакет содержит как HTTP-клиент, так и HTTP-сервер. Это должна быть одна посылка или несколько? Этот вопрос может вызвать бурные дебаты, и я не уверен, что сегодня существует однозначный ответ. Несмотря на его длительное использование (15 лет), я по-прежнему не уверен, даст ли реорганизация этого пакета на более мелкие пакеты лучшие результаты.
Преимущества более крупного пакета многочисленны, такие как централизованная документация для пользователей, более простое начальное кодирование, более простой рефакторинг и возможность совместного использования вспомогательного кода без необходимости создавать для них комплексные интерфейсы (что может потребовать извлечения основных типов пакета в другой субпакет). Однако есть и некоторые недостатки. Например, в более крупном пакете может быть сложнее ориентироваться, поскольку он содержит множество различных компонентов (например, они теряются в реализации клиента net/http и случайно попадают в серверный код), или его может стать сложно использовать из-за в нем переизбыток функций. Например, я столкнулся с кодовой базой, которая использует библиотеку C для некоторых фундаментальных типов, но требует, чтобы части кодовой базы распространялись в виде двоичного файла на различные платформы, которым библиотека C строго не нужна. Чтобы избежать сложностей с cgo в многоплатформенном двоичном файле, мы создали больше пакетов в кодовой базе, чтобы изолировать использование библиотеки C.
В данном случае однозначного решения нет. Вместо этого задачи, которые может выполнять инженер (начальные и постоянные), можно рассматривать как баланс или выбор. Законы и постановления (LLM) существенно влияют на этот выбор.
- Поскольку студенты LLM лучше справляются с вопросами экзаменационного типа, большее количество пакетов меньшего размера упрощает предоставление полного, но изолированного контекста для части работы. Это справедливо и для людей, поэтому мы вообще используем пакеты, но мы жертвуем размером пакета дополнительным вводом/подготовкой/заполнением, чтобы сделать код более читаемым. Поскольку LLM одновременно выполняет большую часть этой дополнительной работы и получает от нее выгоду, компромисс меняется. (В качестве бонуса мы, люди, получаем более читаемый код!)
- Меньшие и более многочисленные пакеты можно скомпилировать и протестировать независимо от несвязанного кода. Это полезно для цикла разработки LLM, поскольку означает, что изменения можно скомпилировать и протестировать до рефакторинга других зависимых пакетов, а пакет имеет более простую среду тестирования.
Пример
Позвольте мне привести пример, чтобы объединить несколько обсуждаемых идей:
Напишите пробоотборник резервуара для квартилей чисел с плавающей запятой.
Первоначально я бы структурировал свой проект с помощью пакета под названием «streamstat», содержащего несколько алгоритмов, каждый из которых находился в отдельных файлах. Однако теперь я предпочитаю изолировать этот единственный алгоритм в отдельный пакет. Другие подобные или варианты алгоритмов могут быть сгруппированы отдельно в разные пакеты. Этот подход, похоже, разделяют и другие, о чем свидетельствует пакет квантилей с открытым исходным кодом, который имеет аналогичную структуру.
Двигаясь дальше, давайте обсудим результаты LLM. При первой попытке все кажется удовлетворительным. Этот запрос, включая спецификации языка программирования Go, побудил меня создать quartile_sampler.go.
// QuartileSampler maintains a reservoir sample to estimate quartiles of a stream
// of float64 values. It uses reservoir sampling to maintain a representative
// sample when processing large streams of data.
type QuartileSampler struct {
reservoir []float64
seen int
maxSize int
rng *rand.Rand
}
// NewQuartileSampler creates a new sampler that maintains up to maxSize samples.
// A larger maxSize provides more accurate estimates but uses more memory.
func NewQuartileSampler(maxSize int) *QuartileSampler { … }
Основной интерфейс тоже хорош:
// Add adds a new value to the sampler.
func (qs *QuartileSampler) Add(value float64) { … }
// Quartiles returns the estimated 25th, 50th (median), and 75th percentiles
// of the data seen so far. Returns (0,0,0) if no data has been added.
func (qs *QuartileSampler) Quartiles (q1, median, q3 float64) {
if len(qs.reservoir) == 0 {
return 0, 0, 0
}
// Make a copy to avoid modifying the reservoir
sorted := make([]float64, len(qs.reservoir))
copy(sorted, qs.reservoir)
slices.Sort(sorted)
n := len(sorted)
q1 = percentile(sorted, 0.25)
median = percentile(sorted, 0.50)
q3 = percentile(sorted, 0.75)
return q1, median, q3
}
Большой! Также есть тесты.
В качестве примечания: возможно, здесь пора остановиться. Иногда я использую кодеген LLM в качестве специального инструмента поиска. Например, когда меня заинтриговал отбор проб из резервуара, но я хочу понаблюдать за его применением в необычных условиях, таких как отбор проб во временном окне. Вместо проведения традиционного обзора литературы я мог бы изменить свое предложение для реализации, которая отслеживает свежесть (или даже попросить его включить ссылки в комментарии, которые я затем могу проверить, чтобы убедиться, что это не фабрикация информации или доступны ли заслуживающие доверия исследования). .
Часто я просматриваю фрагменты кода в течение примерно 60 секунд, замечаю хитрый прием, который раньше не приходил мне в голову, только чтобы отбросить его и перезапустить процесс. Теперь я знаю, что такие трюки возможны. Однако это демонстрирует сложность оценки ценности, создаваемой моделями большого языка (LLM). Хотя они могут создавать неоптимальный или невозможный код, застревать в повторяющихся шаблонах и тратить мое время, они также могут сэкономить мне значительное время, привлекая мое внимание к соответствующей информации, о которой я не знал.
Вернемся к нашему кодированию. Удивительно, но первый вывод кода не удалось скомпилировать. В процессе создания функции Quartiles я наткнулся на следующую строчку:
n := len(sorted)
Как исследователь, я заметил, что определение слова «отсортировано», приведенное несколькими строками назад, похоже, представляет собой срезанную переменную. Однако в моем текущем анализе эта переменная, похоже, не имеет используемого значения. Следовательно, когда я использую такие инструменты, как gopls, или запускаю go build, они сразу отмечают ненужное определение из-за его неиспользования.
declared and not used: n
Эту проблему решить просто. При повторном вводе ошибки в модель большого языка (LLM) она автоматически исправляется. Однако, поскольку, прочитав код, я вижу, что могу просто удалить строку напрямую, я предпочитаю делать именно это.
Теперь тесты. Я получил то, что ожидал. В quartile_sampler_test.go:
func TestQuartileSampler(t *testing.T) {
tests := []struct {
name string
data []float64
wantQ1 float64
wantMed float64
wantQ3 float64
epsilon float64 // allowed error for floating point comparison
}{
{
name: "basic sequence",
data: []float64{1, 2, 3, 4, 5, 6, 7},
wantQ1: 2,
wantMed: 4,
wantQ3: 6,
epsilon: 0.1,
},
…
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
qs := NewQuartileSampler(100) // Use large reservoir for accurate testing
for _, v := range tt.data {
qs.Add(v)
}
q1, med, q3 := qs.Quartiles
if math.Abs(q1-tt.wantQ1) > tt.epsilon {
t.Errorf("Q1 = %v, want %v (±%v)", q1, tt.wantQ1, tt.epsilon)
}
if math.Abs(med-tt.wantMed) > tt.epsilon {
t.Errorf("Median = %v, want %v (±%v)", med, tt.wantMed, tt.epsilon)
}
if math.Abs(q3-tt.wantQ3) > tt.epsilon {
t.Errorf("Q3 = %v, want %v (±%v)", q3, tt.wantQ3, tt.epsilon)
}
})
}
}
Именно с такой задачей я бы справился! Чтобы проверить свои результаты, я планирую запустить несколько сценариев, используя альтернативный метод, и записать их прогнозируемые результаты. Однако у этого подхода есть две проблемы.
Насколько я могу судить, изначально LLM не проверял эти цифры, прогоняя их через другую версию программного обеспечения. Вместо этого, похоже, что он сам генерирует цифры, что известно как слабое место в LLM. Таким образом, подобный тест, хотя и логичен для людей, поскольку мы часто полагаемся на данные других инструментов или сами выполняем расчеты, может быть не идеальным при работе с LLM.
Второй вопрос, требующий улучшения, заключается в том, что мы могли бы быть более строгими. Я рад, что мы сейчас находимся на этапе, когда программисты пишут свои собственные тесты, но, похоже, мы не уделяем тестированию такого же усердия, как к нашему производственному коду. Этот компромисс понятен, учитывая временные ограничения. Однако, хотя языковые модели могут и не преуспеть в математических навыках, они с лихвой компенсируют это своим энтузиазмом.
Давайте попросим провести еще лучший тест.
В тестах создайте самую простую и читаемую версию стандартного кода квартиля для фиксированного набора известных значений в массиве. Проведите эту версию и пробоотборник резервуара через эти тестовые сценарии. Убедитесь, что результаты достаточно близки (в пределах допустимой погрешности или эпсилон), выполнив следующие действия:
1. Напишите код сравнения, чтобы проверить, дают ли два подхода схожие результаты, что сделает его адаптируемым для использования в среде нечеткого тестирования.
2. Выполните стандартный код квартиля и пробоотборник резервуара с помощью этих тестовых примеров.
3. Сравните результаты обоих методов, убедившись, что они находятся в пределах допустимой погрешности (эпсилон).
4. Структурируйте код сравнения так, чтобы его можно было использовать в сценарии нечеткого тестирования для будущих целей тестирования.
Это дало нам новый тестовый код:
// referenceQuartiles calculates the exact quartiles for a slice of float64 values
// using linear interpolation, matching the behavior expected from the sampler.
func referenceQuartiles(data []float64) (q1, median, q3 float64) { … }
// compareQuartiles checks if two sets of quartiles are within epsilon of each other.
// Returns true if they match within the tolerance, false otherwise.
func compareQuartiles(q1a, meda, q3a, q1b, medb, q3b, epsilon float64) bool { … }
// checkQuartiles is a test helper that compares sampler output against the reference
// implementation and reports any differences.
func checkQuartiles(t *testing.T, data []float64, epsilon float64) {
t.Helper
// Get reference values
wantQ1, wantMed, wantQ3 := referenceQuartiles(data)
// Get sampler values using a large reservoir for accuracy
qs := NewQuartileSampler(1000)
for _, v := range data {
qs.Add(v)
}
gotQ1, gotMed, gotQ3 := qs.Quartiles
if !compareQuartiles(gotQ1, gotMed, gotQ3, wantQ1, wantMed, wantQ3, epsilon) {
t.Errorf("Quartiles mismatch:\ngot (q1=%v, med=%v, q3=%v)\nwant (q1=%v, med=%v, q3=%v)\nepsilon=%v",
gotQ1, gotMed, gotQ3, wantQ1, wantMed, wantQ3, epsilon)
}
}
Исходный тест выше был переработан для использования checkQuartiles, и у нас есть кое-что новое:
func FuzzQuartileSampler(f *testing.F) {
// Add some seed corpus
f.Add([]float64{1, 2, 3, 4, 5})
f.Fuzz(func(t *testing.T, data []float64) {
// Use a larger epsilon for fuzzing since we might get more extreme values
checkQuartiles(t, data, 0.2)
})
}
Это весело, потому что это неправильно. Мой запущенный инструмент gopls
сразу говорит:
fuzzing arguments can only have the following types:
string, bool, float32, float64,
int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64,
[]byte
Как исследователь, я обнаружил, что повторное внесение обнаруженной ошибки в LLM позволяет заново выполнить фазз-тест. Этот тест построен на основе функции func(t *testing.T, data []byte)
, которая использует math.Float64frombits
для извлечения чисел с плавающей запятой из среза данных. . Подобные взаимодействия предполагают возможность автоматизации обратной связи с инструментами; все, что требовалось, — это четкое сообщение об ошибке, чтобы добиться существенного прогресса в практическом применении. В данном случае мое вмешательство не потребовалось.
За последние несколько недель просмотр моих журналов чата LLM (правда, не являющийся тщательным статистическим анализом) показывает, что более чем в 80% случаев, когда возникает ошибка инструмента, LLM часто добивается значительного прогресса, не требуя от меня каких-либо дополнительных данных. Примерно в половине случаев он даже полностью решает проблему самостоятельно, без какого-либо существенного участия с моей стороны. По сути, в таких случаях я действую как посланник.
Куда мы идем? Лучшие тесты, может быть, даже меньше СУХИХ
Примерно 25 лет назад возникло движение в области программирования, основанное на концепции «избегать повторения». Однако, как и в случае со многими краткими принципами, которые преподают студентам университетов, этой идее иногда придавали слишком большое значение. Стоимость абстрагирования кода для повторного использования значительна; это требует изучения промежуточных абстракций и добавления функций, чтобы сделать повторно используемый код максимально универсальным, что часто заставляет нас полагаться на библиотеки, наполненные ненужными, отвлекающими функциями.
За последние полтора десятилетия практика кодирования стала более сбалансированной: программисты поняли, что зачастую разумнее воссоздать концепцию, а не делиться ее реализацией, когда затраты на это превышают затраты на создание и поддержку отдельных кодов. В обзорах кода вы редко встретите комментарии типа «Это того не стоит, разделите реализации». (И это хорошо, поскольку никто не ценит такую обратную связь после того, как приложил все усилия.) Программисты становятся все более умелыми в принятии обоснованных решений о компромиссах.
В настоящее время баланс сместился таким образом, что создание обширных тестов стало проще. С помощью модели изучения языка (LLM) вы можете реализовать нечеткий тест, адаптированный к вашим потребностям, на тщательную разработку которого у вас, возможно, не было времени в прошлом. Поскольку LLM не требует постоянного рассмотрения выбора других задач, таких как устранение очередной ошибки в системе отслеживания проблем, вы можете потратить больше времени на то, чтобы сделать тесты простыми для понимания и эффективными. Следовательно, этот сдвиг благоприятствует более специализированным реализациям.
Я ожидаю, что эта проблема будет наиболее очевидной в области адаптеров REST API для конкретного языка. API большинства крупных компаний сопровождаются множеством таких оболочек, часто низкого качества, написанных не для какой-то конкретной цели, а скорее для того, чтобы охватить каждую сложную деталь API в обширном и запутанном интерфейсе. Даже если все сделано эффективно, я считаю более практичным обратиться к документации REST (обычно это набор команд Curl) и разработать специфичную для языка оболочку для 1% API, который действительно важен для меня. Такой подход уменьшает объем знаний API, необходимых на начальном этапе, а также сводит к минимуму сложность, с которой будущие программисты (включая меня) сталкиваются при чтении кода.
В своих текущих проектах в Sketch.dev я разработал оболочку Gemini API с использованием языка программирования Go. Хотя существующая оболочка Go была тщательно создана экспертами языка, для ее полного понимания требуется основательное чтение: она довольно подробная и всеобъемлющая.
$ go doc -all genai | wc -l
1155
Первоначально мой простой сценарий включал примерно 200 строк кода, включающих один метод и три различных типа. Чтение всего сценария занимает около 20% усилий, необходимых для прочтения документации официального пакета. Изучив его внутреннюю работу, вы обнаружите, что он служит оболочкой для другой обширной реализации, которая в основном генерируется автоматически и включает protos, grpc и другие связанные компоненты. Однако моя цель довольно проста: мне просто нужно отправить запрос cURL и проанализировать полученный объект JSON.
В конечном итоге наступает этап проекта, на котором Gemini служит основой всего приложения, на котором используются почти все функции. Кроме того, использование gRPC дополняет систему телеметрии, которая уже существует в вашей организации, и было бы полезно использовать обширную официальную оболочку. Однако в большинстве случаев это требует значительно больше усилий из-за того, что в любой момент нам часто требуется лишь небольшая часть API. Таким образом, пользовательские клиенты, в основном разработанные с помощью графического процессора, как правило, гораздо более эффективны при выполнении задач.
На мой взгляд, мы движемся в будущее, в котором мы увидим рост узкоспециализированного кода, а не широко используемых обобщенных пакетов. Это также приведет к более разборчивым тестовым примерам. Повторно используемый код останется ценным, но он будет оптимально использоваться за счет разработки небольших надежных интерфейсов. При эффективном применении этот подход может привести к улучшению качества программного обеспечения, хотя изначально могут быть некоторые случаи использования программного обеспечения низкого качества. В конечном счете, я ожидаю, что общая тенденция будет направлена на улучшение программного обеспечения с точки зрения действительно важных показателей.
Автоматизация этих наблюдений: Sketch.dev
Как программист, я, естественно, хочу, чтобы компьютеры выполняли за меня задачи. Но когда дело доходит до извлечения полезной информации из больших языковых моделей (LLM), это кажется непростой задачей. Как компьютер может эффективно выполнить эту задачу?
Более эффективный подход к решению проблем — не делать широких предположений. Вместо этого сначала решите конкретные проблемы, а затем постепенно расширяйте сферу охвата. Например, вместо того, чтобы создавать универсальный пользовательский интерфейс для программирования чатов, который превосходно работает как на COBOL, так и на Haskell, лучше сосредоточиться на одной среде программирования. Поскольку мой основной язык программирования — Go, я рассматриваю решение, специально разработанное для программистов Go.
- Что-то вроде игровой площадки Go, построенной на редактировании пакета и тестах.
- Интерфейс чата в редактируемом коде
- Небольшая среда UNIX, в которой мы можем запустить go get и go test.
- интеграция goimports
- интеграция с gopls
- Автоматическая обратная связь с моделью: при редактировании модели выполните команду «получить», «создать», «тестировать», оставить отзыв об отсутствующих пакетах, ошибках компилятора, неудачных тестах модели, чтобы попытаться исправить их автоматически.
Некоторые из нас создали ранний прототип этого: Sketch.dev.
Цель состоит не в том, чтобы функционировать как «веб-IDE», а скорее в том, чтобы задаться вопросом, соответствует ли программирование на основе чата традиционному определению интегрированной среды разработки (IDE). Видите ли, IDE — это больше, чем просто набор инструментов; это тщательно созданное пространство, предназначенное для разработчиков. Это среда, в которой я могу контролировать ход работы. Я не хочу, чтобы языковая модель (LLM) случайным образом генерировала первоначальный вариант в моей текущей ветке проекта. Хотя LLM — это инструмент для разработчиков, для эффективного функционирования и получения обратной связи, необходимой для оптимальной работы, требуется собственная специализированная среда.
Проще говоря, мы интегрировали goimport в Sketch не для использования человеком, а для того, чтобы сделать код Go более совместимым с автоматическими сигналами, которые помогают компилятору выдавать более точные сообщения об ошибках модели обучения языку (LLM), работающей с ним. По сути, вы можете рассматривать Sketch.dev как «интегрированную среду разработки Go (IDE), предназначенную для LLM.
Эта недавно разработанная работа далека от завершения, осталось несколько важных задач, таких как интеграция git для управления существующими пакетами, их редактирование и размещение изменений в ветке. Кроме того, нам необходимо усовершенствовать нашу систему обратной связи по тестированию и улучшить управление консолью. Наш текущий подход предполагает изучение и тонкую настройку среды, адаптированной для конкретной ниши программирования, полагая, что она даст превосходные результаты по сравнению с универсальным инструментом.
Дэвид Кроушоу является одним из первоначальных создателей (ранее занимавшим должность технического директора) в компании Tailscale, проживает в районе залива Сан-Франциско и в настоящее время занимается разработкой Sketch.dev. Имея опыт программирования на протяжении трех десятилетий, он с нетерпением ждет еще трех десятилетий программирования.
Смотрите также
- 7 лучших чехлов для Apple iPhone 16 Pro Max 2024 года
- Обзор саундбара LG S95TR: наконец-то хорошо
- Huawei Watch GT 5 против GT 4: стоит ли обновлять свое носимое устройство?
- Наконец-то я нашел утилиту для игрового ноутбука, которую действительно стоит использовать
- 5 игровых мышей, которые стоит купить вместо Logitech G Pro X Superlight 2
- Обзор PrivadoVPN: новый бюджетный VPN, которым можно пользоваться бесплатно
- AirPods Max 2 против AirPods Max: в чем разница?
- Обзор настоящих беспроводных наушников Audio-Technica ATH-CKS30TW+
- 8 фильмов ужасов о вторжении в дом, которые заставят вас дважды проверить свои замки
- Обзор Razer Basilisk V3 Pro 35K – то же самое, но лучше
2025-01-09 00:55