AI Prompt Engineering · Урок

Шаблоны «вывод — ввод»

Извлекайте структурированные данные из шага 1 для передачи на шаг 2

Урок 2 из 413 шагов

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

Главная задача: извлечение и внедрение

В цепочке промптов Шаг 1 создаёт текст. Шагу 2 нужен конкретный фрагмент этого текста в качестве входных данных. Задача заключается в том, чтобы надёжно извлечь из результата Шага 1 именно нужное поле и корректно внедрить его в промпт Шага 2.

Если Шаг 1 возвращает неструктурированный текст, извлечение становится ненадёжным. Решение — спроектировать промпты Шага 1 так, чтобы они возвращали структурированный результат, обычно JSON, который можно разобрать и программно внедрить.

Проектирование шага 1 для машинной обработки

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

import anthropic
import json

client = anthropic.Anthropic(api_key='YOUR_API_KEY')

step1_prompt = '''
<task>
Analyze the customer review below.
</task>

<review>
The onboarding was confusing and took 3 hours. The core feature works great though.
</review>

<output_format>
Return ONLY a JSON object. No other text.
{
  "sentiment": "positive|negative|mixed",
  "issues": ["string"],
  "positives": ["string"],
  "priority": "high|medium|low"
}
</output_format>
'''

response = client.messages.create(
    model='claude-opus-4-5',
    max_tokens=300,
    messages=[{'role': 'user', 'content': step1_prompt}]
)
print(response.content[0].text)

Разбор результата шага 1

После того как шаг 1 вернёт данные в формате JSON, разберите их в Python и извлеките поля, необходимые для шага 2:

import json

def parse_step1_output(raw_text):
    # Models sometimes wrap JSON in extra text -- strip it
    text = raw_text.strip()
    # Find the first { and last } to extract JSON object
    start = text.find("{")
    end = text.rfind("}")
    if start != -1 and end != -1 and end > start:
        text = text[start:end+1]
    try:
        return json.loads(text)
    except json.JSONDecodeError as e:
        raise ValueError("Step 1 output is not valid JSON: " + str(e))

# Example usage
raw = '{"sentiment": "mixed", "issues": ["confusing onboarding"], "positives": ["core feature"], "priority": "high"}'
parsed = parse_step1_output(raw)
print(parsed['issues'])
print(parsed['priority'])

Передача извлечённых полей в шаг 2

После разбора подставьте конкретные поля в шаблон запроса шага 2. Используйте f-строки Python или переменные шаблона:

def build_step2_prompt(parsed_step1):
    issues = '\n'.join(f'- {issue}' for issue in parsed_step1['issues'])
    priority = parsed_step1['priority']
    sentiment = parsed_step1['sentiment']

    return f'''
<context>
A customer review was analyzed. Overall sentiment: {sentiment}. Priority: {priority}.
</context>

<task>
Write a customer support response addressing these specific issues:
{issues}
Acknowledge the positives before addressing the issues.
</task>

<output_format>
Plain text response, 3 sentences maximum, professional tone.
</output_format>
'''

parsed = {'sentiment': 'mixed', 'issues': ['confusing onboarding'], 'priority': 'high', 'positives': ['core feature']}
print(build_step2_prompt(parsed))

Полная двухшаговая цепочка

Объединим разбор и подстановку в полноценный двухшаговый конвейер:

import anthropic, json

client = anthropic.Anthropic(api_key='YOUR_API_KEY')

def call(prompt, max_tokens=500):
    r = client.messages.create(
        model='claude-opus-4-5', max_tokens=max_tokens,
        messages=[{'role': 'user', 'content': prompt}]
    )
    return r.content[0].text

def review_response_chain(review_text):
    # Step 1: Analyze
    step1 = call(f'Analyze this review. Return JSON: {{"sentiment": str, "issues": [str], "priority": str}}\n\nReview: {review_text}')
    parsed = json.loads(step1.strip())

    # Inject into Step 2
    issues_str = ', '.join(parsed['issues'])
    step2_prompt = f'Write a 2-sentence support reply. Issues to address: {issues_str}. Priority: {parsed["priority"]}.'

    # Step 2: Draft response
    reply = call(step2_prompt)
    return reply

print(review_response_chain('Login is broken. App crashes on startup.'))

Обработка подстановки вложенных данных JSON

Если шаг 1 возвращает вложенные объекты, извлекайте только необходимые шагу 2 данные, чтобы подставляемый запрос оставался кратким:

step1_output = {
    'document': {
        'title': 'Q3 Report',
        'sections': [
            {'name': 'Revenue', 'value': '$4.2M', 'change': '+12%'},
            {'name': 'Users', 'value': '85,000', 'change': '+5%'},
            {'name': 'Churn', 'value': '3.2%', 'change': '-0.8%'}
        ]
    },
    'summary': 'Strong revenue quarter with moderate user growth.'
}

# Extract only what Step 2 needs — not the full nested object
def extract_for_step2(data):
    sections = data['document']['sections']
    metrics = '\n'.join(f"{s['name']}: {s['value']} ({s['change']})" for s in sections)
    return {
        'metrics': metrics,
        'summary': data['summary']
    }

step2_input = extract_for_step2(step1_output)
print(step2_input)

Как избежать избыточной подстановки

