0Pricing
AI Agents · Урок

Управление контекстом и историей клиента

Персонализированные ответы с учётом прошлых покупок, обращений и предпочтений.

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

Почему контекст очеловечивает агентов

Разница между посредственным и превосходным агентом службы поддержки — контекст. Когда агент говорит: «Я вижу, что ваша подписка продлевается на следующей неделе — хотите приостановить её до этого момента?», клиент чувствует, что его знают, а не просто обслуживают.

В этом уроке рассматривается создание подробного слоя контекста клиента для агентов.

Схема профиля клиента

Определите стандартный профиль клиента, объединяющий данные из нескольких источников. Агент получает этот словарь в начале каждого разговора.

from dataclasses import dataclass, field
from datetime import date

@dataclass
class CustomerProfile:
    customer_id: str
    name: str
    email: str
    join_date: date
    subscription_tier: str          # 'free', 'pro', 'enterprise'
    account_age_days: int
    lifetime_value_usd: float
    previous_tickets: list[dict] = field(default_factory=list)
    recent_purchases: list[dict]  = field(default_factory=list)
    preferences: dict             = field(default_factory=dict)

    @property
    def is_long_term_customer(self) -> bool:
        return self.account_age_days > 365

if __name__ == '__main__':
    from datetime import date
    profile = CustomerProfile(
        customer_id='cust_1', name='Jane Doe', email='jane@example.com',
        join_date=date(2023, 1, 15), subscription_tier='pro',
        account_age_days=400, lifetime_value_usd=1250.50,
    )
    print(f'{profile.name} ({profile.subscription_tier}) - long-term customer: {profile.is_long_term_customer}')

Получение истории покупок

Получите последние N заказов из серверной части интернет-магазина. Включите дату заказа, товары, общую сумму и статус. Это позволит агенту понять, что покупал клиент, и есть ли проблемы с недавними заказами.

import requests

SHOP_API = 'https://api.yourshop.com'
SHOP_KEY  = 'YOUR_SHOP_API_KEY'

def get_purchase_history(customer_id: str, limit: int = 10) -> list[dict]:
    resp = requests.get(
        f'{SHOP_API}/customers/{customer_id}/orders',
        headers={'Authorization': f'Bearer {SHOP_KEY}'},
        params={'limit': limit, 'sort': '-created_at'}
    )
    resp.raise_for_status()
    orders = resp.json()['orders']
    return [
        {
            'order_id':   o['id'],
            'date':       o['created_at'][:10],
            'total_usd':  o['total'],
            'status':     o['status'],
            'items':      [i['name'] for i in o['line_items']]
        }
        for o in orders
    ]

Получение предыдущих обращений в поддержку

Получите последние N обращений в поддержку, чтобы понять, какие проблемы повторяются. Если одна и та же проблема клиента была решена уже трижды, это проблема продукта — передайте ее на более высокий уровень и установите соответствующий флаг.

def get_support_history(customer_id: str, limit: int = 5) -> list[dict]:
    resp = requests.get(
        f'{SHOP_API}/customers/{customer_id}/tickets',
        headers={'Authorization': f'Bearer {SHOP_KEY}'},
        params={'limit': limit, 'sort': '-created_at'}
    )
    resp.raise_for_status()
    tickets = resp.json()['tickets']
    return [
        {
            'ticket_id': t['id'],
            'subject':   t['subject'],
            'status':    t['status'],
            'resolved':  t.get('resolved_at', ''),
            'category':  t.get('category', 'general')
        }
        for t in tickets
    ]

def has_recurring_issue(tickets: list[dict], category: str) -> bool:
    return sum(1 for t in tickets if t['category'] == category) >= 3

Чтение тарифа и статуса подписки

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

def get_subscription_info(customer_id: str) -> dict:
    resp = requests.get(
        f'{SHOP_API}/customers/{customer_id}/subscription',
        headers={'Authorization': f'Bearer {SHOP_KEY}'}
    )
    if resp.status_code == 404:
        return {'tier': 'free', 'status': 'active', 'renewal_date': None}
    resp.raise_for_status()
    sub = resp.json()
    return {
        'tier':         sub['plan'],
        'status':       sub['status'],        # active / past_due / canceled
        'renewal_date': sub.get('current_period_end', '')[:10],
        'cancel_at':    sub.get('cancel_at_period_end', False)
    }

Расчет срока существования аккаунта

Срок существования аккаунта показывает лояльность клиента. К клиенту, который пользуется Вашими услугами с 2021 года, следует относиться иначе, чем к тому, кто зарегистрировался вчера. При необходимости упоминайте продолжительность сотрудничества, чтобы установить контакт.

from datetime import datetime, timezone

def calculate_account_age(join_date_str: str) -> dict:
    join = datetime.fromisoformat(join_date_str.replace('Z', '+00:00'))
    now  = datetime.now(timezone.utc)
    delta = now - join
    years  = delta.days // 365
    months = (delta.days % 365) // 30
    return {
        'days':   delta.days,
        'years':  years,
        'months': months,
        'label':  f'{years} year(s) and {months} month(s)' if years else f'{months} month(s)'
    }

