Search
Write a publication
Pull to refresh

Comments 23

Как я понял, они то, что раньше люди делали руками - добавляли просьбы рассуждать по шагам, решали задачи через разбиение на агетов - обернули у себя внутри и сказали, что это новая нейронка. Не забывая при этом брать деньги за токены потраченные на рассуждения, которые мы даже не видим (60 баксов за миллион токенов, что раз в 10 больше gpt 4o). И то, что мы не видим рассуждения, кстати не круто для open source сообщества - не получится эффективно дообучать более слабые сетки на примерах GPT

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

UFO landed and left these words here

И то, что мы не видим рассуждения, кстати не круто для open source сообщества - не получится эффективно дообучать более слабые сетки на примерах GPT

https://x.com/DrJimFan/status/1834279865933332752

- Large Language Monkeys: Scaling Inference Compute with Repeated Sampling. Brown et al. finds that DeepSeek-Coder increases from 15.9% with one sample to 56% with 250 samples on SWE-Bench, beating Sonnet-3.5.
- Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters. Snell et al. finds that PaLM 2-S beats a 14x larger model on MATH with test-time search.

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

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

собственно если кому интересно то вот:

func calculate(values []int) float64 {
	// Сортировка чтобы найти максимум
	sort.Ints(values)
	last := len(values) - 1
	maxValue := values[last];

	var aggregatedValue float64 = 0.0
	for i := last; i >= 0; i-- {
		value := values[i]
		delta := float64(maxValue) - aggregatedValue
		amount := delta * (math.Pow(float64(value) / float64(maxValue), 3) / 5)
		aggregatedValue += amount
	}
	return aggregatedValue;
}

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

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

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

Также, поскольку порядок операций неважен, можно дополнительно разбить этот массив, к примеру, на 8 частей и считать каждую часть на отдельном ядре, а потом сложить то, что получилось, по формуле. Например, если первая часть массива приблизилась к maxValue на 50% и вторая часть на 90%, то суммарно обе части вместе приблизились к maxValue на 95%.

Такие оптимизации будут и значительно проще для продумывания и реализации, и будут ускорять в разы или даже на порядки больше, чем попытка избавиться от одного из циклов. Хотя если действительно можно избавиться от одного из циклов, с учётом того, что там delta равна (maxValue - aggregatedValue), а не (maxValue - value), то я бы хотел посмотреть, как это возможно.

Если данные идут потоково, и нет возможности сохранить их в память из-за нехватки памяти, могу предложить только считать не от общего maxValue, а от текущего, а если вдруг встретили больше, то немного скорректировать текущее aggregatedValue + пересчитать данные для X последних элементов или запланировать этот пересчёт на потом. Точность при этом упадёт, но примерный ответ будет.

Теперь правда хоть какая-то инфа по оптимизации для этой задачи в Интернете есть, и тестировать LLM теперь на этой задаче сложнее.

>>Порядок операций здесь неважен.
верно.

>>Например, если первая часть массива приблизилась к maxValue на 50% и вторая часть на 90%, то суммарно обе части вместе приблизились к maxValue на 95%.

a := calculate([]int{50, 50})
b := calculate([]int{100, 100})
c := calculate([]int{50, 50, 100, 100})
d := calculate([]int{50, 100})
fmt.Println(a,b,c,d)
18 36 39.160000000000004 22


как вы заметили порядок не важен, но я не понял что за формулы вы собираетесь применить чтобы получилось f(18, 36) = f(22, 22) = 39.16

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

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

Я имел ввиду, что мы вначале в 8 потоков найдём maxValue, например, с помощью функции calculate_part1(array), а потом в 8 потоков найдём aggregatedValue с помощью функции calculate_part2(array, maxValue).

Вот пример на javascript:

//Returns maxValue
function calculate_part1(a) {
	if (!Array.isArray(a) && !ArrayBuffer.isView(a)) throw new TypeError('a must be an Array or a TypedArray');
	if (a.length < 1)                                throw new Error('a.length must be >= 1');
	
	let maxValue = a[0];
	
	for (let i = 1; i < a.length; i++)
		maxValue = Math.max(maxValue, a[i]);
	
	return maxValue;
}

//Returns aggregatedValue
function calculate_part2(a, maxValue, start = 0, end = a.length) {
	const k = (1 / maxValue) ** 3 / 5;
	let sum = -0;
	
	for (let i = start; i < end; i++)
		sum += (maxValue - sum) * a[i] ** 3 * k;
	
	return sum;
}