Распространённая ошибка — подставить в шаг 2 весь результат шага 1. Это раздувает запрос шага 2 и может запутать модель ненужными полями.

  • Плохо: f'Here is the analysis: {str(all_of_step1_output)}'
  • Хорошо: извлекайте только конкретные поля, необходимые шагу 2, и подставляйте их с понятными метками

Шаг 2 должен получать ровно ту информацию, которая ему нужна, — не больше и не меньше.

Условное ветвление на основе результата

Разобранный результат шага 1 может определять, какой запрос шага 2 будет выполнен, превращая линейную цепочку в разветвлённый конвейер:

def route_chain(user_message):
    # Step 1: Classify intent
    classification = json.loads(call(
        f'Classify this message as billing, technical, or general. Return JSON: {{"intent": str}}\n\nMessage: {user_message}'
    ))

    intent = classification['intent']

    # Route to specialized Step 2 prompt
    if intent == 'billing':
        prompt = f'You are a billing specialist. Address: {user_message}'
    elif intent == 'technical':
        prompt = f'You are a senior engineer. Provide technical guidance for: {user_message}'
    else:
        prompt = f'You are a general support agent. Respond to: {user_message}'

    return call(prompt)

print(route_chain('My invoice shows a wrong amount.'))

Накопление состояния между шагами

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

def run_pipeline(initial_input):
    state = {'input': initial_input}

    # Step 1
    state['entities'] = json.loads(call(
        f'Extract entities as JSON: {{"people": [], "companies": []}}\n\n{state["input"]}'
    ))

    # Step 2 uses entities from Step 1
    companies_str = ', '.join(state['entities'].get('companies', []))
    state['company_types'] = call(
        f'Classify these companies as startup/enterprise: {companies_str}'
    )

    # Step 3 uses output from Steps 1 and 2
    state['summary'] = call(
        f'Write a 2-sentence summary.\nEntities: {state["entities"]}\nClassifications: {state["company_types"]}'
    )

    return state

result = run_pipeline('Apple and OpenAI announced a partnership with Elon Musk.')
print(result['summary'])

Утилиты для извлечения данных JSON

Создайте повторно используемую утилиту извлечения данных для инфраструктуры цепочки:

import re, json

def extract_json(text):
    "Extract JSON from model output, handling extra text around the object."
    # Try direct parse first
    try:
        return json.loads(text.strip())
    except json.JSONDecodeError:
        pass
    # Try finding JSON object by bracket matching
    start = text.find("{")
    end = text.rfind("}")
    if start != -1 and end != -1 and end > start:
        try:
            return json.loads(text[start:end+1])
        except json.JSONDecodeError:
            pass
    # Try finding JSON array
    start = text.find("[")
    end = text.rfind("]")
    if start != -1 and end != -1 and end > start:
        try:
            return json.loads(text[start:end+1])
        except json.JSONDecodeError:
            pass
    raise ValueError("Could not extract JSON from: " + text[:200])

print(extract_json('{"key": "value"}'))

Проверка схем передачи результата во входные данные

Конвейеры, в которых результат одного шага становится входными данными другого, требуют двух уровней проверок:

  • Проверяйте каждый шаг отдельно: возвращает ли шаг 1 стабильный JSON, пригодный для разбора? Формирует ли шаг 2 правильный результат для заданных извлечённых входных данных?
  • Проверяйте цепочку целиком: выдаёт ли сквозной конвейер правильные результаты для репрезентативных входных данных?

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

def test_step1(review_text, expected_sentiment):
    raw = call(f'Analyze review. Return JSON: {{"sentiment": str}}\n\n{review_text}')
    parsed = extract_json(raw)
    assert parsed['sentiment'] == expected_sentiment, f'Expected {expected_sentiment}, got {parsed["sentiment"]}'
    print(f'PASS: sentiment={parsed["sentiment"]}')

# Run unit test for Step 1
test_step1('The product is excellent!', 'positive')
test_step1('This is terrible.', 'negative')

Быстрая проверка

Какой формат результата рекомендуется для шага 1 цепочки запросов, если результат будет извлекаться программно и подставляться в шаг 2?

Передача результата во входные данные — основные выводы

Надёжные схемы передачи результата во входные данные делают цепочки запросов готовыми к использованию в боевой среде:

  • Проектируйте запросы шага 1 так, чтобы они возвращали JSON с явно заданной схемой, а не обычный текст
  • Разбирайте результат шага 1 перед подстановкой: удаляйте маркеры блоков Markdown и обрабатывайте ошибки разбора JSON
  • Подставляйте только конкретные поля, необходимые шагу 2, и избегайте избыточной подстановки
  • Используйте словари состояния для накопления и передачи данных в длинных цепочках
  • Разобранный результат может управлять условным ветвлением и направлять выполнение к специализированным запросам шага 2
  • Создавайте повторно используемые утилиты извлечения данных JSON, учитывающие несогласованность результатов модели
  • Проверяйте каждый шаг отдельно, а затем проверяйте весь конвейер целиком
Можно начать бесплатно

Изучай AI Prompt Engineering с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
53
Уроки
199

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

Урок «Шаблоны «вывод — ввод»» бесплатный?

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

Чему я научусь в уроке «Шаблоны «вывод — ввод»»?

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

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

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

Сколько времени занимает урок «Шаблоны «вывод — ввод»»?

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

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

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

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

  1. Что такое цепочка запросов
  2. Шаблоны «вывод — ввод»
  3. Цепочки последовательных преобразований
  4. Обработка ошибок в цепочках запросов
← Назад к AI Prompt Engineering