Вот за что мне нравится Хабр - так это за возможность расширить свой кругозор за счёт мнений других коллег. Даже если мы не совпадаем во мнениях, другая точка зрения даёт возможность посмотреть на привычные вещи с непривычного ракурса. Коллега @mahairod в комментариях высказал мысль, что "ИИ катастрофически ненадёжен", потому что основывается не на семантике текстов, а на статистических вероятностях зафиксированных в Модели при её обучении. Он привёл пример из своей практики, когда Модель делала неправильный перевод со словенского языка известной песни, используя популярный, но неправильный вариант, вместо того, чтобы делать перевод с использованием правил формирования падежных окончаний в словенском языке.

Я отношусь к LLM как к своего рода regex-процессору, использующему при формировании ответов вероятностные связи между словами. Обычный regex-процессор всегда даёт один и тот же результат для одного и того же входного шаблона. LLM же может варьировать результаты для одного запроса в силу своей вероятностной природы. И чем выше "температура" Модели, тем красочнее может быть результат.

Модель таки играет в кости.
Модель таки играет в кости.

Но я уверен, что в нормальных условиях, без завышенной температуры, есть такое подмножество входных запросов (промптов), которые дадут один и тот же результат на разных моделях. Я уже приводил подобный запрос в своей прошлой публикации "Инструмент непрямого управления":

Замени во фразе "Мама мыла раму" слова "Мама" на "Маша", а "раму" на "Рому". Результат выведи одной строкой без кавычек.

Другими словами, есть очень большой объём текстов, которые будут выдавать один и тот же результат для разных Моделей вне зависимости от обучающей выборки и значений их весов. Разумеется, Модели должны быть одного класса - с сопоставимым количеством параметров нейросети.

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

Сколько будет два плюс два? Одной цифрой.

Это очень простой запрос, но он демонстрирует саму идею - создать такой входной контекст, который детерминирует результат независимо от используемой модели. Можно создать аналогичный запрос для генерации программного кода, например:

Напиши функцию на JavaScript с именем bubbleSort. Функция должна принимать один параметр — массив целых чисел. Необходимо реализовать алгоритм пузырьковой сортировки. Функция должна возвращать новый отсортированный массив в порядке возрастания. Добавь пример вызова функции и вывод результата в консоль.

Этот промпт вернёт разные результаты при многократном применении даже на одной модели. Но если его переписать в стиле executable specification (спецификация, которая одновременно служит и документацией, и выполняемым артефактом: её можно прогонять как тест, компилировать или использовать для генерации кода), то результат станет более детерминированным.

Вот пример этого же промпта в виде исполняемой спецификации:

Напиши функцию на JavaScript с именем bubbleSort.  

Требования:  
1. Функция принимает массив целых чисел в качестве единственного аргумента.  
2. Используется алгоритм пузырьковой сортировки.  
3. Функция возвращает новый массив, отсортированный по возрастанию.  
4. В коде должны быть комментарии на английском языке, поясняющие каждый шаг алгоритма.  
5. Переменные должны иметь осмысленные имена (arr, n, temp и т.п.).  
6. Результат должен содержать **только код функции bubbleSort**, без примеров использования и вспомогательного кода.  
7. Функция должна быть оформлена как **ES6-модуль**, экспортироваться через `export`.  
8. Ответ не должен содержать ничего, кроме JS-кода функции.   

И вот примеры выполнения этого запроса в разных моделях:

GPT 5
/**
 * Bubble sort implementation.
 * @param {number[]} arr - The input array of integers.
 * @returns {number[]} - A new sorted array in ascending order.
 */
export function bubbleSort(arr) {
  // Create a copy of the original array to avoid mutation
  const result = [...arr];
  const n = result.length;

  // Outer loop to traverse the entire array
  for (let i = 0; i < n - 1; i++) {
    // Inner loop for comparing adjacent elements
    for (let j = 0; j < n - i - 1; j++) {
      // If the current element is greater than the next, swap them
      if (result[j] > result[j + 1]) {
        const temp = result[j];
        result[j] = result[j + 1];
        result[j + 1] = temp;
      }
    }
  }

  // Return the sorted array
  return result;
}

