LangChainMiddleTechnical

В чём разница между zero-shot, few-shot и chain-of-thought промптингом в LangChain?

Zero-shot — задача без примеров; few-shot — с примерами вход/выход; CoT — с инструкцией думать пошагово. LangChain реализует их через FewShotChatMessagePromptTemplate и системные промпты с явной структурой рассуждения.

Три стратегии промптинга

Zero-shot, few-shot и chain-of-thought (CoT) — это подходы к составлению инструкций для LLM, которые определяют, сколько примеров и какую структуру рассуждения получает модель. LangChain реализует каждый из них через соответствующие классы промптов.

Zero-shot промптинг

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

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

zero_shot_prompt = ChatPromptTemplate.from_messages([
    ("system", "Ты классификатор тональности. Отвечай одним словом: positive, negative или neutral."),
    ("human", "{text}"),
])

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = zero_shot_prompt | llm | StrOutputParser()

result = chain.invoke({"text": "Отличный продукт, очень доволен!"})
print(result)  # positive

Few-shot промптинг

В промпт включаются конкретные примеры «вход → выход». LangChain предоставляет FewShotChatMessagePromptTemplate и FewShotPromptTemplate, которые динамически форматируют примеры. Дополнительно можно использовать SemanticSimilarityExampleSelector, чтобы выбирать самые релевантные примеры из большого набора.

from langchain_core.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate

examples = [
    {"input": "2+2", "output": "4"},
    {"input": "100 / 5", "output": "20"},
    {"input": "3 * 7", "output": "21"},
]

example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}"),
])

few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

final_prompt = ChatPromptTemplate.from_messages([
    ("system", "Ты калькулятор. Отвечай только числом."),
    few_shot_prompt,
    ("human", "{question}"),
])

chain = final_prompt | llm | StrOutputParser()
print(chain.invoke({"question": "15 * 8"}))  # 120

Chain-of-Thought промптинг

Модель явно просят «думать вслух» перед ответом. Это резко улучшает точность на задачах с многошаговой логикой: математика, анализ кода, юридические рассуждения. CoT активируется либо фразой «Let's think step by step» в системном промпте, либо примерами с пошаговыми объяснениями.

cot_prompt = ChatPromptTemplate.from_messages([
    (
        "system",
        """Реши задачу пошагово.
Шаг 1: Пойми условие.
Шаг 2: Составь план решения.
Шаг 3: Выполни каждый шаг.
Шаг 4: Сформулируй финальный ответ после слова ОТВЕТ:""",
    ),
    ("human", "{problem}"),
])

cot_chain = cot_prompt | llm | StrOutputParser()

result = cot_chain.invoke({
    "problem": "В магазине 3 ящика по 24 яблока. Продали 40 яблок. Сколько осталось?"
})
print(result)
# Шаг 1: 3 ящика, 24 яблока в каждом...
# ...
# ОТВЕТ: 32

Комбинирование: Few-shot CoT

cot_examples = [
    {
        "input": "5 * 12 + 8",
        "output": "Шаг 1: 5 * 12 = 60. Шаг 2: 60 + 8 = 68. ОТВЕТ: 68",
    },
]

example_prompt = ChatPromptTemplate.from_messages([
    ("human", "{input}"),
    ("ai", "{output}"),
])

few_shot_cot = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=cot_examples,
)

final = ChatPromptTemplate.from_messages([
    ("system", "Решай арифметику пошагово."),
    few_shot_cot,
    ("human", "{question}"),
])

chain = final | llm | StrOutputParser()
print(chain.invoke({"question": "7 * 9 - 15"}))

Подводные камни

  • Zero-shot не работает на сложной логике: без примеров и пошагового рассуждения модели ошибаются на задачах с несколькими зависимыми шагами — CoT обязателен.
  • Порядок few-shot примеров важен: исследования показывают, что последние примеры влияют на ответ сильнее первых. Более сложные примеры лучше ставить ближе к концу.
  • Плохие примеры хуже нуля: некорректный few-shot пример «обучает» модель неправильному поведению — она будет воспроизводить ошибку из примера.
  • CoT увеличивает количество токенов: пошаговые рассуждения в ответе могут быть в 3–10 раз длиннее прямого ответа. Это увеличивает cost и latency.
  • SemanticSimilarityExampleSelector требует векторного хранилища: если примеров много (100+), стоит использовать динамический выбор, иначе промпт переполнится.
  • CoT ненадёжен на маленьких моделях: GPT-3.5-уровневые модели часто «теряют нить» рассуждения на середине. Используйте CoT только с GPT-4o, Claude 3 Sonnet и выше.
  • Форматирование CoT-ответа: если нужен только финальный ответ без рассуждений, добавляйте постобработку — парсинг строки после «ОТВЕТ:», иначе в downstream-код попадает вся цепочка мышления.

Common mistakes

  • Объяснять prompting patterns только синтаксисом без shape, dtype, состояния или режима выполнения.
  • Игнорировать leakage, воспроизводимость, пустые входы и скрытые копии данных.
  • Не проверять production-симптомы: latency, память, ретраи, дрейф качества и несовпадение версий.

What the interviewer is testing

  • Может ли связать prompting patterns с реальным контрактом входов и выходов.
  • Упоминает ли тесты, метрики, reproducibility и диагностику ошибок.
  • Видит ли различие между demo-кодом в ноутбуке и production-пайплайном.

Sources

Related topics