//Combines few aggregatedValues calculated independently
function calculate_part3(maxValue, ...sums) {
	let ans = -0;
	
	for (const sum of sums) {
		const progress = sum / maxValue;
		ans += progress - ans * progress;  //Need to test if works with negative numbers
	}
	
	return ans * maxValue;
}

//Tests functions above
function test() {
	const EL_COUNT    = 1000,
	      buffer      = typeof SharedArrayBuffer === 'function' ? new SharedArrayBuffer(EL_COUNT * 8) : new ArrayBuffer(EL_COUNT * 8),
	      array       = (new Float64Array(buffer)).map(v => Math.random() * 100),
		  biggerValue = array[(EL_COUNT * 0.8) | 0] = 1000,
	      maxValue    = calculate_part1(array),  //Single-thread version but multi-thread can be used instead
		  
	      //Slow way
		  ans_slow    = calculate_part2(array, maxValue),  //Single-thread version
		  
		  //Fast way
		  sum1        = calculate_part2(array, maxValue, 0,   200),  //Please calc it in thread 1
		  sum2        = calculate_part2(array, maxValue, 200, 400),  //Please calc it in thread 2
		  sum3        = calculate_part2(array, maxValue, 400, 600),  //Please calc it in thread 3
		  sum4        = calculate_part2(array, maxValue, 600, 800),  //Please calc it in thread 4
		  sum5        = calculate_part2(array, maxValue, 800, 1000), //Please calc it in thread 5
		  ans_fast    = calculate_part3(maxValue, sum1, sum2, sum3, sum4, sum5);
	
	console.log(ans_slow);  //237.84063581747668
	console.log(ans_fast);  //237.84063581747665
	console.log(areDoublesEqual_simple(ans_fast, ans_slow));  //true
}

function areDoublesEqual_simple(a, b) {
	return Math.abs(a - b) < 0.00000000000001 || Math.abs(a / b - 1) < 0.00000000000001;
}

test();

а, так я то писал что задача как раз в том чтобы избавиться от цикла поиска максимума. Так то оно быстрее если ядра есть лишние и бесплатные. В моем случае такой халявы не было :)

Потестил, и прямо сходу нашёл ей новые применения. Например, я пишу сценарий к фильму. Раньше я мог юзать нейросети только для каких-то точечных переписок, например предложить несколько альтернативных реплик, вместо тех, что меня не устраивают. Или попросить нейросетку пересказать сцену, чтобы понять как поймёт её среднестатистический зритель. При этом юзал в основном Claude, а не ChatGPT, он с художественными текстами лучше.

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

А вот o1 прямо хорошо себя показал. Я закинул сцену, которую я считаю не очень удачной, накинул мысли почему она сейчас не работает и предположения как её можно изменить, намёки на связи с другими частями сценария. И после 40 секунд раздумья o1 вывел эту сцену туда, куда я вообще изначально её не замышлял. И получилось всё живо и классно. Да, такое получилось только один раз за 15 попыток, но это уже очень круто.

С этого момента уже можно начинать серьёзно работать с текстами, когда получается не просто реферат на заданную тему, а что-то реально интересное и увлекательное. Да, с o1 здесь по-прежнему будет много работы над промптами, но уже сильно экономит время.

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

Очередное подтверждение ироничной ситуации, что люди хотели переложить на роботов монотонную работу, чтобы остались только творческие задачи, но роботы сказали им "подержи-ка моё пиво".

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

А в чём проблема заставить нейросетку думать подольше? Полно же итеративных алгоритмов, уменьшающих ошибку с каждой итерацией, но не дающие 100% точный ответ. Просто подкрутить количество итераций и всё?

а что такое "точный ответ" для генеративной задачи?

Пишут, что модели и раньше умели рассуждать, но делали это менее эффективно. В новой модели при итеративном само-исправлении (рефлексии) и рассуждениях сделали так, чтобы модель куда чаще приходила к правильному ответу. А еще добавили "аргументационные токены" - The o1 models introduce reasoning tokens. The models use these reasoning tokens to "think", breaking down their understanding of the prompt and considering multiple approaches to generating a response. After generating reasoning tokens, the model produces an answer as visible completion tokens, and discards the reasoning tokens from its context.

в чём проблема заставить нейросетку думать подольше?

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

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

Sign up to leave a comment.

Other news