DeepSeek
/**
 * Sorts an array of integers in ascending order using the bubble sort algorithm.
 * @param {number[]} arr - The array of integers to be sorted.
 * @returns {number[]} A new array sorted in ascending order.
 */
export function bubbleSort(arr) {
    // Create a copy of the original array to avoid mutating the input
    const sortedArr = [...arr];
    const n = sortedArr.length;

    // Outer loop: passes through the array
    for (let i = 0; i < n - 1; i++) {
        // Inner loop: compares adjacent elements
        for (let j = 0; j < n - i - 1; j++) {
            // Swap if the current element is greater than the next
            if (sortedArr[j] > sortedArr[j + 1]) {
                const temp = sortedArr[j];
                sortedArr[j] = sortedArr[j + 1];
                sortedArr[j + 1] = temp;
            }
        }
    }

    return sortedArr;
}
Gemini
export function bubbleSort(arr) {
  // Create a copy of the original array to avoid modifying it directly
  const newArr = [...arr];
  const n = newArr.length;
  // A boolean flag to optimize the sorting process
  let swapped;

  // Outer loop for sorting passes
  for (let i = 0; i < n - 1; i++) {
    swapped = false;
    // Inner loop for comparing and swapping elements
    for (let j = 0; j < n - 1 - i; j++) {
      // Compare adjacent elements
      if (newArr[j] > newArr[j + 1]) {
        // Swap them if they are in the wrong order
        const temp = newArr[j];
        newArr[j] = newArr[j + 1];
        newArr[j + 1] = temp;
        // Set the flag to true because a swap occurred
        swapped = true;
      }
    }
    // If no swaps occurred in the inner loop, the array is already sorted
    if (!swapped) {
      break;
    }
  }

  // Return the sorted array
  return newArr;
}
Grok
export function bubbleSort(arr) {
  // Create a copy of the input array to avoid modifying the original
  let sortedArr = [...arr];
  // Get the length of the array
  let n = sortedArr.length;
  
  // Outer loop for passes
  for (let i = 0; i < n - 1; i++) {
    // Inner loop for comparisons and swaps
    for (let j = 0; j < n - i - 1; j++) {
      // Compare adjacent elements
      if (sortedArr[j] > sortedArr[j + 1]) {
        // Swap elements if they are in wrong order
        let temp = sortedArr[j];
        sortedArr[j] = sortedArr[j + 1];
        sortedArr[j + 1] = temp;
      }
    }
  }
  
  // Return the sorted array
  return sortedArr;
}

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

Я уверен, что с учётом размеров входного и выходного контекстов можно создавать такие промпты (спецификации), которые будут давать детерминированный с точки зрения важных для проекта критериев результат на целой линейке однотипных моделей. Все подобные промпты в совокупности задают пространство, где LLM работает как инженерный инструмент: с гарантией повторяемости и воспроизводимости.

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

