Галоўная / Артыкулы / Цыкл наступнага токена: псіхалогічны модэль LLM-ў прыямо перад тым, як вы пачнёте викорыстоўваць агентаў.

Цыкл наступнага токена: псіхалогічны модэль LLM-ў прыямо перад тым, як вы пачнёте викорыстоўваць агентаў.

Дазнаецеся, як працуюць токены, акна контэксту, выбір прымероў і цыкл генеравання, за дапамогай невялікіх прымероў на Python, якія адказваюць на пытанне, чаму існуюць RAG, ReAct і LangGraph.

1143 слоў

Інжынеры, які працуюць з LLM-амі через такі фрэймворкі, як LangChain, частаў не можуць з’ясавіць, калі ўтворыўся проблема, чыя це віна — фрэймворка, API, які ў яго ўключаны, чы сама модель. Рашэнням являецца чыстая ментальная модель: LLM — это функцыя прагнозавання наступнага токена, якая вызываецца паўтароўна ў цікле. Калі такая канцэпцыя ўсвядомлена, RAG — это спосаб выбору таго, што будзе падацца ў функцыю, ReAct — спосаб аналізу таго, што выходзіць, а LangGraph — спосаб коордынацыі багацькох вызоваў. Прыклады нижэй працуюць локальна з Python і адной маленькай бібліятэкай, ключа API не патрэбна.

Генераванне — это прагнозавання наступнага токена ў цікле

Пры наявнасці серыі токенаў модель вяртае верыгоднасць кожнага можлівага наступнага токена. Выбираецца адны, яго дадаюць да серыі, а сама дужэйшая серыя зноў вводзіцца ў працэс. Гэта павтарываецца, пакуль не будзе досягнуты токен зупінкі або ліміт дужжыны. Стрімаванне выходных дадзенняў проста прадстаўляе гэты цікл токен за токенам.

Выліваецца два наследкія:

  • Няма плану. Кожны токен залежыць толькі ад токенаў, якія ўжо былі.
  • Няма памяці между вызваннямі. Кожны запит пачынаецца ад самэх токенаў, якія вы адправляеце, і самэ гэта є прычыной існавання генеравання з падтрымкай выкарыстоўвання ранейшых дадзеных.

Токены — это часткі слова, а не самыя слова

Модель бачыць цэлыя числа, а не текст. Токенізатор ператварае строкі на ID токенаў і назад. Часта вжываемыя словы зазвычай становяць адзін токен, тады як рэдкасці і код дзелююцца на калькі токенаў. Прыблізны показнік: адзін токен — цэлае трохце часткі слова.

Фрагмент завантажыць o200k_base, кодаванне з сямейства gpt-4o, через tiktoken, кодавае рэченне і выдрукоўвае кожны ID разам з фрагментам тексту. Заўважыце, што "LangGraph" становіць два токены, а прасторы пад словамі належаць да наступнага токена.

import tiktoken

# tokenizer of the gpt-4o model family
enc = tiktoken.get_encoding("o200k_base")

ids = enc.encode("LangGraph orchestrates agents.")
print(ids)
# [30741, 9922, 109873, 1381, 19297, 13]

for i in ids:
    print(i, repr(enc.decode([i])))
# 'Lang' 'Graph' ' orchestr' 'ates' ' agents' '.'

Адаптаванне і выконання — гэта разныя фазы

Падчас адаптавання вагі корэктуецца праз прыказванне наступных токенаў у вялікіх колькасцях тексту. Пад час выконання викорыстоўваецца зашчытаны модэль. Ваш запит ніколі не зменяе вагі, таму інфармацыю, якой не хапае модэлю, трэба падаць у запит пад час выконання. Самэ гэта і робіць RAG.

Вікна контэкста — гэта весь свет модэля

Одна вызова може обрабатваць толькі певную колькасць токенаў, і гэты ліміт, вікна контэкста, абягае як запит, так і створаны выход. Усё, што знаходзіцца за межамі, для той вызовы не існуе. Чат здаецца безперывным толькі таму, што прыложэнне ў кожны раз перасылае паказаныя раней поведамленні, а RAG існуе таму, што зборы дакументаў не пасвядчаюць, таму замест таго адбіраецца калькі актуальных фрагментаў.

Бюджетаванне — это простая арымэтыка. Адказчык після падрахавання токэнаў за дапамойкай токенізатора вырахоўвае ўсё гэта, плюс резерв для адказу, з дыяпазона 128 000 токэнаў, які заданы для gpt-4o-mini. Ліміты разлічаюцца ў залежнасці ад модэляў і версый, таму пераканайцеся ў актуальной дасягледзе вашага прадаўцы.

