От текста к смыслу: Embeddings, GPT и многомерные векторы в конкурентном анализе мобильных приложений. Agglomerative Clustering.. Agglomerative Clustering. embeddings.. Agglomerative Clustering. embeddings. gpt.. Agglomerative Clustering. embeddings. gpt. kmeans.. Agglomerative Clustering. embeddings. gpt. kmeans. llm.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer. анализ отзывов.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer. анализ отзывов. Аналитика мобильных приложений.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer. анализ отзывов. Аналитика мобильных приложений. Блог компании Garage Eight.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer. анализ отзывов. Аналитика мобильных приложений. Блог компании Garage Eight. искусственный интеллект.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer. анализ отзывов. Аналитика мобильных приложений. Блог компании Garage Eight. искусственный интеллект. кластеризация отзывов.. Agglomerative Clustering. embeddings. gpt. kmeans. llm. OpenAI Embeddings API. voice of customer. анализ отзывов. Аналитика мобильных приложений. Блог компании Garage Eight. искусственный интеллект. кластеризация отзывов. тональность отзывов.

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

От текста к смыслу: Embeddings, GPT и многомерные векторы в конкурентном анализе мобильных приложений - 1

Меня зовут Вова Михайлов, я маркетинговый аналитик в Garage Eight. Мы развиваем международные финтех-продукты и стараемся использовать всю информацию для улучшения наших сервисов, в том числе отзывы. 

В этой статье я расскажу, как мы смогли автоматизировать и ускорить аналитику фидбэков с помощью Embeddings и GPT. Наш опыт будет релевантен не только финтеху, но и любым компаниям, которые хотят научиться в реальном времени получать данные из отзывов и сравнивать себя с конкурентами. 

Предыстория: в чём проблема

  • I completed the action, but nothing changed on my side.

  • The information I expected is missing.

  • Still waiting for everything to update.

  • The expected update hasn’t come through.

Все эти отзывы относятся к одной теме, при этом различаются по лексике и тональности. Для человека очевидно, что их связывает, а для компьютера это совершенно разные наборы слов. 

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

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

  • Ручной анализ. Сначала аналитики читали фидбэк вручную и раскладывали его по категориям в Excel. Это работало на десятках и сотнях отзывов, но масштабировать дальше было очень ресурсоемко. 

  • Опросы и NPS. Далее компании начали измерять NPS, CSAT и другие метрики удовлетворенности. Это позволило понять уровень лояльности, но не дало объяснений причин проблем.

  • Keyword Analytics. Потом появился поиск по ключевым словам и Word Cloud. Можно было собирать облака тегов, определять ключевые темы, но проблема была в том, что алгоритм выявлял слова, а не смысл. Отзывы на одну тему, написанные разными словами, оказывались в разных категориях. 

  • Classical NLP. С появлением NLP стали использовать TF-IDF, LDA и Topic Modeling для автоматического поиска тем. Это усовершенствовало группировку, но всё еще не помогало справиться с ключевой проблемой.

  • Embeddings. Здесь произошла революция: вместо слов начали использовать многомерное векторное представление смысла. Например:

    • My funds are missing → [0,14, −0,92, 0,33, …].

    • Deposit never arrived → [0,15, −0,90, 0,31, …].

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

  • LLM. Большие языковые модели стали отличным дополнением: Embeddings хорошо находят группы похожих отзывов, а LLM помогают интерпретировать их и превращать в понятные бизнес-темы.

В своем решении я использовал связку инструментов: 

Google Play Scraper → OpenAI Embeddings API → KMeans Clustering → GPT Naming → Meta Clustering → GPT Naming → Business Topics

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

Используем Embeddings: level 1

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

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

Итак, переходим к основной части. В основе Embeddings лежит идея представления текста в виде многомерного вектора признаков. Для этого я использую OpenAI Embeddings API, который преобразует каждый отзыв в вектор размерностью 1536 признаков.

from openai import OpenAI

client = OpenAI(api_key=config.API_KEY)

def get_embedding(text):

   response = client.embeddings.create(

       model="text-embedding-3-small",

       input=text

   )

   return response.data[0].embedding

df["embedding"] = df["Review"].apply(get_embedding)

После построения Embeddings я использую алгоритм KMeans для поиска плотных областей в семантическом пространстве. KMeans я выбрал по нескольким причинам: 

  • это простой и хорошо изученный алгоритм;

  • быстро работает на десятках тысяч записей и легко масштабируется;

  • дает предсказуемый результат;

  • позволяет контролировать количество тем через параметр K.

Единственная сложность — KMeans требует заранее знать количество кластеров. Именно поэтому пришлось экспериментировать с разными значениями K и смотреть на качество получаемых тем.

Кроме KMeans, я рассматривал еще два метода: 

  • DBSCAN/HDBSCAN. Они не требуют заранее задавать число кластеров, хорошо находят выбросы и часто используются для embedding-space. Но в моих тестах они либо давали слишком много мелких кластеров, либо сильно зависели от параметров.

  • Agglomerative Clustering. Он хорошо показывает иерархию тем и удобен для последующего объединения похожих кластеров. В итоге именно его я использовал на втором уровне пайплайна для формирования MetaTopic.

В результате получилось так, что KMeans отвечает за поиск локальных смыслов внутри отзывов, а Agglomerative Clustering помогает находить более крупные бизнес-темы поверх уже найденных кластеров.

Интересный момент — появление LLM сильно изменило требования к кластеризации. Раньше нужно было получить «идеальные» кластеры, потому что именно они были конечным результатом анализа. Теперь кластеризация стала промежуточным этапом. 

