Перейти к основному содержимому

Guidance

Управляйте выводом LLM с помощью регулярных выражений и грамматик, гарантируйте генерацию валидного JSON/XML/кода, обеспечивайте соблюдение структурированных форматов и создавайте многошаговые рабочие процессы с помощью Guidance — фреймворка ограниченной генерации от Microsoft Research.

Метаданные навыка​

ИсточникОпционально — установка через vibeos skills install official/mlops/guidance
Путьoptional-skills/mlops/guidance
Версия1.0.0
АвторOrchestra Research
ЛицензияMIT
Зависимостиguidance, transformers
Платформыlinux, macos, windows
ТегиPrompt Engineering, Guidance, Constrained Generation, Structured Output, JSON Validation, Grammar, Microsoft Research, Format Enforcement, Multi-Step Workflows

Справочник: полный SKILL.md​

к сведению

Ниже приведено полное определение навыка, которое VibeOS загружает при его активации. Это те инструкции, которые видит агент, когда навык активен.

Guidance: Ограниченная генерация LLM

Когда использовать этот навык​

Используйте Guidance, когда вам необходимо:

  • Контролировать синтаксис вывода LLM с помощью регулярных выражений или грамматик
  • Гарантировать генерацию валидного JSON/XML/кода
  • Снизить задержку по сравнению с традиционными подходами к промптингу
  • Обеспечить соблюдение структурированных форматов (даты, email, ID и т.д.)
  • Создавать многошаговые рабочие процессы с Python-управлением потоком
  • Предотвращать невалидный вывод с помощью грамматических ограничений

Звёзды на GitHub: 18 000+ | От: Microsoft Research

Установка​

# Базовая установка
pip install guidance

# С определёнными бэкендами
pip install guidance[transformers] # Модели Hugging Face
pip install guidance[llama_cpp] # Модели llama.cpp

Быстрый старт​

Базовый пример: Структурированная генерация​

from guidance import models, gen

# Загрузка модели (поддерживает OpenAI, Transformers, llama.cpp)
lm = models.OpenAI("gpt-4")

# Генерация с ограничениями
result = lm + "Столица Франции — " + gen("capital", max_tokens=5)

print(result["capital"]) # "Париж"

С Anthropic Claude​

from guidance import models, gen, system, user, assistant

# Настройка Claude
lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Использование контекстных менеджеров для чат-формата
with system():
lm += "Вы — полезный ассистент."

with user():
lm += "Какая столица Франции?"

with assistant():
lm += gen(max_tokens=20)

Основные концепции​

1. Контекстные менеджеры​

Guidance использует Python-контекстные менеджеры для взаимодействия в чат-стиле.

from guidance import system, user, assistant, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Системное сообщение
with system():
lm += "Вы — эксперт по генерации JSON."

# Сообщение пользователя
with user():
lm += "Сгенерируй объект человека с именем и возрастом."

# Ответ ассистента
with assistant():
lm += gen("response", max_tokens=100)

print(lm["response"])

Преимущества:

  • Естественный чат-поток
  • Чёткое разделение ролей
  • Лёгкость чтения и поддержки

2. Ограниченная генерация​

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

Ограничения через регулярные выражения​

