Приёмы подстановки переменных
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 — локальная установка не требуется.
Все уроки этого курса
- Что такое шаблон запроса
- Создание шаблонов с пропусками
- Приёмы подстановки переменных
- Повторное использование шаблонов в разных задачах