Главное — не идеальная математическая точность, а быстрое объединение семантически похожих отзывов, которые затем LLM может качественно проанализировать, назвать темы, выделить проблемы и сформулировать выводы. Это позволяет использовать более простые и быстрые алгоритмы кластеризации, сохраняя высокое качество итоговой аналитики.

Технически кластеризация реализуется следующими строками: 

import numpy as np

from sklearn.cluster import KMeans

X = np.vstack(df["embedding"].values)

kmeans = KMeans(

   n_clusters=15,

   random_state=42,

   n_init="auto"

)

df["ClusterID"] = kmeans.fit_predict(X)

Если на вход KMeans дать 1000 отзывов, то вместо тысячи отдельных комментариев можно получить примерно 10–20 устойчивых тематических кластеров. Например, в нашем случае могут быть такие области:

  • Verification

  • Localization

  • Trust & Security

  • Product Features

На этом этапе мы уже переходим от текста к смыслу, но сами кластеры пока остаются просто математическими группами похожих векторов.

Собираем данные с помощью GPT

Чтобы сделать результаты кластеризации понятными человеку, поверх подключается ChatGPT. Модель анализирует примеры отзывов внутри каждого кластера и формирует базу данных с названием темы, описанием проблемы, тональностью отзывов, их количеством и средним рейтингом. Дополнительно для каждого отзыва в базе данных сохраняются дата публикации, рейтинг и тональность, что позволяет анализировать не только сами темы, но и их динамику во времени.

Для обработки данных используем промпт: 

prompt = f"""

You are a senior product researcher.

Analyze the customer reviews below.

Identify the single dominant customer topic inside this cluster.

Return ONLY valid JSON:

{{

 "cluster_name": "Topic name",

 "description": "Short description",

 "sentiment": "Positive"

}}

Rules:

- Return exactly one topic.

- Choose the dominant theme.

- Sentiment must be only: Positive, Negative, Mixed.

Reviews:

{reviews_text}

"""

response = client.chat.completions.create(

   model=config.MODEL_TOPICS,

   response_format={"type": "json_object"},

   messages=[

       {"role": "user", "content": prompt}

   ],

   temperature=0

)

result = json.loads(response.choices[0].message.content)

Таким образом тысячи комментариев превращаются в полноценную модель Voice of Customer. Анализируя модель, мы поняли, что можем использовать ее не только на собственных отзывах, но и на отзывах конкурентов. Так мы смогли выявить их сильные и слабые стороны, а также определить наше положение на рынке с точки зрения клиентов.

От текста к смыслу: Embeddings, GPT и многомерные векторы в конкурентном анализе мобильных приложений - 2

Всё получилось: Embeddings определили векторы отзывов, KMeans кластеризовал их, а GPT собрал понятную БД. И тут появилась новая проблема: оказалось, что одинаковые темы могут иметь разные названия:

  • Need English Language

  • English Language Request

  • Lack of English Support

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

Используем Embeddings и GPT: level 2

На этом этапе для уже найденных GPT тем мы повторно строим Embeddings и с помощью Agglomerative Clustering применяем иерархическую кластеризацию. Это позволяет объединять похожие темы разных компаний в общие группы.

from sklearn.cluster import AgglomerativeClustering

from sklearn.metrics.pairwise import cosine_distances

topic_texts = (

   topics["ClusterName"] + "n" + topics["Description"]

).tolist()

topic_embeddings = [

   get_embedding(text)

   for text in topic_texts

]

X_topics = np.vstack(topic_embeddings)

distance_matrix = cosine_distances(X_topics)

clustering = AgglomerativeClustering(

   metric="precomputed",

   linkage="average",

   distance_threshold=0.35,

   n_clusters=None

)

topics["MetaClusterID"] = clustering.fit_predict(distance_matrix)

Затем GPT снова обрабатывает данные и формирует более высокий уровень абстракции — MetaTopic. После этого похожие MetaTopic дополнительно консолидируются в бизнес-категории.

prompt = f"""

You are a product analytics expert.

Below are similar customer topics from different apps.

Create one concise MetaTopic name that represents them.

Return ONLY valid JSON:

{{

 "meta_topic": "Meta topic name"

}}

Topics:

{topics_text}

"""

response = client.chat.completions.create(

   model=config.MODEL_TOPICS,

   response_format={"type": "json_object"},

   messages=[

       {"role": "user", "content": prompt}

   ],

   temperature=0

)

result = json.loads(response.choices[0].message.content)

В результате получается многоуровневая карта смыслов:

Review (Отзыв) → Cluster (Общая тема) → MetaTopic (Более крупная тема) → BusinessTopic (Бизнес-задача).

Например: Need English Language → English Language Support → Multilingual App Support → Localization.

Как поэтапно выглядят все шаги нашего решения

Как поэтапно выглядят все шаги нашего решения

Фактически система перестает работать со словами и начинает работать со смыслами: на входе — тысяча неструктурированных отзывов, на выходе — десяток бизнес-категорий, их тональность, объем обсуждения и динамика изменений во времени. Именно это позволяет использовать отзывы не как набор комментариев, а как источник знаний о продукте, клиентах и рынке.

Вместо итогов

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

Сейчас мы активно пользуемся внутри инструментом и планируем внедрить чат-бота, который будет дополнительно анализировать и комментировать результаты в модели Voice of Customer. 

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

Автор: Vladimir_Mihailov

Источник