Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Prompt Engineering
prompt_eng

Prompt Engineering

Техники эффективного взаимодействия с LLM: zero-shot, few-shot, chain-of-thought, ReAct, prompt templates

Prompt Engineering

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

#Введение

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

Почему это важно:

  • Один и тот же вопрос, заданный по-разному, может дать кардинально разные ответы
  • Хороший промпт может компенсировать ограничения модели
  • Правильный промптинг снижает количество токенов и стоимость API calls

#1. Zero-Shot Prompting

Zero-shot — самый простой подход: вы даёте модели только задачу, без примеров.

from openai import OpenAI client = OpenAI() response = client.chat.completions.create( model="gpt-4", messages=[ {"role": "user", "content": "Переведи на французский: Hello, World!"} ] ) print(response.choices[0].message.content) # Output: Bonjour, le monde!

Когда использовать:

  • Простые, распространённые задачи (перевод, суммаризация)
  • Модель уже знает домен (общие знания)
  • Нужно быстро получить ответ без подготовки примеров

Ограничения:

  • Может не работать на niche tasks (специфичные форматы, домены)
  • Модель может не понять ожидаемый формат ответа

#2. Few-Shot Prompting

Few-shot — вы предоставляете несколько примеров input-output перед задачей. Это показывает модели паттерн, который нужно продолжить.

messages = [ {"role": "user", "content": """ English: Hello → French: Bonjour English: World → French: Monde English: Good morning → French: Bonjour matin English: Thank you → French: ? """} ]

Пример с кастомным форматом:

from langchain import PromptTemplate template = PromptTemplate.from_template(""" Примеры классификации тональности: Текст: "Отличный продукт, очень доволен!" → Тональность: позитивная Текст: "Ужасное качество, не рекомендую" → Тональность: негативная Текст: "Нормально, ничего особенного" → Тональность: нейтральная Текст: "{text}" → Тональность: """) prompt = template.format(text="Быстрая доставка, товар как в описании") # Модель продолжит паттерн: позитивная

Когда использовать:

  • Custom formats (JSON, XML, специфичные шаблоны)
  • Niche domains (медицина, юриспруденция)
  • Когда zero-shot даёт непредсказуемые результаты

Best practices:

  • 3-5 примеров обычно достаточно
  • Примеры должны быть репрезентативными
  • Размещайте примеры в порядке возрастания сложности

#3. Chain-of-Thought (CoT)

Chain-of-Thought — техника, при которой модель генерирует промежуточные шаги рассуждения перед финальным ответом. Особенно эффективна для математических и логических задач.

#Zero-shot CoT

Добавьте фразу "Let's think step by step" (или "Давай рассуждать пошагово"):

messages = [ {"role": "user", "content": """ Вопрос: У меня 5 яблок, я съел 2, потом купил 3. Сколько яблок осталось? Давай рассуждать пошагово. """} ] # Модель сгенерирует: # Рассуждение: # 1. Было 5 яблок # 2. Съел 2: 5 - 2 = 3 # 3. Купил 3: 3 + 3 = 6 # Ответ: 6 яблок

#Few-shot CoT

Покажите примеры с рассуждениями:

messages = [ {"role": "user", "content": """ Вопрос: Роберт стоит 5-м в очереди слева и 7-м справа. Сколько человек в очереди? Рассуждение: Если Роберт 5-й слева, значит слева от него 4 человека. Если он 7-й справа, значит справа от него 6 человек. Всего: 4 + 1 (Роберт) + 6 = 11 человек. Ответ: 11 Вопрос: Поезд едет 60 км/ч. Какое расстояние он проедет за 2.5 часа? Рассуждение: Расстояние = Скорость × Время. 60 км/ч × 2.5 ч = 150 км. Ответ: 150 км Вопрос: В комнате 3 лампы. Каждая потребляет 60 Вт. Сколько Вт потребляют все лампы? Рассуждение: """} ]

Почему это работает:

  • CoT активирует "System 2" мышление (медленное, аналитическое)
  • Модель вынуждена разбивать задачу на подзадачи
  • Промежуточные шаги служат self-correction механизмом

Интеграция с FastAPI:

from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class ReasoningRequest(BaseModel): question: str @app.post("/reason") async def reason(request: ReasoningRequest): response = client.chat.completions.create( model="gpt-4", messages=[{ "role": "user", "content": f"{request.question}\nДавай рассуждать пошагово." }] ) return {"answer": response.choices[0].message.content}

#4. ReAct (Reason + Act)

ReAct — паттерн для задач, требующих взаимодействия с внешними инструментами. Модель циклически генерирует:

  1. Thought (рассуждение о том, что делать)
  2. Action (вызов инструмента)
  3. Observation (результат действия)
  4. Повторяет, пока не получит ответ

#Пример ReAct цикла

Question: Какая погода в городе, где находится штаб-квартира Apple?

Thought: Мне нужно найти город, где находится штаб-квартира Apple
Action: search(query="Apple headquarters location")
Observation: Apple Park находится в Купертино, Калифорния

Thought: Теперь нужно узнать погоду в Купертино
Action: get_weather(location="Cupertino, CA")
Observation: 22°C, ясно, влажность 45%

Thought: У меня есть вся информация для ответа
Answer: В Купертино (где находится штаб-квартира Apple) сейчас 22°C, ясно.

#Реализация с LangChain

