Использование машинного обучения для решения инцидентов

18.02.20

Разработка - Тестирование QA

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

Я не люблю, когда к месту и не к месту употребляют термин «Искусственный интеллект». «Искусственный интеллект отделяет котиков от собачек», «искусственный интеллект помогает ловить преступников», «абонентам помогут сократить расходы с помощью искусственного интеллекта». Чувствуется в этом какая-то попытка выдать желаемое за действительное. Я предпочитаю термин «Машинное обучение». По крайней мере именно про него я буду рассказывать дальше.

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

Обращаю внимание, что несмотря на ресурс, где статья опубликована – непосредственно к 1С она практически не имеет отношения. Только математика и Python.

 

Постановка задачи:

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

Было решено реализовать две функции:

  1. Автоматический вариант решения. Сразу после того, как сотрудник набрал текст инцидента можно, проанализировав его, предложить ему возможное решение.
  2. Предсказание правильного классификатора. Выбор правильного классификатора — это функция 1 линии техподдержки, правильный выбор позволяет корректно маршрутизировать инцидент, что в свою очередь сокращает время на решение инцидента. Ну, думаю всем очевидно, что если к 1С-нику придет инцидент, что между двумя узлами есть потеря сетевых пакетов, то время решения инцидента увеличится на время пока сотрудник увидит этот инцидент, вернет его на первую линию, а там уже правильно маршрутизируют ошибочно назначенный инцидент.

Реализовать удалось обе функции, о первой я расскажу в этой статье, а про вторую – в следующей.

 

Немного теории.

В 2013 году в компании Google был разработан инструмент для анализа семантики естественных языков word2vec. Идея инструмента – подать на вход текстовый корпус, затем внутри происходит компьютерная магия и на выходе мы получаем матрицу, в которой каждое из слов нашего корпуса представлено как вектор, причем чем более сонаправлены вектора (чем больше косинусное произведение между ними), тем они более похожи.

На картинке я попытался изобразить ТОП-5 векторов, наиболее близких слову «Собака». Обучение матрицы происходило на википедии и на национальном корпусе русского языка. Самостоятельно поиграться можно например тут https://rusvectores.org/ Естественно на рисунке лишь схема, на самом деле матрица является не двумерной, то есть каждое слово задается не двумя координатами, а сотней и более.

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

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

Вся разработка велась на Python в среде Anaconda. При установке Анаконды часть необходимых библиотек устанавливается сразу, часть необходимо будет доустановить. Так как статья не ставит своей целью обучить программированию на Python, я не буду углубляться в вопросы «как поставить библиотеку», «а почему написано именно так», однако готов при необходимости обсудить это в комментариях. Так же обязательно выслушаю советы опытных питонистов, потому что уверен, мой код далек от оптимального.

Объявим нужные нам библиотеки:

import warnings

warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')

#Подавляем лишние оповещения

import pyodbc

#Все инциденты считываются из базы данных, библиотека для доступа к SQL

import pandas as pd

#Про pandas написано куча книг. Кратко - pandas это высокоуровневая Python библиотека для анализа данных.

import re

#Ммм, регулярки (картинка с Гомером)

import pymorphy2

morph = pymorphy2.MorphAnalyzer()

#Морфологический анализатор.

import logging

logging.root.handlers = []

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)

#Библиотека для логирования

from smart_open import smart_open

#Библиотека для работы с большими удаленными файлами

import numpy as np

#Библиотека для работы с большими многомерными массивами

from numpy import random

import genism

# Библиотека обработки естественного языка

import nltk

#пакет библиотек и программ для символьной и статистической обработки естественного языка

from sklearn.model_selection import train_test_split

from sklearn import linear_model

from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer

from sklearn.metrics import accuracy_score, confusion_matrix, recall_score

# sklearn - бесплатная библиотека машинного обучения для языка программирования Python

import matplotlib.pyplot as plt

#Необходимо для рисования графиков

from gensim.models import Word2Vec

#А вот и сам Word2Vec

from sklearn.neighbors import KNeighborsClassifier

from sklearn import linear_model

from nltk.corpus import stopwords

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

 

%matplotlib inline

 

Загрузим стоп слова

stop_words = stopwords.words('russian')

 

Загрузка инцидентов ведется из базы данных инцидентов. При необходимости выполнить загрузку можно из любого источника.

 

connection_string_remedy = 'DRIVER={ODBC Driver 17 for SQL Server};SERVER=MyServer;DATABASE=MyBase;UID=user;PWD=password'

 

