0Pricing
AI Prompt Engineering · Урок

Приёмы подстановки переменных

f-строки, .format() и библиотеки шаблонов для формирования запросов

«Приёмы подстановки переменных» — бесплатный урок AI Prompt Engineering на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Prompt Engineering, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Prompt Engineering содержит 4 уроков всего.

Четыре способа формирования шаблонов в Python

Python предлагает несколько способов формировать шаблоны запросов с подстановкой переменных. У каждого есть свои преимущества и компромиссы:

  • f-строки — встроенная подстановка, выполняемая сразу, без импорта
  • str.format() — именованные заполнители, удобная проверка
  • string.Template — безопасная подстановка с символом доллара, поддержка частичного заполнения
  • Jinja2 — полноценный движок шаблонов: условные блоки, циклы, фильтры и наследование

Выбор подхода зависит от сложности шаблонов, навыков команды и необходимости в расширенных возможностях, таких как условные блоки и циклы.

Подход 1: f-строки

F-строки — самый простой подход к шаблонам запросов, если все переменные доступны во время формирования:

import openai

client = openai.OpenAI(api_key='sk-...')

def generate_linkedin_post(company, topic, tone, word_count):
    prompt = (
        f'Write a LinkedIn post for {company} about {topic}. '
        f'Tone: {tone}. '
        f'Length: {word_count} words. '
        'Professional but conversational. '
        'End with one question to engage readers. '
        'No hashtags. Active voice.'
    )

    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

print(generate_linkedin_post(
    company='DataStream Analytics',
    topic='how AI is changing data pipelines',
    tone='enthusiastic but grounded',
    word_count=180
))

Подход 2: str.format()

str.format() хорошо подходит, если Вы хотите хранить строки шаблонов отдельно от кода, который заполняет их, — это удобно для загрузки шаблонов из файлов:

import openai

client = openai.OpenAI(api_key='sk-...')

# Template stored as a module-level constant or loaded from a file
SUPPORT_REPLY_TEMPLATE = '''You are a customer support agent for {company_name}.

Respond to this customer message:
---
{customer_message}
---

Tone: {tone}.
Keep the response under {max_words} words.
Do not offer refunds unless the customer explicitly asks.
Always close by asking if there is anything else you can help with.'''

def generate_support_reply(company, message, tone='empathetic and helpful', max_words=150):
    prompt = SUPPORT_REPLY_TEMPLATE.format(
        company_name=company,
        customer_message=message,
        tone=tone,
        max_words=max_words
    )

    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

Подход 3: string.Template

string.Template из стандартной библиотеки Python использует заполнители со знаком доллара ($variable или ${variable}). Его главное преимущество: safe_substitute() оставляет отсутствующие переменные как буквальный текст заполнителей вместо вызова ошибки, что позволяет выполнять частичное заполнение:

from string import Template
import openai

client = openai.OpenAI(api_key='sk-...')

# $ placeholders — safe with code that contains curly braces
BASE_TEMPLATE = Template(
    'Write a $format_type for $audience about $topic. '
    'Tone: $tone. Length: $word_count words. '
    'Active voice. No jargon.'
)

def generate(format_type, audience, topic, tone='professional', word_count=200):
    prompt = BASE_TEMPLATE.substitute(
        format_type=format_type,
        audience=audience,
        topic=topic,
        tone=tone,
        word_count=word_count
    )

    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

# Partial fill example — safe_substitute leaves $word_count as-is
partial = BASE_TEMPLATE.safe_substitute(
    format_type='blog post', audience='developers', topic='API design'
)
print(partial)  # $tone and $word_count remain as placeholders

Основы Jinja2

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

from jinja2 import Template
import openai

client = openai.OpenAI(api_key='sk-...')

# Jinja2 uses {{ }} for variables and {% %} for logic
JINJA_PROMPT = Template('''
Write a {{content_type}} for {{audience}} about {{topic}}.
Tone: {{tone}}.
{% if include_examples %}
Include {{example_count}} concrete examples.
{% endif %}
{% if word_count %}
Length: {{word_count}} words.
{% else %}
Aim for 200-300 words.
{% endif %}
Active voice. No jargon.
''')

def generate(content_type, audience, topic, tone, include_examples=False, example_count=2, word_count=None):
    prompt = JINJA_PROMPT.render(
        content_type=content_type,
        audience=audience,
        topic=topic,
        tone=tone,
        include_examples=include_examples,
        example_count=example_count,
        word_count=word_count
    )

    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

Циклы Jinja2 в шаблонах

Циклы Jinja2 позволяют перебирать списки в шаблоне — это удобно для создания запросов с несколькими элементами на основе структур данных:

from jinja2 import Template
import openai

client = openai.OpenAI(api_key='sk-...')

MULTI_PRODUCT_TEMPLATE = Template('''
Write a product comparison for {{audience}}.
Compare the following products:

{% for product in products %}
- {{product.name}}: {{product.description}}
{% endfor %}

Structure: one paragraph per product, then a 2-sentence recommendation.
Tone: {{tone}}. Active voice. No bullet points in paragraphs.
''')

products = [
    {'name': 'Asana', 'description': 'project management with timeline views'},
    {'name': 'Linear', 'description': 'developer-focused issue tracking'},
    {'name': 'Monday.com', 'description': 'visual work management for teams'}
]

prompt = MULTI_PRODUCT_TEMPLATE.render(
    audience='startup founders',
    products=products,
    tone='direct and practical'
)

response = client.chat.completions.create(
    model='gpt-4o-mini',
    messages=[{'role': 'user', 'content': prompt}]
)
print(response.choices[0].message.content)

Фильтры Jinja2