from langchain.agents import initialize_agent, Tool from langchain.llms import OpenAI from langchain.utilities import SerpAPIWrapper llm = OpenAI(temperature=0) search = SerpAPIWrapper() tools = [ Tool( name="Search", func=search.run, description="Полезно для поиска фактов в интернете" ), Tool( name="Weather", func=get_weather, # ваша функция description="Полезно для получения текущей погоды" ) ] agent = initialize_agent( tools, llm, agent="zero-shot-react-description", verbose=True ) result = agent.run("Какая погода в городе, где находится штаб-квартира Apple?")

#Реализация с FastAPI

from fastapi import FastAPI, BackgroundTasks from pydantic import BaseModel import httpx app = FastAPI() class AgentRequest(BaseModel): query: str class WeatherTool: async def get_weather(self, location: str) -> str: async with httpx.AsyncClient() as client: resp = await client.get( f"https://api.weather.com/{location}" ) return resp.json()["description"] class SearchTool: async def search(self, query: str) -> str: async with httpx.AsyncClient() as client: resp = await client.get( "https://api.serper.dev/search", params={"q": query} ) return resp.json()["organic"][0]["snippet"] @app.post("/agent") async def run_agent(request: AgentRequest): tools = {"weather": WeatherTool(), "search": SearchTool()} # ReAct цикл thoughts = [] for _ in range(5): # максимум 5 итераций # Генерируем thought + action response = client.chat.completions.create( model="gpt-4", messages=[{ "role": "user", "content": f"Question: {request.query}\n" + "\n".join(thoughts) + "\nThought:" }] ) thought = response.choices[0].message.content thoughts.append(f"Thought: {thought}") # Парсим action и выполняем if "Action:" in thought: action = parse_action(thought) observation = await tools[action.name](**action.args) thoughts.append(f"Observation: {observation}") else: return {"answer": thought, "steps": thoughts} return {"answer": thoughts[-1], "steps": thoughts}

#5. Prompt Templates

Prompt templates — параметризированные шаблоны для генерации промптов. Позволяют переиспользовать структуру промпта с разными данными.

#Базовый пример

from langchain import PromptTemplate template = """Ты — опытный {role}. Твоя задача — {task}. Контекст: {context} Вопрос пользователя: {question} Ответ:""" prompt = PromptTemplate( template=template, input_variables=["role", "task", "context", "question"] ) formatted = prompt.format( role="Python разработчик", task="объяснить концепцию", context="FastAPI — современный веб-фреймворк", question="Что такое dependency injection?" )

#Шаблон для код-ревью

code_review_template = PromptTemplate.from_template(""" Ты — senior Python разработчик. Проведи код-ревью следующего кода. Код: ```python {code}

Проанализируй:

  1. Потенциальные баги
  2. Производительность
  3. Читаемость
  4. Безопасность
  5. Соответствие PEP 8

Формат ответа:

  • Баги: ...
  • Производительность: ...
  • Читаемость: ...
  • Безопасность: ...
  • PEP 8: ...
  • Рекомендации: ... """)

### FastAPI endpoint с шаблоном

```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

app = FastAPI()

class CodeReviewRequest(BaseModel):
    code: str = Field(..., description="Код для ревью")
    language: str = Field(default="python")

@app.post("/code-review")
async def code_review(request: CodeReviewRequest):
    prompt = code_review_template.format(
        code=request.code
    )
    
    response = client.chat.completions.create(
        model="gpt-4",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.2  # низкая температура для консистентности
    )
    
    return {"review": response.choices[0].message.content}

#6. Best Practices

#Структура хорошего промпта

1. Роль/Персона
   "Ты — опытный Python разработчик..."

2. Задача
   "Твоя задача — написать функцию..."

3. Контекст
   "Эта функция будет использоваться в..."

4. Ограничения
   "Не используй внешние библиотеки..."

5. Формат вывода
   "Ответ должен быть в формате JSON..."

6. Примеры (few-shot)
   "Пример входа: {...}, пример выхода: {...}"

#Полная структура

prompt = """ Ты — senior Python разработчик с 10-летним опытом (роль). Твоя задача — оптимизировать следующий SQL-запрос (задача). Контекст: Запрос выполняется 1000+ раз в секунду в production (контекст). Ограничения: - Не меняй логику запроса - Используй только стандартные индексы - Объясни каждое изменение (ограничения) Формат ответа: 1. Оптимизированный запрос 2. Список изменений 3. Ожидаемое улучшение (формат) Исходный запрос: {query} """

#Частые ошибки

ОшибкаКак исправить
Слишком общий промптДобавьте контекст и ограничения
Нет формата выводаЯвно укажите ожидаемый формат
Слишком много инструкцийРазбейте на несколько шагов
Нет примеров для niche tasksДобавьте few-shot примеры
Игнорирование CoT для сложных задачИспользуйте "рассуждай пошагово"

#7. Тестирование промптов

#A/B тестирование

import asyncio from typing import List async def test_prompts( prompts: List[str], test_cases: List[dict] ) -> dict: results = {p: [] for p in prompts} for case in test_cases: tasks = [ client.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": p.format(**case)}] ) for p in prompts ] responses = await asyncio.gather(*tasks) for prompt, response in zip(prompts, responses): results[prompt].append( evaluate_response(response, case["expected"]) ) return { prompt: sum(scores) / len(scores) for prompt, scores in results.items() }

#Метрики качества

  • Accuracy: процент правильных ответов
  • Consistency: стабильность ответов на перефразированные вопросы
  • Token efficiency: отношение полезных токенов к общим
  • Latency: время генерации ответа

Далее: Function Calling