Объявим функцию, которая приведет текст инцидента к машиннообрабатываемому виду. Для этого мы сделаем следующее:

 

1. Удаляем всё лишнее (цифры, подписи, телефоны)

2. Приводим к нижнему регистру.

3. Удаляем стоп-слова.

4. лемматизируем и добавляем часть речи (ну кстати тестирование показало, что добавление части речи не улучшает результат, поэтому ниже этот функционал закомментирован.

 

def lemmatization(text,morphing = True):

    stop_words = stopwords.words('russian')

    border = text.find('Для решения инцидента заявитель должен предоставить')

#После этого текста в инциденте у нас идет служебная информация, ФИО сотрудника,

#магазин, с которого он обратился, номер телефона, IP адрес компьютера и прочее

#то, что для наших целей явно мешает. Удаляем.

    if border > 0:

        text = text[0:border]

    text = text.lower()

    text = re.sub(r"\d+", "", text, flags=re.UNICODE)

    text = re.sub('\W', ' ', text).split()

    if morphing == False:

        return text

    text_new = ''

    x = 0

    previous_word_ne = False

    for item in text:    

        if item == 'не':

            previous_word_ne = True

#это важная часть. Так как машина превращает слова в вектора – для нее «работает» и «не работает» не антонимы,

# а просто -в первом случае один вектор, а во втором случае два и они между собой не связаны.

#Поэтому превратим два слова «не работает» в одно «не_работает»

 

       

        if len(item) > 2:

            if not (item in stop_words):

                if previous_word_ne:

                    text_new = text_new+'не_'+morph.parse(item)[0].normal_form+' '#'_'+str(morph.parse(item)[0].tag.POS)+' '

# morph.parse(item)[0].normal_form – приведение к нормальной форме: «Побежали» -> «бежать», «компьютеров» -> «компьютер» и т.д.

                    previous_word_ne = False

                else:

                    text_new = text_new+morph.parse(item)[0].normal_form+' '#'_'+str(morph.parse(item)[0].tag.POS)+' '

                   

    return text_new

 

Результат работы функции:

lemmatization ("Для решения первой задачи сделаем следующее предположение – у нас есть инцидент и его решение, которое придумано человеком")

 

'решение один задача сделать следующий предположение инцидент решение который придумать человек '

 

Загрузим данные в DataFrame:

 

%%time

cnxn = pyodbc.connect(connection_string_remedy)

cursor = cnxn.cursor()

 

sql = '''

    SELECT Number, Description, ShortDescription

    FROM [MyBase].[dbo].[MyTable] (nolock)

    where cast(DateCreate as date) > '2018-01-01'

    and '''

#Здесь Description – текст инцидента, а ShortDescription его классификатор

 

#Кладем результат запроса в DataFrame и лемматизируем текст инцидента

 

df_result = pd.read_sql_query (sql, cnxn)

for index, row in df_result.iterrows():

    text = row['Description']

    text_new = lemmatization(text)

    df_result.iat[index,1]=text_new

 

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

 

my_tags = (df_result['ShortDescription'].value_counts()>1000)

my_tags = my_tags[my_tags == True].index.tolist()

len(my_tags)

 

У меня получилось 57 самых частых классификаторов. Данный параметр нужно подбирать на основании ваших данных.

 

Копируем DataFrame, чтобы заново не готовить исходный DataFrame. Дальше работаем только с отфильтрованным DataFrame. Сравниваем количество в отфильтрованном и полном DataFrame

 

df_result_filter = df_result[df_result['ShortDescription'].isin(my_tags)]

print(df_result.count())

print(df_result_filter.count())

df_result_filter.to_csv('Data/df_result_filter.csv', encoding = "utf-8")

 

У меня получилось 553551 инцидент в неотфильтрованном и 509497 инцидентов в отфильтрованном датафреймах.

 

Теперь давайте посмотрим на распределение инцидентов по классификаторам:

 

df_result_filter.ShortDescription.value_counts().plot(kind="bar", rot=90)

plt.rcParams['figure.figsize'] = [30, 5]

plt.show()

 

 

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

 

train_data, test_data = train_test_split(df_result_filter, test_size=0.1, random_state=42)

 

Далее создадим вспомогательные функции:

 

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

 

def plot_confusion_matrix(cm, title='Confusion matrix', cmap=plt.cm.Blues):

    plt.imshow(cm, interpolation='nearest', cmap=cmap)

    plt.title(title)

    plt.colorbar()

    tick_marks = np.arange(len(my_tags))

    target_names = my_tags

    plt.xticks(tick_marks, target_names, rotation=90)

    plt.yticks(tick_marks, target_names

    plt.ylabel('True label')

    plt.xlabel('Predicted label')

    fig = plt.gcf()

    fig.set_size_inches(18.5, 10.5)

    fig.savefig('test2png.png', dpi=100)

   

Функция, непосредственно вычисляющая матрицу ошибок.  

 

def evaluate_prediction(predictions, target, title="Confusion matrix"):

    print('accuracy %s' % accuracy_score(target, predictions))

    print('recall %s' % recall_score(target,predictions, average='micro'))

    cm = confusion_matrix(target, predictions)

    cm_normalized = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]

    plot_confusion_matrix(cm_normalized, title + ' Normalized')

 

 

Функция, превращающая текст инцидента в вектор   

def word_averaging(wv, words):

    all_words, mean = set(), []

   

    for word in words:

        if isinstance(word, np.ndarray):

            mean.append(word)

        elif word in wv.vocab:

            mean.append(wv.syn0norm[wv.vocab[word].index])

            all_words.add(wv.vocab[word].index)

 

    if not mean:

        logging.warning("cannot compute similarity with no input %s", words)

        # FIXME: remove these examples in pre-processing

#        return np.zeros(wv.layer1_size,)

        return np.zeros(wv.vector_size,)

 

    mean = gensim.matutils.unitvec(np.array(mean).mean(axis=0)).astype(np.float32)

    return mean

 

def  word_averaging_list(wv, text_list):

    return np.vstack([word_averaging(wv, review) for review in text_list])

 

#Разобьем полученные данные на массив (ndarray), строками в котором будут списки (list), где каждый элемент списка – отдельное слово.

def w2v_tokenize_text(text):

    tokens = []

    for sent in nltk.sent_tokenize(text, language='english'):

        for word in nltk.word_tokenize(sent, language='english'):

            if len(word) < 3:

                continue

            tokens.append(word)

    return tokens

 

Приступаем непосредственно к тренировке.

#Используя вышеобъявленную функцию превратим наш Датафрейм в массив с инцидентами (каждый инцидент это список, в котором отдельный элемент списка – слово)

 

inc_tokenized = df_result.apply(lambda r: w2v_tokenize_text(r['Description']), axis=1).values

 

Посмотрим, что у нас получилось, возьмем 50-ый элемент массива:

inc_tokenized[50]

 

['добрый',

 'день',

 'ошибочно',

 'отгрузить',

 'телефон',

 'просить',

 'отменить',

 'отрузка',

 'поставить',

 'остаток',

 'телефон',

 'мочь',

 'вернуть',

 'клиент',

 'номер',

 'сейф',

 'пакет',

 'номер',

 'отгрузка',

 'заранее',

 'спасибо',

 'табельный',

 'номер']

 

Обучим нашу модель

%%time

model = Word2Vec(inc_tokenized,

size=200,

window=5,

min_count=3,

workers=8)

wv = model.wv

 

Создадим L2-нормированные вектора и сохраним результат, он нам потребуется в дальнейшем

wv.init_sims(replace=True)

wv.save_word2vec_format('data/key_vectors_inc.bin')

 

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

 

wv.most_similar(positive=['ошибка'])

 

[('сообщение', 0.653794527053833),
 ('ощибка', 0.5926002264022827),
 ('табличка', 0.552541196346283),
 ('ошбка', 0.525760293006897),
 ('надпись', 0.5208160281181335),
 ('окошко', 0.5118091106414795),
 ('попытка', 0.49567654728889465),
 ('сбой', 0.48171132802963257),
 ('окно', 0.4712887406349182),
 ('уведомление', 0.46060070395469666)]

 

 

wv.most_similar(positive=['сим'])

 

[('симкарта', 0.801783561706543),
 ('симка', 0.7723581790924072),
 ('sim', 0.7251297235488892),
 ('болванка', 0.6134322881698608),
 ('бронзовый', 0.5933068990707397),
 ('сикарта', 0.592644989490509),
 ('icc', 0.582025408744812),
 ('ctn', 0.581929087638855),
 ('не_сим', 0.5614026188850403),
 ('бронза', 0.5609164237976074)]

 

wv.most_similar(positive=['телефон'])

 

[('смартфон', 0.8400038480758667),
 ('айфон', 0.7854971885681152),
 ('планшет', 0.7388856410980225),
 ('lite', 0.6476684212684631),
 ('iphone', 0.613440990447998),
 ('vita', 0.610135018825531),
 ('nokia', 0.6086500287055969),
 ('апп', 0.6069196462631226),
 ('товар', 0.6057144403457642),
 ('prime', 0.6033762693405151)]

 

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

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

 

%%time

full_tokenized = df_result.apply(lambda r: w2v_tokenize_text(r['Description']), axis=1).values

X_full_word_average = word_averaging_list(wv,full_tokenized)

df_result['X_full_word_average'] = list(X_full_word_average)

 

Это позволит нам искать не похожие слова, а похожие инциденты. Давайте проверим, работает ли наше предположение.

 

Определим функцию, которая вернет нам расстояние между выбранным вектором и матрицей векторов.

def find_similar_index(a, A):

    subs = (a[:,None] - A)

    sq_dist = np.einsum('ij,ij->j',subs, subs)

    return sq_dist

 

Преобразуем наш инцидент в вектор и найдем вектора, которые наиболее близки нашему. Выберем только те, расстояние до которых меньше 0.3. Чем меньше расстояние – тем ближе наш инцидент к полученному.

 

df_result_copy = df_result_filter

inc_text = '''

Добрый день. Не получается распечатать ценники по акции Самсунг

с услугами связи и акссесуарами. Ценник должен быть акционный. Название

акции в 1С - Акция «Samsung 3-я цена». Данную акцию не находит. И

выдает ошибку. Скрин приложен.

'''

inc_lemmatization = (lemmatization(inc_text))

inc_tokenize = w2v_tokenize_text(inc_lemmatization)

inc_average_list = word_averaging(wv,inc_tokenize)

 

df_result_copy['similar_index'] = find_similar_index(inc_average_list,X_full_word_average.T)

df_result_copy = df_result_copy.sort_values('similar_index')

df_order = df_result_copy[df_result_copy['similar_index']<0.3].head(1000)

df_order.head(10)

 

 

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

 

Инцидент с номером 20862395 это исходный инцидент, посмотрим следующие:

Номер инцидента

Текст

20868378

'Добрый день, по акции Смартфоны Samsung Galaxy с услугами связи и

аксессуарами невозможно напечатать акционный ценник, нет данной акции.

Когда набираешь артикул выдает ошибку

18399650

Добрый день! При печати ценника на Самсунг по акции А30 всего за 99

руб/мес не дает выбрать акцию. Нет возможности напечатать акционный

ценник

18047257

Добрый день, по акции HUAWEI P30 lite ценник должен печататься с суммой

16590р цена по акции, полная цена смартфона 21990р, ценник не

корректный,Ю скрины во вложении

21026274

Добрый день.

Не печатаются ценники по акции скидка на смартфон apple при покупке доп

товаров и услуг

 

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

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

Когда сотрудник ввел текст инцидента первым делом мы отправляем его (текст, а не сотрудника) на поиск похожих инцидентов. В случае если среди похожих есть инцидент с готовым решением – покажем его сотруднику и спрашиваем подошло ли решение. Если решение подходит – мы не создаем инцидент, считая что проблема решена.

Машинное обучение Python HelpDesk

См. также

Тестирование QA DevOps и автоматизация разработки Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х Россия Бухгалтерский учет Налоговый учет Платные (руб)

Готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарии возможно использовать как для vanessa-automation, так и для СППР. Поддерживаемые версии конфигураций ERP2 и КА2: 2.5.16.115.

2220 руб.

04.07.2022    7635    38    1    

26

Тестирование QA DevOps и автоматизация разработки Программист Пользователь Платформа 1С v8.3 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Налоговый учет Платные (руб)

Автотесты 1С - готовые тестовые сценарии, предназначенные для регресс-тестирования функционала конфигурации после обновления типовым релизом. Сценарии проверяют интерактивное заполнение форм документов, справочников и результат проведения документов. Сценарий – feature-файл, разработанный с помощью vanessa-automation. Запуск сценария выполняется интерактивно с помощью vanessa-automation или с помощью vanessa-runner в CI-системах. Доступно тестирование тонкого клиента. Поддерживаемые версии конфигураций 1С:Бухгалтерия предприятие 3.0 и версии КОРП: 3.0.144.49.

1728 руб.

20.01.2022    7201    17    0    

11

Нейросети Мастера заполнения Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Платные (руб)

Расширение для заполнения описания номенклатуры с помощью модели ИИ GigaChat от Сбера. Расширение формирует продающее описание товара по его наименованию с помощью модели искусственного интеллекта. Будет полезно для владельцев интернет магазинов, каталогов товаров и продающих через маркетплейсы. Адаптировано для основных конфигураций: УТ, ЕРП, КА, УНФ.

5000 руб.

08.11.2023    2029    11    0    

20

Тестирование QA DevOps и автоматизация разработки Программист Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Набор универсальных подсценариев для заполнения форм типовых объектов справочников и документов конфигураций ERP 2.5 и КА 2.5. Сценарии представляют собой feature-файлы для vanessa-automation с тегом @exportscenarios. Используются для разработки функциональных сценариев.

1500 руб.

26.01.2023    3502    6    0    

3

Нейросети Пользователь Платформа 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Оптовая торговля, дистрибуция, логистика Россия Управленческий учет Платные (руб)

Расширение "Искусственный интеллект и нейросети в 1С: Работа с отзывами маркетплейсов" предназначено для применения искусственного интеллекта в повседневной деятельности селлеров на маркетплейсах. Среди функций - работа с отзывами, вопросами и чатами покупателей, диалог с нейросетями, генерация картинок, заполнение описаний номенклатуры и другое.

5000 руб.

03.04.2024    4339    1    0    

7

Мастера заполнения Нейросети Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Платные (руб)

Расширение для заполнения описания товара (номенклатуры) с помощью модели ИИ ChatGPT с ключевыми словами. Расширение формирует продающее описание товара по его наименованию с помощью модели искусственного интеллекта. Будет полезно для владельцев интернет магазинов, каталогов товаров и продающих через маркетплейсы. Адаптировано для основных конфигураций: УТ, ЕРП, КА, УНФ. Прошло аудит на 1cfresh.com. Версия для автоматического заполнения

5000 руб.

13.03.2023    17076    44    49    

74

Тестирование QA Программист Платформа 1С v8.3 Бесплатно (free)

Иногда возникают ситуации, когда надо развернуть тестовую базу клиента / свою на серверах Windows или Linux. Тестовые базы могут понадобиться в разных ситуациях: у клиента ошибка, на нашей базе она не воспроизводится, реализуем новый функционал и хотелось бы протестировать на Linux и т.д. А теперь представим, что это все на потоке. Что тестовых баз 1С не одна, а 20-30. И получаем проблему, что непонятно, занята она сейчас кем-то или нет. Предлагаю вариант решения этой проблемы.

28.06.2024    980    Diversus    12    

4

Нейросети Программист Платформа 1С v8.3 ИТ-компания Россия Бесплатно (free)

Искусственный интеллект наконец-то может решить проблемы, которые много лет портили жизнь бухгалтерам, директорам и бизнесу в целом. Часто они возникали из-за пресловутого «человеческого фактора». Широкое распространение нейронный сетей знаменует собой исключение этого фактора и уменьшение числа ошибок.

07.06.2024    9810    Neti    36    

17
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Diversus 2325 18.02.20 15:38 Сейчас в теме
Отличная статья! Спасибо за подробное описание. Если позволите замечание:
В случае если среди похожих есть инцидент с готовым решением – покажем его сотруднику и спрашиваем подошло ли решение. Если решение подходит – мы не создаем инцидент, считая что проблема решена.
На мой взгляд было бы лучше все таки создавать инцидент, сразу устанавливая статус, что он решен и способ его решения - машинное обучение с указанием на способ решения. Тогда можно было бы видеть тут же в help desk/service desk сколько таких инцидентов было решено с использованием машинного обучения. Иначе не совсем понятен порядок цифр и сколько в процентном отношении все таки по факту решается автоматически.
PS: Но это больше придирки конечно :)
anatoliy.kichuk; romankoav; +2 Ответить
3. Repich 563 18.02.20 16:11 Сейчас в теме
(1) Эта информация фиксируется в отдельной базе. Точнее фиксируется сам факт что пользователю предложено решение и его ответ "подошло/не подошло". Но идея - создавать инцидент и сразу закрывать его - интересная, это действительно дополнительная информация для аналитики, спасибо, обдумаю.
2. akim2040 46 18.02.20 15:43 Сейчас в теме
Можно спросить, у Вас тоже есть такие нерадивые пользователи, которые считают что на сервис-деск достаточно кинуть один скриншот без всякого описания?
Если да, как такие обрабатываете?
4. Repich 563 18.02.20 16:14 Сейчас в теме
(2) К сожалению только вручную. Первая линия возвращает их на инициатора с требованием описать проблему.
5. TODD22 19 18.02.20 16:19 Сейчас в теме
(4)
К сожалению только вручную. Первая линия возвращает их на инициатора с требованием описать проблему.