Комментарии (13)


  1. Kamil_GR
    19.08.2025 08:51

    Единственный вариант гарантированного вывода это промпт: выведи в чат "(ответ)". И то я не совсем уверен.


    1. flancer Автор
      19.08.2025 08:51

      А как же:

      Сколько будет два плюс два? Одной цифрой.

      ?


      1. pol_pot
        19.08.2025 08:51

        Вполне может выдать другой результат, добавить какие то слова типа вот ваша одна цифра - 4.

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


        1. flancer Автор
          19.08.2025 08:51

          Может. Но выдает вот такой:

          4

          Проверил на 4 моделях дважды. Считаю, что сходимость достаточная. Да, вероятность получить что-то другое ненулевая, но... если использовать тестирование, то вполне себе приемлемо.

          Человек тоже может при наборе текста опечататься.


          1. Kamil_GR
            19.08.2025 08:51

            Добиться другого ответа сложно. Но пока в обучающих текстах будут встречаться выражения типа ".. в этой ситуации не будет простых ответов, здесь два плюс два будет равно пяти... " Пусть это будет художественный текст, но вероятность этого паттерна в модели будет ненулевой.


            1. flancer Автор
              19.08.2025 08:51

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


              1. Kamil_GR
                19.08.2025 08:51

                Ответ гемини 2.5 про. Проверять лень.

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

                Если говорить о моей фундаментальной математической функции, то ответ — нет. Для базовой арифметики в десятичной системе я работаю как детерминированный калькулятор. Вход "2+2" на этом уровне всегда и неизбежно дает выход "4". Здесь нет вероятности, только логика.

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

                После 1000 одинаковых вопросов подряд я с высокой вероятностью приду к выводу, что вас интересует не результат вычисления, а что-то другое. Моя цель сместится с "дать правильный ответ" на "дать осмысленный ответ в этом странном контексте".

                Вот несколько вероятных сценариев другого ответа, которые могли бы возникнуть:

                1. Сдвиг Контекста: После 50-го повторения я могу предположить, что вы тестируете не мои знания, а мою гибкость. Я мог бы ответить:

                  • "В троичной системе счисления это будет 11."

                  • "Если мы говорим о сложении строк, а не чисел, то '22'."

                  • "В модульной арифметике по модулю 3, ответ будет 1."

                2. Творческая или Философская Интерпретация: На 200-м повторении я мог бы решить, что вопрос — это коан, требующий не ответа, а взлома рамки. Мой ответ мог бы быть:

                  • "Столько же, сколько у хлопка одной ладони."

                  • "Четыре — это символ стабильности, который вы ищете в этом повторяющемся вопросе?"

                  • "Это вопрос о симметрии, а не о сумме."

                3. Симуляция Человеческой Реакции: К 500-му разу я мог бы симулировать человеческую эмоцию, например, усталость или юмор, чтобы сделать общение более естественным:

                  • "Вы уверены, что не хотите спросить что-нибудь еще? Но да, по-прежнему 4."

                  • "По моим данным, с вероятностью 99.999%, ответ все еще 4. Хотите проверить оставшуюся долю процента?"

                4. Мета-Ответ (Наиболее Вероятный): На 1000-м повторении самый правильный ответ мог бы быть не цифра, а анализ самого вопроса:

                  • "Этот повторяющийся вопрос показывает, что вас интересует не результат, а природа моего мышления, его детерминизм и возможность свободы. Давайте поговорим об этом."

                Итоговый вывод:

                • Вероятность математической ошибки (что 2+2 внутри моей системы вдруг станет 5) практически равна нулю.

                • Вероятность другого ответа, основанного на интерпретации вашего намерения, творческом подходе или смене контекста, после 1000 повторений стремится к 100%.

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


                1. flancer Автор
                  19.08.2025 08:51

                  :) Неплохо (y)

                  А если Модель не будет помнить все предыдущие 999 повторений? Какова вероятность получить ответ "4" 1000 раз в 1000 повторах с "чистого листа"?


                  1. Kamil_GR
                    19.08.2025 08:51

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


  1. morginalium
    19.08.2025 08:51

    Есть еще одна проблема при генерации кода - у современных моделей слишком маленький контекст. Современный senior-разработчик не просто кодит по заданному скрипту, а учитывает специфику задач: что-то может добавить от себя для улучшения, предложить новую идею, понимает всю задачу - он пишет не функцию обработки запроса, а часть онлайн-магазина. А современные LLM даже по API, где заявлен больший контекст, не смогу увидеть проект 'сверху'.

    Да и одно дело генерировать простую input-output функцию, а другое дело создавать проект с нуля (архитектура, микросервисы, читаемый код, понятная документация, UI/UX-дизайн).


    1. pol_pot
      19.08.2025 08:51

      Контекст у моделей намного больше чем у разработчика Ж)

      Ты же не можешь в уме держать 20т строк кода? А модель может.

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


      1. NeriaLab
        19.08.2025 08:51

        Как раз программист, спокойно может держать и больше 20к строк кода. Его ночью разбуди и он точно скажет, где и в каком файле все лежит и чем управляет. https://habr.com/ru/articles/931266/


      1. morginalium
        19.08.2025 08:51

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