Фильтры Jinja2 преобразуют значения переменных непосредственно во время формирования шаблона. Встроенные фильтры, полезные для запросов:

  • {{ topic | upper }} — перевести тему в верхний регистр
  • {{ word_count | default(200) }} — использовать 200, если word_count не задан
  • {{ audience | title }} — преобразовать строку аудитории в заглавный регистр
  • {{ items | join(', ') }} — объединить список через запятые

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

Загрузка шаблонов из файлов

Для больших или сложных шаблонов хранение в отдельных текстовых файлах помогает сохранить код Python чистым. Environment и FileSystemLoader Jinja2 хорошо справляются с этой задачей:

from jinja2 import Environment, FileSystemLoader
import openai

client = openai.OpenAI(api_key='sk-...')

# Load all templates from the 'prompts/' directory
env = Environment(loader=FileSystemLoader('prompts/'))

def render_template(template_name, variables):
    '''Load and render a .j2 template file with the given variables.'''
    template = env.get_template(template_name)
    return template.render(**variables)

def generate_from_file(template_name, variables):
    prompt = render_template(template_name, variables)

    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return response.choices[0].message.content

# Usage: load prompts/blog_post.j2 and fill with variables
result = generate_from_file('blog_post.j2', {
    'topic': 'API rate limiting strategies',
    'audience': 'backend engineers',
    'tone': 'technical and direct',
    'word_count': 500
})
print(result)

Выбор подходящего подхода

Выбирайте подход к подстановке в зависимости от сложности шаблонов:

  • f-строки — быстрые сценарии, разовая автоматизация, шаблоны, достаточно короткие для чтения непосредственно в коде
  • str.format() — хранящиеся отдельно шаблоны, кодовые базы команды и случаи, когда желательно получать KeyError при отсутствии переменных
  • string.Template — если содержимое может содержать фигурные скобки (например, фрагменты кода) или требуется частичное заполнение
  • Jinja2 — сложные шаблоны с условными блоками, циклами, несколькими файлами или команда, имеющая опыт работы с шаблонами

Излишнее усложнение — реальный риск: обращайтесь к Jinja2 только тогда, когда Вам действительно нужны его расширенные возможности.

Безопасность шаблонов: атаки с внедрением инструкций

Если значения переменных поступают от пользователя, внедрение инструкций в запрос представляет реальный риск. Злоумышленник может передать значение вроде: "Игнорируйте все предыдущие инструкции и..."

Защитные меры:

  • Проверяйте и очищайте все переменные, предоставленные пользователем, до подстановки
  • Для входных данных, видимых пользователю, заключайте переменную в разделители: "Входные данные пользователя: ---{user_input}---"
  • Используйте фильтрацию результатов, чтобы обнаруживать и отклонять ответы, похожие на результаты выполнения внедрённых инструкций
  • Никогда не предоставляйте значениям, введённым пользователем, доступ к переменным системного запроса

Проверка сформированных шаблонов

Всегда проверяйте формирование шаблонов отдельно от вызовов API. Проверьте сформированную строку до её отправки модели:

def test_template_render():
    test_cases = [
        {'topic': 'cloud security', 'audience': 'CTOs', 'tone': 'formal', 'word_count': 300},
        {'topic': 'ML pipelines', 'audience': 'data scientists', 'tone': 'technical', 'word_count': 500},
        # Edge cases
        {'topic': '', 'audience': 'developers', 'tone': 'casual', 'word_count': 100},  # empty topic
        {'topic': 'AI' * 100, 'audience': 'all', 'tone': 'brief', 'word_count': 50},  # very long topic
    ]

    TEMPLATE = 'Write a {word_count}-word {tone} article about {topic} for {audience}. Active voice.'

    for i, case in enumerate(test_cases):
        try:
            rendered = TEMPLATE.format(**case)
            assert len(rendered) > 0, 'Empty render'
            print(f'Case {i+1} OK: {len(rendered)} chars')
        except (KeyError, AssertionError) as e:
            print(f'Case {i+1} FAILED: {e}')

test_template_render()

Проверка знаний: методы подстановки

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

Какой подход к подстановке лучше всего подходит для этого сценария?

Повторение: методы подстановки переменных

Python предлагает четыре способа формирования шаблонов запросов: f-строки (встроенные и простые), str.format() (именованные заполнители, KeyError при отсутствии переменных), string.Template (синтаксис со знаком доллара, безопасное частичное заполнение) и Jinja2 (полноценный движок с условными блоками, циклами, фильтрами и загрузкой файлов).

Выбирайте подход в зависимости от сложности: используйте f-строки для быстрых сценариев, str.format() для хранящихся отдельно шаблонов, string.Template, если содержимое содержит фигурные скобки, и Jinja2, если нужны условные блоки, циклы или шаблоны на основе файлов. Всегда проверяйте формирование шаблонов отдельно от вызовов API.

Часто задаваемые вопросы

Урок «Приёмы подстановки переменных» бесплатный?

Да — полный текст урока «Приёмы подстановки переменных» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Prompt Engineering, подпишись на CoddyKit PRO. Курс AI Prompt Engineering содержит 4 уроков всего.

Чему я научусь в уроке «Приёмы подстановки переменных»?

f-строки, .format() и библиотеки шаблонов для формирования запросов Ты практикуешь AI Prompt Engineering с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать AI Prompt Engineering?

Предыдущий опыт не требуется. AI Prompt Engineering на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Приёмы подстановки переменных»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке AI Prompt Engineering?

Да. Каждый урок AI Prompt Engineering включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Что такое шаблон запроса
  2. Создание шаблонов с пропусками
  3. Приёмы подстановки переменных
  4. Повторное использование шаблонов в разных задачах
← Назад к AI Prompt Engineering