Управление контекстом и историей клиента
Персонализированные ответы с учётом прошлых покупок, обращений и предпочтений.
«Управление контекстом и историей клиента» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Маршрутизация обращений и логика эскалации
- Интеграция с CRM: Salesforce и HubSpot
- Протоколы передачи оператору
- Управление контекстом и историей клиента