age = calculate_account_age('2021-03-15T00:00:00Z')
print(age['label'])  # e.g. '5 year(s) and 2 month(s)'

Формирование строки контекста для LLM

Преобразуйте профиль клиента в краткий блок контекста, который будет добавлен в системный запрос. Делайте его коротким — включайте только факты, непосредственно относящиеся к текущему сеансу.

def build_context_block(profile: CustomerProfile) -> str:
    recent_order = profile.recent_purchases[0] if profile.recent_purchases else None
    last_ticket  = profile.previous_tickets[0]  if profile.previous_tickets  else None
    parts = [
        f'Customer: {profile.name} ({profile.email})',
        f'Account age: {profile.account_age_days} days | Tier: {profile.subscription_tier}',
        f'Lifetime value: USD {profile.lifetime_value_usd:.0f}',
    ]
    if recent_order:
        parts.append(
            f'Last order: {recent_order["date"]} — '
            f'{', '.join(recent_order["items"][:2])} ({recent_order["status"]})'
        )
    if last_ticket:
        parts.append(f'Last ticket: "{last_ticket["subject"]}" ({last_ticket["status"]})')
    return '\n'.join(parts)

Персонализация ответов с помощью контекста

Добавьте блок контекста в системный запрос, чтобы LLM естественно учитывала его в ответах, не получая прямого указания на это.

import openai

client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')

def respond_with_context(user_message: str, profile: CustomerProfile) -> str:
    context = build_context_block(profile)
    system_prompt = (
        f'You are a helpful customer service agent for ShopCo.\n'
        f'Customer context:\n{context}\n\n'
        f'Be warm and personal. Reference their history when relevant. '
        f'Address the customer by first name.'
    )
    resp = client.chat.completions.create(
        model='gpt-4o',
        messages=[
            {'role': 'system', 'content': system_prompt},
            {'role': 'user',   'content': user_message}
        ]
    )
    return resp.choices[0].message.content

Кэширование контекста клиента

Получение данных профиля из нескольких программных интерфейсов при каждом сообщении выполняется медленно и обходится дорого. Кэшируйте профиль в начале диалога и обновляйте только поля, которые могут измениться: статус заказа и статус обращения.

import time

profile_cache: dict[str, dict] = {}  # customer_id -> {profile, fetched_at}
CACHE_TTL = 300  # 5 minutes

def get_cached_profile(customer_id: str) -> CustomerProfile | None:
    entry = profile_cache.get(customer_id)
    if entry and time.time() - entry['fetched_at'] < CACHE_TTL:
        return entry['profile']
    return None

def set_cached_profile(customer_id: str, profile: CustomerProfile):
    profile_cache[customer_id] = {
        'profile': profile,
        'fetched_at': time.time()
    }

Выявление чувствительных ситуаций по истории

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

def assess_risk_flags(profile: CustomerProfile) -> list[str]:
    flags = []

    # Check for cancellation risk
    cancel_keywords = ['cancel', 'unsubscribe', 'quit', 'competitor']
    for ticket in profile.previous_tickets:
        if any(kw in ticket.get('subject', '').lower() for kw in cancel_keywords):
            flags.append('cancellation_risk')
            break

    # Defective product pattern
    defective = sum(1 for o in profile.recent_purchases if o.get('status') == 'refunded')
    if defective >= 2:
        flags.append('product_quality_issue')

    # High-value customer
    if profile.lifetime_value_usd > 5000:
        flags.append('high_value_customer')

    return flags

Полный конвейер сборки контекста

Объедините все источники данных в одну функцию assemble_context(), вызываемую один раз в начале диалога.

from datetime import date

def assemble_context(email: str) -> CustomerProfile:
    # Try cache first
    # In production: look up customer_id from email in your user DB
    customer_id = 'CUST_123'

    cached = get_cached_profile(customer_id)
    if cached:
        return cached

    # Fetch from all sources
    sub    = get_subscription_info(customer_id)
    orders = get_purchase_history(customer_id)
    tickets = get_support_history(customer_id)

    profile = CustomerProfile(
        customer_id=customer_id,
        name='Alice Smith',
        email=email,
        join_date=date(2021, 3, 15),
        subscription_tier=sub['tier'],
        account_age_days=calculate_account_age('2021-03-15T00:00:00Z')['days'],
        lifetime_value_usd=1240.00,
        previous_tickets=tickets,
        recent_purchases=orders
    )
    set_cached_profile(customer_id, profile)
    return profile

Какой элемент контекста клиента непосредственно позволяет агенту сказать: «Я вижу, что Вы с нами с 2021 года»

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

Итоги работы с контекстом клиента

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

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

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

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

Чему я научусь в уроке «Управление контекстом и историей клиента»?

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

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

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

Сколько времени занимает урок «Управление контекстом и историей клиента»?

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

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

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

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

  1. Маршрутизация обращений и логика эскалации
  2. Интеграция с CRM: Salesforce и HubSpot
  3. Протоколы передачи оператору
  4. Управление контекстом и историей клиента
← Назад к AI Agents