def count_tokens(text: str) -> int:
    return len(enc.encode(text))

prompt = "Summarize the attached design doc."
window = 128_000     # e.g. gpt-4o-mini
reserve = 1_000      # room for the answer
used = count_tokens(prompt)
print("left:", window - reserve - used)

Тэмпература кантролюе выбіранне наступнага токэна

Метод адбору выбірае аднаго токэна з распаду модэля, а тэмпература перакаштоввае гэты распад. Калі тэмпература близкая да нуля, паўтараючыся токэн практычна завжды выграўвае. Пры значэнні 1,0 і вышэ менавіта токэны, якія раней былі малаямо верагодныя, атрымаюць рэальную шанс. Для экстракцыі, структураванага выходу і агентаў для вызову інструментаў вярны ўжыць тэмпературу 0, а для прадрафтавання і брейнстармінгу — прыблізна 0,7–1,0. Наша інструкцыя па тэмпературе, top-k і top-p раскрывае іншыя параметры адбору.

Стварэнне ціклу ў мініятуры

Наступны прыклад спаўнюе рэальны токенайзер з фальшывым моделлю, створаным на адной табліцы пашуку. Ён маленькі, але выконвае той самы цикл, што і справжній LLM: кодаванне, прыказанне, дадзенне да адной табліцы, зупнэнне.

Спачатку маленькі корпус токенайзуецца, і працуецца з кожной суседней парой ID. Для кожнага токена табліца зберагае толькі яго найчастэйшаг наступніка, што робіць гэты прыказчык „жаднамудрый“, ў той жа час, што це эквівалент тэмпературы нуля.

CORPUS = (
    "the agent calls the model. "
    "the model returns a token. "
    "the agent calls the tool. "
    "the tool returns a result."
)

ids = enc.encode(CORPUS)
counts = {}
for a, b in zip(ids, ids[1:]):
    counts.setdefault(a, {})
    counts[a][b] = counts[a].get(b, 0) + 1

# greedy "model": token -> likeliest successor
table = {
    a: max(s, key=s.get)
    for a, s in counts.items()
}

Цікл кодавае запит, шукае найбольш верагодны наступнік апошньага токена, дадзеў яго да адной табліцы і выведае декодаваны текст. Якщо наступніка няма, вяртаецца None, які выступае ў ролі токена зупнэння. Саме дадзенне да адной табліцы ёсьць ключовай ступенём: выходны данные станавяцца вхіднымі.

seq = enc.encode("the agent calls")
for _ in range(3):
    nxt = table.get(seq[-1])
    if nxt is None:    # our toy "stop token"
        break
    seq.append(nxt)    # output becomes input
    print(enc.decode(seq))

Прылічэнне расте на адны токен за кожны крок:

the agent calls the
the agent calls the model
the agent calls the model.

Адзін дакладны момант ёсць павучы. У корпусе слова „the“ частаюць пасля „model“ і „tool“ аднакова частота, а max застаўляе тое, што пазнаў першы. Рэальныя моделі сталквуюцца з такімі майже равнымі распадамі постаўна, таму так важлівы настройкі выбору прымэроў.

Адкліканне прымэроў

Зберагуйце фрагменты ў аднам скрыптэ, напрыклад examples/part01_tokens.py, разам з файлам requirements.txt, у якім перыядначаны tiktoken. Ён выводзіць распад токэнаў, выконвае расчыткі бюджету і запускае простую петлю за адну секунду, у автонамны режым пасля таго, як данні токенайзера будуць зберагнутыя у кэш. Потым зменіце корпус і старайцесь, каб выходныя данні таксама змениліся.

pip install -r requirements.txt
python examples/part01_tokens.py

Ключовыя выводы

  • LLM — это зафіксаваная функцыя, якая ператварае последовальнась токэнаў у распад наступных токэнаў, і якая працуе ў цыклі зворотнага зв’язку.
  • Ён ведае толькі своія вагі, а таксама розмер вікна контэксту, і ніколі не выучваеся з вашага запиту.
  • Разнаўтнеча выкалічваецца за дапамою выбору прыкладаў, які кантролюецца параметрам тэмпературы.
  • Тэхнікі агента вялікай прычыны наказваюць, калікі токены застаюцца і што выдзейчыцца з тых токенаў, якія выходзяць.
  • Спадневаная літэратура