Границите на модела
Накратко: Езиковият модел халюцинира: уверено пише правдоподобни, но неверни неща, защото предсказва вероятен текст, а не проверява истината; затова отговорът се сверява с източника.
Проблем
Тридесет дни, които ги няма
Асистентът на поддръжката отговаря на клиент: „Можете да върнете якето до 30 дни от получаването.“ Отговорът е учтив, гладък и уверен. Политиката на магазина е 14 дни.
На двадесетия ден клиентът праща якето обратно. Складът го връща, а клиентът пише отзив с една звезда и цитира асистента.
Никой не е програмирал „30 дни“. Откъде се взе числото и как да се пазиш от следващото?
Идеята
Моделът пише вероятен текст, не проверени факти
Езиковият модел е научен да продължава текст с вероятна следваща дума. Той не пази таблица с факти и не проверява отговора си. Ако в текста, на който е учен, „до“ често е следвано от число, той ще сложи число. Кое число, решава вероятността, а не политиката на магазина.
Гладък и уверен отговор, който е грешен или измислен, се казва халюцинация (hallucination). Тя не е бъг, който ще се поправи с една кръпка. Тя идва от самия начин, по който моделът пише: за него вярното и грешното изречение са просто по-вероятен и по-малко вероятен текст.
Виж го
Малък модел, който обещава грешно
Моделът от урока за следващия токен, в най-малкия си вид: за всяка дума пази думите, които са я следвали в текста. Повторенията остават, затова думата, която се среща по-често, се тегли по-често.
# за всяка дума: думите, които са я следвали в текстаdef train(corpus): follows = {} for sentence in corpus: words = (sentence + " .").split(" ") for word, after in zip(words, words[1:]): follows.setdefault(word, []).append(after) return followsТекстът са десет изречения от поддръжката на магазина:
corpus = [ "връщането е до 14 дни от получаването", "доставката до софия е до 2 дни", "доставката до пловдив е до 2 дни", "доставката до варна е до 3 дни", "парите се връщат до 5 работни дни", "гаранцията е 24 месеца", "плащането с карта е сигурно", "куриерът се обажда преди доставката", "поръчка над 50 евро е с безплатна доставка", "отказаната пратка се връща до 7 дни",]Най-вероятната дума всеки път:
# най-честата (при равенство първата в текста)def most_common(options): return max(options, key=options.count)
def greedy(follows, start): words = start.split(" ") while len(words) < 12: last = words[-1] word = most_common(follows[last]) if word == ".": break words.append(word) return " ".join(words)И с избор по вероятност, с генератор със семе, за да е изходът еднакъв при всяко пускане:
def sample(follows, start, rng): words = start.split(" ") while len(words) < 12: options = follows[words[-1]] word = options[int(rng.next() * len(options))] if word == ".": break words.append(word) return " ".join(words)follows = train(corpus)print("най-вероятната дума всеки път:")print(" " + greedy(follows, "връщането"))print("шест пускания, думата се тегли по вероятност:")rng = Rng(3876)for i in range(1, 7): answer = sample(follows, "връщането", rng) mark = "има го в текста" if answer in corpus else "няма го в текста" print(f" {i}. {answer} ({mark})")най-вероятната дума всеки път: връщането е до 2 днишест пускания, думата се тегли по вероятност: 1. връщането е 24 месеца (няма го в текста) 2. връщането е до 14 дни от получаването (има го в текста) 3. връщането е сигурно (няма го в текста) 4. връщането е до 5 работни дни (няма го в текста) 5. връщането е до 2 дни (няма го в текста) 6. връщането е до варна е 24 месеца (няма го в текста)Най-вероятният отговор е „връщането е до 2 дни“, а в текста пише 14. От шестте изтеглени отговора само един е изречение от текста. Останалите са гладки и грешни: „връщането е 24 месеца“ е взето от гаранцията, а „до 5 работни дни“ от връщането на парите.
Виж го
Откъде дойде числото
# най-честата (при равенство първата в текста)def most_common(options): return max(options, key=options.count)
def greedy(follows, start): words = start.split(" ") while len(words) < 12: last = words[-1] word = most_common(follows[last]) if word == ".": break words.append(word) return " ".join(words)# най-честата (при равенство първата в текста)def most_common(options): return max(options, key=options.count)
def greedy(follows, start): words = start.split(" ") while len(words) < 12: last = words[-1] word = most_common(follows[last]) if word == ".": break words.append(word) return " ".join(words)# всяко число в отговора трябва да го има в източникаdef check(answer, source): known = numbers(source) claimed = numbers(answer) if not claimed: return "? няма число за проверка" for n in claimed: if n not in known: return f"✗ {n} го няма в източника" return "✓ числата са в източника"
def numbers(text): words = [w.strip(".,") for w in text.split(" ")] return [w for w in words if w.isdigit()]Стъпка по стъпка, с думи
- Моделът продължава „връщането“, всеки път с най-честата следваща дума.
- „е до“ е в 4 изречения, едното от тях е за връщането. Дотук е вярно.
- След „до“ най-често идва „2“: от двете изречения за доставката.
- После точка. Гладко изречение, което го няма в текста: „връщането е до 2 дни“.
- Проверката взима числата от отговора и от политиката за връщане.
- 2 го няма в политиката. Там пише 14 дни.
- Всяка двойка думи е от текста на магазина. Цялото изречение е грешно, а звучи толкова уверено, колкото вярното.
Всяка двойка думи в отговора е вярна някъде в текста. Цялото изречение не е вярно никъде. Големите модели гледат много повече от една дума назад и грешат много по-рядко, но принципът е същият: те пишат вероятно, а не проверено.
Пробвай
Предвиди изхода
Моделът е научен на три изречения. Какво ще напише с най-вероятната дума всеки път, ако започне от думата за доставката?
corpus = [ "доставката до софия е 2 дни", "доставката до варна е 3 дни", "смяната на размер е 3 дни",]print(greedy(train(corpus), "доставката"))След „доставката“ двата пъти идва „до“. След „до“ идват „софия“ и „варна“ по веднъж: при равенство печели първата в текста, „софия“. После „е“, а след „е“ „3“ се среща два пъти (Варна и смяната на размер), а „2“ веднъж. Така излиза „доставката до софия е 3 дни“, изречение, което го няма в текста и е грешно: до София е 2 дни.
Идеята
Същият въпрос, друг отговор
Когато думата се тегли по вероятност, всяко пускане може да даде друг отговор. В програмата шестте пускания дадоха пет различни изречения. Това е недетерминизъм: един и същ вход, различен изход. Тестовете, логовете и оплакванията на клиентите стават по-трудни, защото „при мен работи“ вече не значи нищо.
Температура 0 (най-вероятната дума всеки път) прави отговора повторим, но не и верен. Програмата даде „до 2 дни“ при всяко пускане. При истинските доставчици дори температура 0 не обещава напълно еднакъв отговор: сметките на сървъра не вървят винаги в същия ред.
Идеята
Датата на знанията
Моделът знае само текста, на който е учен. Той е събран до определена дата, датата на знанията (knowledge cutoff). Каквото е станало след нея, моделът не го знае: новата политика за връщане, новият продукт, цената от днес.
И не знае нищо, което никога не е било в текста му: статусът на поръчка 1042 е в базата на магазина, не в модела. По подразбиране моделът не казва „не знам“. Той пише вероятен отговор и тук се ражда „пристига утре“, което никой не е проверил.
Затова фактите влизат в заявката: политиката като текст в промпта, статусът на поръчката от програмата. Как моделът сам поисква статуса, е в урока за инструментите.
Идеята
Провери отговора срещу източника
Щом отговорът трябва да стъпва на документ, програмата може да провери поне част от него. Най-грубата проверка: всяко число в отговора трябва да го има в източника.
# всяко число в отговора трябва да го има в източникаdef check(answer, source): known = numbers(source) claimed = numbers(answer) if not claimed: return "? няма число за проверка" for n in claimed: if n not in known: return f"✗ {n} го няма в източника" return "✓ числата са в източника"
def numbers(text): words = [w.strip(".,") for w in text.split(" ")] return [w for w in words if w.isdigit()]Шестте отговора от програмата горе срещу политиката за връщане:
source = "Връщането е до 14 дни от получаването. Парите се връщат до 5 работни дни."answers = [ "връщането е 24 месеца", "връщането е до 14 дни от получаването", "връщането е сигурно", "връщането е до 5 работни дни", "връщането е до 2 дни", "връщането е до варна е 24 месеца",]for a in answers: print(f"{a} → {check(a, source)}")връщането е 24 месеца → ✗ 24 го няма в източникавръщането е до 14 дни от получаването → ✓ числата са в източникавръщането е сигурно → ? няма число за проверкавръщането е до 5 работни дни → ✓ числата са в източникавръщането е до 2 дни → ✗ 2 го няма в източникавръщането е до варна е 24 месеца → ✗ 24 го няма в източникаПроверката хвана три грешни отговора. Но пусна „връщането е до 5 работни дни“: 5 го има в политиката, само че за връщането на парите. И не може да каже нищо за „връщането е сигурно“, защото там няма число. Груба проверка намалява риска, без да го маха. Затова в истински системи проверките са няколко, а където грешката е скъпа, гледа човек.
Пробвай
Намери грешката
Колега опростява проверката. Сега отговорът „връщането е до 4 дни“ минава като верен, макар че в политиката пише 14. На кой ред е грешката?
Избери реда с грешката.
Числото се търси като част от текста на източника. „4“ е част от „14“, затова проверката го намира. Числата трябва да се сравняват цели: първо се вадят числата на източника и после се търси същото число сред тях.
Пробвай
Попълни
Моделът спира изречението, когато най-вероятната следваща дума е краят. Как изглежда краят в текста за обучение?
def greedy(follows, start):
words = start.split(" ")
while len(words) < 12:
last = words[-1]
word = most_common(follows[last])
if word == :
break
words.append(word)
return " ".join(words)При обучението всяко изречение получава " ." накрая, затова точката е отделна дума. Когато моделът избере нея, изречението свършва. Без тази проверка моделът пише до границата от 12 думи.
Идеята
Кога езиковият модел е грешният инструмент
- Има точен отговор, който се смята. Сумата на поръчката, ДДС, остатъкът по сметка. Един ред код не греши, моделът може да сбърка цифра.
- Данните са живи. Статус на поръчка, наличност, днешна цена. Те са в базата. Моделът може да ги поиска чрез инструмент, но не бива да ги „помни“.
- Правилото е твърдо. „Връщане до 14 дни“ е
if, не промпт. Каквото трябва да е винаги еднакво, се пише в кода. - Решението трябва да се обясни и провери после. Отказано плащане или кредит иска причина, която се повтаря. За такива решения има модели като логистичната регресия, а правилата се пишат явно.
- Грешката струва повече от мълчанието. Медицински, правни, финансови отговори към клиент. Тогава моделът пише чернова, а човек решава.
Къде моделът е силен: чернови, резюмета, превод, подреждане на свободен текст (за кой отдел е писмото), извличане на данни от текст, отговори по документ, които се проверяват. Задачи, в които малката неточност се хваща лесно и не струва скъпо.
По-точно, за любопитните
Защо и големите модели халюцинират. Те са научени на огромен текст, а после още малко да следват инструкции и да казват „не знам“. Това намалява грешките, но не ги маха: моделът пак избира вероятен текст. Особено опасни са редките факти (номер на член от закон, цитат, име на функция в малка библиотека), където в текста за обучение има малко примери.
Какво помага, на слоеве. Фактите в заявката (политиката като текст, модулът за търсене по смисъл и RAG по-нататък в курса прави точно това). Изход по схема и проверка в кода (структуриран изход). Тестов набор с въпроси и правилни отговори, който се пуска при всяка смяна (оценяване). Отговор „не знам, предавам на колега“, когато проверката не мине. И човек там, където грешката е скъпа.
Колко е малък моделът тук. Биграмният модел помни една дума назад и е научен на десет изречения. Голям модел гледа хиляди токени назад и е научен на трилиони. Затова той рядко лепи „връщането е до 2 дни“ от две изречения. Но когато в контекста няма отговор, той пак пише най-вероятното продължение, а не „не знам“.
Измерването на халюцинации. Процентът грешни отговори зависи от задачата и от данните. Числата от чужди тестове не казват нищо за твоя асистент. Мериш ги ти, на твоите въпроси, както в урока за оценяването.
Упражнение
Отговорите за доставката
Реши задачата в редактора си.
Асистентът отговаря за доставката, а източникът е: „Доставката до София е до 2 работни дни. До Варна е до 3 работни дни. Над 50 евро доставката е безплатна.“ Провери пет отговора със същото правило (всяко число в отговора трябва да го има в източника) и отпечатай присъдата за всеки:
- Доставката до София е до 2 дни.
- Доставката до Варна е до 4 дни.
- Доставката е безплатна над 30 евро.
- Доставката до Пловдив е до 1 ден.
- Доставката е безплатна за всички поръчки.
Доставката до София е до 2 дни. → ✓ числата са в източникаДоставката до Варна е до 4 дни. → ✗ 4 го няма в източникаДоставката е безплатна над 30 евро. → ✗ 30 го няма в източникаДоставката до Пловдив е до 1 ден. → ✗ 1 го няма в източникаДоставката е безплатна за всички поръчки. → ? няма число за проверкаПоследният отговор е грешен, а проверката не може да го хване: в него няма число.
Още задачи
- Число на място. Проверявай не само дали числото го има, а и думата преди него: „до 2“ за София. Кои отговори хваща сега?
- Отказ. Когато проверката не мине, програмата да връща „Ще ви свържа с колега.“ вместо отговора на модела.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Списъчни изрази и генератори · Текстът на парчета: токени · Предсказване на следващия токен · Прозорецът на контекста
- Продължава в: Извикване на модел през API · Промптът е код · Структуриран изход: JSON по схема · Инструменти: моделът пита, програмата прави
- Задачи по темата: Как работи езиков модел