А автоматически это нельзя сделать? Если нет текстового описания то нужно ответить на ряд наводящих вопросов и отправить повторно. Можно сразу сделать форму в которую нельзя отправить без текстового описания.
6. Repich 563 18.02.20 16:23 Сейчас в теме
(5)
А автоматически это нельзя сделать? Если нет текстового описания то нужно ответить на ряд наводящих вопросов и отправить повторно. Можно сразу сделать форму в которую нельзя отправить без текстового описания.


Можно конечно. Но так как жалоб от первой линии нет - значит проблема не сильно им мешает.
7. TODD22 19 18.02.20 16:26 Сейчас в теме
(6)У нас заявка без описания не создаётся.
8. akim2040 46 18.02.20 17:00 Сейчас в теме
(7) ну ведь ничего не мешает написать в описании "не работает", и это будет не очень информативно. Думаю и правда, такое только под ручную обработку
Fox-trot; +1 Ответить
9. TODD22 19 18.02.20 17:10 Сейчас в теме
(8)
ну ведь ничего не мешает написать в описании "не работает", и это будет не очень информативно.

Конечно ничего не мешает. Но наличие этого поля уже дисциплинирует. К тому же можно там же делать подсказки как надо описывать ошибки, пожелания по доработке и тд.
Меньше "холостой" работы для ТП им не надо отправлять пользователю его ошибку что бы дополнял. Обычно описание есть. Не всегда внятное, но всё же есть.
10. pm74 202 18.02.20 18:33 Сейчас в теме
(0) супер , прочитал пока бегло но впечатляет
11. lunjio 67 18.02.20 20:37 Сейчас в теме
(0)
Спасибо за статью, очень интересное решение.
У вас это в виде внешней компоненты/сервиса, как организовано на уровне архитектуры ? Погрузите пожалуйста в непосредственную реализацию, тоесть вы разбираете текущее обращение, получаете схожие слова, запросом отбираете инциденты где есть эти слова, потом их так же к векторам преобразуете и т.д? Либо внешний сервис напрямую к скулю обращается и сам уже получает список инцидентов с похожими словами и их преобразует к векторам и выдает упорядоченными по схожести ?
Как с производительностью дела обстоят ? За какой промежуток времени обработка и выдача результата происходит ? Спасибо
12. Repich 563 18.02.20 21:18 Сейчас в теме
(11) Наверное отвечу отдельной статьей.
17. Repich 563 25.02.20 18:27 Сейчас в теме
13. rabid_otter 134 20.02.20 11:28 Сейчас в теме
прочел бегло, статья крутая. вот это я понимаю автоматизация автоматизации.
juliia1992; +1 Ответить
14. kalyaka 1087 21.02.20 09:26 Сейчас в теме
А есть какие-нибудь решения, которые бы могли проводить смысловой лингвистический анализ и на основе смысловых фреймов определять о чем идет речь в тексте? А то так получается, что анализа никакого нет, есть чисто статистическая выборка и оценка вероятности, что на основе такого набора слов скорее всего речь идет об этом.

Это чем-то мне напоминает изучение иностранного языка в школе, когда учитель не особо заморачивается над передачей понимания, делает упор на зубрежке иностранных слов. После такого обучения на основе данных о контексте переводимого текста и знания отдельных слов можно ловко "фантазировать" близкий (иногда не очень) по смыслу перевод.
15. Repich 563 21.02.20 16:08 Сейчас в теме
(14) То, о чем вы пишите работает точно так же как и описанный выше механизм. Берется выборка для обучения, на основе которой строится модель, которая в свою очередь выдает коэффициент сходства исследуемого текста и тех классификаторов, которые есть в модели.
Машинное обучение и модные сейчас нейронные сети оперируют ТОЛЬКО числами.
Если вы обучили модель на журнальных статьях - она сможет отличить статью про спорт от статьи про автомобили, но рассказ Куприна от повести Чехова она отличить не сможет.
16. kalyaka 1087 21.02.20 17:13 Сейчас в теме
(15) Я имел в виду использование лингвистического анализа: типа кто-то или что-то совершает такое то действие. Выделить объект и субъект и возможные отношения между ними. Т.е. это получается экспертная система с возможностью накопления связанной информации для поиска путей решения.

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