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)
Сравнение с альтернативами
| Возможность | Guidance | Instructor | Outlines | LMQL |
|---|---|---|---|---|
| Ограничения через регулярные выражения | ✅ Да | ❌ Нет | ✅ Да | ✅ Да |
| Поддержка грамматик | ✅ КСГ | ❌ Нет | ✅ КСГ | ✅ КСГ |
| Валидация Pydantic | ❌ Нет | ✅ Да | ✅ Да | ❌ Нет |
| Заживление токенов | ✅ Да | ❌ Нет | ✅ Да | ❌ Нет |
| Локальные модели | ✅ Да | ⚠️ Ограничено | ✅ Да | ✅ Да |
| API-модели | ✅ Да | ✅ Да | ⚠️ Ограничено | ✅ Да |
| Python-синтаксис | ✅ Да | ✅ Да | ✅ Да | ❌ SQL-подобный |
| Кривая обучения | Низкая | Низкая | Средняя | Высокая |
Когда выбирать Guidance:
- Нужны ограничения через регулярные выражения/грамматики
- Нужно заживление токенов
- Создание сложных рабочих процессов с управлением потоком
- Использование локальных моделей (Transformers, llama.cpp)
- Предпочтение Python-синтаксиса
Когда выбирать альтернативы:
- Instructor: Нужна валидация Pydantic с автоматическими повторными попытками
- Outlines: Нужна валидация JSON-схем
- LMQL: Предпочтение декларативного синтаксиса запросов
Характеристики производительности
Снижение задержки:
- На 30-50% быстрее традиционного промптинга для ограниченного вывода
- Заживление токенов уменьшает ненужную регенерацию
- Грамматические ограничения предотвращают генерацию невалидных токенов
Использование памяти:
- Минимальные накладные расходы по сравнению с неограниченной генерацией
- Компиляция грамматики кэшируется после первого использования
- Эффективная фильтрация токенов во время инференса
Эффективность токенов:
- Предотвращает трату токенов на невалидный вывод
- Отсутствие необходимости в циклах повторных попыток
- Прямой путь к валидному выводу
Ресурсы
- Документация: https://guidance.readthedocs.io
- GitHub: https://github.com/guidance-ai/guidance (18k+ звёзд)
- Notebooks: https://github.com/guidance-ai/guidance/tree/main/notebooks
- Discord: Доступна поддержка сообщества
См. также
references/constraints.md— Полные шаблоны регулярных выражений и грамматикreferences/backends.md— Конфигурация для конкретных бэкендовreferences/examples.md— Примеры, готовые к использованию в production