from guidance import models, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Ограничение до валидного формата email
lm += "Email: " + gen("email", regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

# Ограничение до формата даты (ГГГГ-ММ-ДД)
lm += "Дата: " + gen("date", regex=r"\d{4}-\d{2}-\d{2}")

# Ограничение до номера телефона
lm += "Телефон: " + gen("phone", regex=r"\d{3}-\d{3}-\d{4}")

print(lm["email"]) # Гарантированно валидный email
print(lm["date"]) # Гарантированно формат ГГГГ-ММ-ДД

Как это работает:

  • Регулярное выражение преобразуется в грамматику на уровне токенов
  • Невалидные токены отфильтровываются во время генерации
  • Модель может производить только соответствующие результаты

Ограничения через выбор​

from guidance import models, gen, select

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Ограничение до конкретных вариантов
lm += "Тональность: " + select(["positive", "negative", "neutral"], name="sentiment")

# Выбор из нескольких вариантов
lm += "Лучший ответ: " + select(
["A) Париж", "B) Лондон", "C) Берлин", "D) Мадрид"],
name="answer"
)

print(lm["sentiment"]) # Один из: positive, negative, neutral
print(lm["answer"]) # Один из: A, B, C или D

3. «Заживление» токенов​

Guidance автоматически «заживляет» границы токенов между промптом и генерацией.

Проблема: Токенизация создаёт неестественные границы.

# Без заживления токенов
prompt = "Столица Франции — "
# Последний токен: " — "
# Первый сгенерированный токен может быть " Па" (с ведущим пробелом)
# Результат: "Столица Франции — Париж" (двойной пробел!)

Решение: Guidance отступает на один токен назад и генерирует заново.

from guidance import models, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# Заживление токенов включено по умолчанию
lm += "Столица Франции — " + gen("capital", max_tokens=5)
# Результат: "Столица Франции — Париж" (правильные пробелы)

Преимущества:

  • Естественные границы текста
  • Отсутствие проблем с пробелами
  • Лучшая производительность модели (видит естественные последовательности токенов)

4. Генерация на основе грамматик​

Определяйте сложные структуры с помощью контекстно-свободных грамматик.

from guidance import models, gen

lm = models.Anthropic("claude-sonnet-4-5-20250929")

# JSON грамматика (упрощённая)
json_grammar = """
{
"name": <gen name regex="[A-Za-z ]+" max_tokens=20>,
"age": <gen age regex="[0-9]+" max_tokens=3>,
"email": <gen email regex="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}" max_tokens=50>
}
"""

# Генерация валидного JSON
lm += gen("person", grammar=json_grammar)

print(lm["person"]) # Гарантированно валидная JSON-структура

Варианты использования:

  • Сложные структурированные выводы
  • Вложенные структуры данных
  • Синтаксис языков программирования
  • Предметно-ориентированные языки

5. Функции Guidance​

Создавайте переиспользуемые шаблоны генерации с помощью декоратора @guidance.

from guidance import guidance, gen, models

@guidance
def generate_person(lm):
"""Сгенерировать человека с именем и возрастом."""
lm += "Имя: " + gen("name", max_tokens=20, stop="\n")
lm += "\nВозраст: " + gen("age", regex=r"[0-9]+", max_tokens=3)
return lm

# Использование функции
lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = generate_person(lm)

print(lm["name"])
print(lm["age"])

Функции с состоянием:

@guidance(stateless=False)
def react_agent(lm, question, tools, max_rounds=5):
"""ReAct-агент с использованием инструментов."""
lm += f"Вопрос: {question}\n\n"

for i in range(max_rounds):
# Мысль
lm += f"Мысль {i+1}: " + gen("thought", stop="\n")

# Действие
lm += "\nДействие: " + select(list(tools.keys()), name="action")

# Выполнение инструмента
tool_result = tools[lm["action"]]()
lm += f"\nНаблюдение: {tool_result}\n\n"

# Проверка завершения
lm += "Готово? " + select(["Да", "Нет"], name="done")
if lm["done"] == "Да":
break

# Финальный ответ
lm += "\nФинальный ответ: " + gen("answer", max_tokens=100)
return lm

Конфигурация бэкенда​

Anthropic Claude​

from guidance import models

lm = models.Anthropic(
model="claude-sonnet-4-5-20250929",
api_key="ваш-api-ключ" # Или установите переменную окружения ANTHROPIC_API_KEY
)

OpenAI​

lm = models.OpenAI(
model="gpt-4o-mini",
api_key="ваш-api-ключ" # Или установите переменную окружения OPENAI_API_KEY
)

Локальные модели (Transformers)​

from guidance.models import Transformers

lm = Transformers(
"microsoft/Phi-4-mini-instruct",
device="cuda" # Или "cpu"
)

Локальные модели (llama.cpp)​

from guidance.models import LlamaCpp

lm = LlamaCpp(
model_path="/путь/к/модели.gguf",
n_ctx=4096,
n_gpu_layers=35
)

Распространённые шаблоны​

Шаблон 1: Генерация JSON​

from guidance import models, gen, system, user, assistant

lm = models.Anthropic("claude-sonnet-4-5-20250929")

with system():
lm += "Вы генерируете валидный JSON."

with user():
lm += "Сгенерируй профиль пользователя с именем, возрастом и email."

with assistant():
lm += """{
"name": """ + gen("name", regex=r'"[A-Za-z ]+"', max_tokens=30) + """,
"age": """ + gen("age", regex=r"[0-9]+", max_tokens=3) + """,
"email": """ + gen("email", regex=r'"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"', max_tokens=50) + """
}"""

print(lm) # Гарантированно валидный JSON

Шаблон 2: Классификация​

from guidance import models, gen, select

lm = models.Anthropic("claude-sonnet-4-5-20250929")

text = "Этот продукт потрясающий! Я его обожаю."

lm += f"Текст: {text}\n"
lm += "Тональность: " + select(["positive", "negative", "neutral"], name="sentiment")
lm += "\nУверенность: " + gen("confidence", regex=r"[0-9]+", max_tokens=3) + "%"

print(f"Тональность: {lm['sentiment']}")
print(f"Уверенность: {lm['confidence']}%")

Шаблон 3: Многошаговые рассуждения​

from guidance import models, gen, guidance

@guidance
def chain_of_thought(lm, question):
"""Сгенерировать ответ с пошаговыми рассуждениями."""
lm += f"Вопрос: {question}\n\n"

# Генерация нескольких шагов рассуждения
for i in range(3):
lm += f"Шаг {i+1}: " + gen(f"step_{i+1}", stop="\n", max_tokens=100) + "\n"

# Финальный ответ
lm += "\nСледовательно, ответ: " + gen("answer", max_tokens=50)

return lm

lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = chain_of_thought(lm, "Сколько будет 15% от 200?")

print(lm["answer"])

Шаблон 4: ReAct-агент​

from guidance import models, gen, select, guidance

@guidance(stateless=False)
def react_agent(lm, question):
"""ReAct-агент с использованием инструментов."""
tools = {
"calculator": lambda expr: eval(expr),
"search": lambda query: f"Результаты поиска для: {query}",
}

lm += f"Вопрос: {question}\n\n"

for round in range(5):
# Мысль
lm += f"Мысль: " + gen("thought", stop="\n") + "\n"

# Выбор действия
lm += "Действие: " + select(["calculator", "search", "answer"], name="action")

if lm["action"] == "answer":
lm += "\nФинальный ответ: " + gen("answer", max_tokens=100)
break

# Ввод для действия
lm += "\nВвод для действия: " + gen("action_input", stop="\n") + "\n"

# Выполнение инструмента
if lm["action"] in tools:
result = tools[lm["action"]](lm["action_input"])
lm += f"Наблюдение: {result}\n\n"

return lm

lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = react_agent(lm, "Сколько будет 25 * 4 + 10?")
print(lm["answer"])

Шаблон 5: Извлечение данных​

from guidance import models, gen, guidance

@guidance
def extract_entities(lm, text):
"""Извлечение структурированных сущностей из текста."""
lm += f"Текст: {text}\n\n"

# Извлечение человека
lm += "Человек: " + gen("person", stop="\n", max_tokens=30) + "\n"

# Извлечение организации
lm += "Организация: " + gen("organization", stop="\n", max_tokens=30) + "\n"

# Извлечение даты
lm += "Дата: " + gen("date", regex=r"\d{4}-\d{2}-\d{2}", max_tokens=10) + "\n"

# Извлечение местоположения
lm += "Местоположение: " + gen("location", stop="\n", max_tokens=30) + "\n"

return lm

text = "Тим Кук объявил в Apple Park 2024-09-15 в Купертино."

lm = models.Anthropic("claude-sonnet-4-5-20250929")
lm = extract_entities(lm, text)

print(f"Человек: {lm['person']}")
print(f"Организация: {lm['organization']}")
print(f"Дата: {lm['date']}")
print(f"Местоположение: {lm['location']}")

Лучшие практики​

1. Используйте регулярные выражения для проверки формата​

# ✅ Хорошо: Регулярное выражение гарантирует валидный формат
lm += "Email: " + gen("email", regex=r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")

# ❌ Плохо: Свободная генерация может дать невалидные email
lm += "Email: " + gen("email", max_tokens=50)

2. Используйте select() для фиксированных категорий​

# ✅ Хорошо: Гарантированно валидная категория
lm += "Статус: " + select(["pending", "approved", "rejected"], name="status")

# ❌ Плохо: Может сгенерировать опечатки или невалидные значения
lm += "Статус: " + gen("status", max_tokens=20)

3. Используйте заживление токенов​

# Заживление токенов включено по умолчанию
# Никаких специальных действий не требуется — просто объединяйте естественно
lm += "Столица — " + gen("capital") # Автоматическое заживление

4. Используйте стоп-последовательности​

# ✅ Хорошо: Остановка на новой строке для однострочного вывода
lm += "Имя: " + gen("name", stop="\n")

# ❌ Плохо: Может сгенерировать несколько строк
lm += "Имя: " + gen("name", max_tokens=50)

5. Создавайте переиспользуемые функции​

# ✅ Хорошо: Переиспользуемый шаблон
@guidance
def generate_person(lm):
lm += "Имя: " + gen("name", stop="\n")
lm += "\nВозраст: " + gen("age", regex=r"[0-9]+")
return lm

# Использование несколько раз
lm = generate_person(lm)
lm += "\n\n"
lm = generate_person(lm)

6. Балансируйте ограничения​

# ✅ Хорошо: Разумные ограничения
lm += gen("name", regex=r"[A-Za-z ]+", max_tokens=30)

# ❌ Слишком строго: Может привести к ошибке или быть очень медленным
lm += gen("name", regex=r"^(John|Jane)$", max_tokens=10)

Сравнение с альтернативами​

ВозможностьGuidanceInstructorOutlinesLMQL
Ограничения через регулярные выражения✅ Да❌ Нет✅ Да✅ Да
Поддержка грамматик✅ КСГ❌ Нет✅ КСГ✅ КСГ
Валидация Pydantic❌ Нет✅ Да✅ Да❌ Нет
Заживление токенов✅ Да❌ Нет✅ Да❌ Нет
Локальные модели✅ Да⚠️ Ограничено✅ Да✅ Да
API-модели✅ Да✅ Да⚠️ Ограничено✅ Да
Python-синтаксис✅ Да✅ Да✅ Да❌ SQL-подобный
Кривая обученияНизкаяНизкаяСредняяВысокая

Когда выбирать Guidance:

  • Нужны ограничения через регулярные выражения/грамматики
  • Нужно заживление токенов
  • Создание сложных рабочих процессов с управлением потоком
  • Использование локальных моделей (Transformers, llama.cpp)
  • Предпочтение Python-синтаксиса

Когда выбирать альтернативы:

  • Instructor: Нужна валидация Pydantic с автоматическими повторными попытками
  • Outlines: Нужна валидация JSON-схем
  • LMQL: Предпочтение декларативного синтаксиса запросов

Характеристики производительности​

Снижение задержки:

  • На 30-50% быстрее традиционного промптинга для ограниченного вывода
  • Заживление токенов уменьшает ненужную регенерацию
  • Грамматические ограничения предотвращают генерацию невалидных токенов

Использование памяти:

  • Минимальные накладные расходы по сравнению с неограниченной генерацией
  • Компиляция грамматики кэшируется после первого использования
  • Эффективная фильтрация токенов во время инференса

Эффективность токенов:

  • Предотвращает трату токенов на невалидный вывод
  • Отсутствие необходимости в циклах повторных попыток
  • Прямой путь к валидному выводу

Ресурсы​

См. также​

  • references/constraints.md — Полные шаблоны регулярных выражений и грамматик
  • references/backends.md — Конфигурация для конкретных бэкендов
  • references/examples.md — Примеры, готовые к использованию в production