Главная / Статьи / Цикл следующего токена: когнитивная модель ЯИИ до того, как вы начнёте использовать агентов

Цикл следующего токена: когнитивная модель ЯИИ до того, как вы начнёте использовать агентов

Узнайте, как функционируют токены, окна контекста, методы выборки и цикл генерации, с простыми примерами на Python в оффлайн-режиме, которые объясняют, почему существуют RAG, ReAct и LangGraph.

1143 слов

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

Генерация — это прогнозирование следующего токена в цикле

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

Вследствие этого возникают два последствия:

  • Плана нет. Каждый токен зависит только от токенов, находящихся перед ним.
  • Память между вызовами отсутствует. Каждый запрос начинается именно с тех токенов, которые вы отправляете, и именно по этой причине существует генерация с улучшением на основе извлечения информации.

Токены — это части слов, а не целые слова

Модель воспринимает целые числа, а не текст. Токенизатор преобразует строки в идентификаторы токенов и обратно. Часто встречающиеся слова обычно превращаются в один токен, в то время как редкие слова и код делятся на несколько токенов. Примерная оценка: один токен соответствует примерно трём четвертям слова.

Этот фрагмент загружает o200k_base, формат кодирования семейства gpt-4o, с помощью tiktoken, кодирует предложение и выводит каждый идентификатор вместе с соответствующим фрагментом текста. Обратите внимание, что «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 рассматривает другие настройки выборки.

Создание цикла в миниатюре

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

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

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

Основные выводы

  • Глубокая нейронная сеть представляет собой «замороженную» функцию, преобразующую последовательность токенов в распределение следующего токена, которая работает в рамках цикла обратной связи.
  • Он знает только свои веса и размер окна контекста, и никогда не учится на ваших запросах.
  • Разнообразие достигается за счёт выборки, контролируемой параметром температуры.
  • Техники агентов определяют, какие токены будут использованы и что произойдёт с токенами, выходящими из системы.
  • Связанные материалы