File size: 15,070 Bytes
294bf18
fb1efd8
 
c13cb6b
 
 
 
fb1efd8
 
468030d
fb1efd8
 
294bf18
82f47f0
 
5af1322
82f47f0
d9c4c17
82f47f0
513d6cb
 
 
 
 
 
 
0aececc
513d6cb
 
 
 
 
0aececc
d9c4c17
3126589
5350d0c
82f47f0
5af1322
 
037b1e8
e7a7b8a
513d6cb
5af1322
 
 
 
 
 
68864bd
 
e3f5def
68864bd
5af1322
d66a56e
5af1322
 
 
 
 
e3f5def
 
 
 
5af1322
68864bd
5af1322
e3f5def
5af1322
 
 
3126589
d9c4c17
 
 
84d1a91
 
 
 
 
 
 
 
 
 
d9c4c17
 
3126589
 
 
 
 
df2028a
3126589
df2028a
3126589
 
 
 
 
 
d9c4c17
3126589
 
 
 
 
 
 
df2028a
3126589
 
 
 
 
 
d9c4c17
 
3126589
 
 
 
 
 
df2028a
3126589
 
 
 
 
 
 
 
 
 
 
 
 
df2028a
3126589
 
 
 
 
 
d9c4c17
3126589
 
 
 
 
 
 
 
 
 
 
 
 
d9c4c17
3126589
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d9c4c17
3126589
 
 
 
 
 
d9c4c17
3126589
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df2028a
 
3126589
 
 
 
 
df2028a
 
3126589
 
 
 
 
df2028a
 
3126589
 
d9c4c17
 
 
3126589
 
df2028a
 
 
 
 
3126589
 
d9c4c17
 
3126589
 
e7a7b8a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355e616
 
 
e7a7b8a
3126589
037b1e8
 
 
 
 
d9c4c17
3126589
d9c4c17
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
---
language: ru
license: unlicense
tags:
- PyTorch
- Transformers
- gpt2
datasets: inkoziev/incomplete_utterance_restoration
pipeline_tag: text-generation
widget:
- text: '- Как тебя зовут? - Джульетта Мао #'
- text: '- А живешь где? - В поясе астероидов #'
---


## Задача Incomplete Utterance Restoration

Генеративная модель на основе [sberbank-ai/rugpt3large_based_on_gpt2](https://huggingface.co/sberbank-ai/rugpt3large_based_on_gpt2) для восстановления полного текста реплик в диалоге из контекста.

Допустим, последние 2 строки диалога имеют вид:

```
- Как тебя зовут?
- Джульетта Мао
```

Модель позволяет получить полный текст последней реплики, с раскрытыми анафорами, эллипсисами и т.д.:

```
Меня зовут Джульетта Мао
```

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

Подробнее о том, какие ситуации и как обрабатываются моделью, смотрите в [конце страницы](#обрабатываемые-ситуации) и в [этом документе](https://huggingface.co/inkoziev/rugpt_interpreter/blob/main/%D0%92%D0%BE%D1%81%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%BE%D0%BB%D0%BD%D1%8B%D1%85%20%D1%80%D0%B5%D0%BF%D0%BB%D0%B8%D0%BA%20%D0%B2%20%D0%B4%D0%B8%D0%B0%D0%BB%D0%BE%D0%B3%D0%B5.pdf).

## Пример использования

Данная модель работает в прототипе [диалоговой системы](https://github.com/Koziev/chatbot). Она не требует для работы никакой "обвязки", пре- или постпроцессинга, помимо стандартных для моделей семейства GPT,
поэтому использовать ее очень просто:

```
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM


device = "cuda" if torch.cuda.is_available() else "cpu"
model_name = "inkoziev/rugpt_interpreter"
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.add_special_tokens({'bos_token': '<s>', 'eos_token': '</s>', 'pad_token': '<pad>'})
model = AutoModelForCausalLM.from_pretrained(model_name)
model.to(device)
model.eval()

# На вход модели подаем последние 2-3 реплики диалога. Каждая реплика на отдельной строке, начинается с символа "-"
# В конце добавляем символ "#"
input_text = """<s>- Как тебя зовут?
- Джульетта Мао #"""
#input_text = """<s>- Что Предтечи забрали у Предшественников?
#- Они узурпировали у них Мантию — защиту всего живого в галактике #"""

encoded_prompt = tokenizer.encode(input_text, add_special_tokens=False, return_tensors="pt").to(device)

output_sequences = model.generate(input_ids=encoded_prompt, max_length=100, num_return_sequences=1, pad_token_id=tokenizer.pad_token_id)

text = tokenizer.decode(output_sequences[0].tolist(), clean_up_tokenization_spaces=True)[len(input_text)+1:]
text = text[: text.find('</s>')]
print(text)
```


## Формат входных данных

На вход модели подается результат токенизации для текста, составленного из 2 или 3 последних реплик диалога.
Первым токеном должен быть ```<s>```.
Каждая реплика должна начинаться префиксом "- ".
Реплики разделяются символом перевода строки.
К последней реплике, которая будет раскрываться, добавляется подстрока " #".

```
<s>- Как тебя зовут?
- Джульетта Мао #
```


## Обрабатываемые ситуации

Модель разрабатывается с прицелом на использование в [чатботе](https://github.com/Koziev/chatbot). Она поддерживает некоторые
типичные ситуации в читчате, которые перечислены далее.

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

[Эллипсисы](https://ru.wikipedia.org/wiki/%D0%AD%D0%BB%D0%BB%D0%B8%D0%BF%D1%81%D0%B8%D1%81):

```
- Как же тебя зовут, а?
- Меня – Стас, а тебя?  ⇒ Меня зовут Стас. Как тебя зовут?
```

В редких случаях и главное слово в словосочетании может опускаться, модель попытается его восстановить:

```
- Мама, купи мне собаку.
- А ты будешь за ней ухаживать?
- А ты мне здоровую купи.  ⇒ купи мне здоровую собаку
```

[Анафора](https://ru.wikipedia.org/wiki/%D0%90%D0%BD%D0%B0%D1%84%D0%BE%D1%80%D0%B0_(%D0%BB%D0%B8%D0%BD%D0%B3%D0%B2%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%B0)):

```
- Ты собак любишь?
- Не люблю я их  ⇒ я не люблю собак
```

Иногда для раскрытия полной реплики требуется привлечение здравого смысла, модель для этого будет опираться
на статистику претрейна:

```
- Мне на голову упала коробка.
- А что в ней было?  ⇒ что было в коробке|голове?
```

[Гэппинг](https://ru.wikipedia.org/wiki/%D0%AD%D0%BB%D0%BB%D0%B8%D0%BF%D1%81%D0%B8%D1%81#%D0%93%D1%8D%D0%BF%D0%BF%D0%B8%D0%BD%D0%B3_(en:Gapping)):

```
- Ты кошек любишь?
- Их – нет  ⇒  я не люблю кошек
```

Сложный гэппинг:

```
- В 25 лет вы получаете пенсию?
- Не я - отец.  ⇒  Я не получаю пенсию. Отец получает пенсию
```

Восстановление необязательного местоименного подлежащего (см. [pro drop](https://en.wikipedia.org/wiki/Pro-drop_language)):

```
- Согласна?
- Да  ⇒ я согласна
```

Модель пытается "читать между строк" и восстанавливать подразумеваемые части реплики:

```
- Ты разве ещё не ел?
- Тебя ждал  ⇒  я еще не ел. я ждал тебя.
```

Отрицания в диалоге:

```
- Я не прав?
- Нет. (Да.) ⇒ ты не прав
```

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

```
- Как прошли выходные?
- В Простоквашино ездила...  ⇒  я на выходных ездила в Простоквашино
```

Все вышесказанное может быть в разных сочетаниях одновременно:

```
- Где твой кот?
- Жена к ветеринару повезла.  ⇒ жена повезла моего кота к ветеринару
- Заболел?  ⇒  твой кот заболел?
```

Сложные предложения:

```
- Я сварила суп, иди ешь.
- Из чего?  ⇒  из чего ты сварила суп?
```

Замена подлежащего производится, если это улучшает понимание реплики:

```
- Как себя чувствует твой попугай?
- Бедняга умер...   ⇒   мой попугай умер
```

Иногда от реплики остается только наречие, модель будет восстанавливать все остальное:

```
- Девушка, а Вы животных любите?
- Очень!  ⇒ я очень люблю животных
```

Форма сказуемого иногда может меняться из соображений согласованности:

```
- Рабинович, как думаете, что будет делать правительство, если завтра население разом бросит курить?
- Таки, поднимут акцизы на алкоголь...  ⇒ правительно поднимет акцизы на алкоголь, если завтра население разом бросит курить
```

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

```
- У тебя брат есть?
- Да, есть
- Где он работает?  ⇒ Где работает твой брат?
```

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

Во многих случаях модель приводит порядок слов к более-менее каноническому. Точнее говоря, она старается
выдать текст с таким порядком слов, который обычно используют носители языка в данном контексте диалога.
Если русскоговорящие предпочитают OVS вместо формального SVO, то модель будет выдавать именно OVS:

```
- У тебя штрафы были?
- Нет, их никогда не было ⇒ у меня никогда не было штрафов
```

Модель обычно вставляет личные местоимения, даже если форма глагола позволяет обойтись без них:

```
- Жару любишь?
- Ненавижу ее  ⇒ я ненавижу жару
```

Сложносочиненные ответы разбиваются на отдельные клаузы, чтобы downstream pipeline мог обработать их последовательно:

```
- Тебя как зовут?
- Кортана, а тебя как?  ⇒  Меня зовут Кортана. Как тебя зовут?
```

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

```
- Где живешь?
- В Шанхае  ⇒ я живу в Шанхае
- Давно?   ⇒  ты давно живешь в Шанхае?
- Два года уже  ⇒ я уже два года живу в Шанхае
- Как там погода?  ⇒ как там погода в Шанхае?
```

Последнее, что хочется отметить: модель обучена **только** на диалоговых данных с короткими репликами (читчат).
Она практически не способна раскрывать анафоры в художественных текстах, хотя это не ограничение модели,
а особенность обучающего датасета.

### Пример работы в чате

Первый столбец содержит реплики диалога [модели читчата](https://huggingface.co/inkoziev/rugpt_chitchat) с собой, второй столбец - результат раскрытия реплик моделью интерпретатора:

```
- Добрый вечер, бро!                               |  
- Чё, будем общаться?                              |  Мы будем общаться?
- Ага, а как же                                    |  Мы будем общаться
- О чем хочешь говорить?                           |  О чем ты хочешь говорить?
- Давай о чем-нибудь хорошем                       |  Я хочу говорить о чем-нибудь хорошем
- Мне нравится обсуждать компьютерные игры         |  Мне нравится обсуждать компьютерные игры
- О, компьютерные игры меня тоже интересуют        |  Меня тоже интересуют компьютерные игры
- Ты играл в Minecraft?                            |  Ты играл в Minecraft?
- Неа, но хотел бы                                 |  Я не играл в игру Minecraft. Я хочу поиграть в игру Minecraft.
```

### Датасет

Обучающие данные без аугментации: [inkoziev/incomplete_utterance_restoration](https://huggingface.co/datasets/inkoziev/incomplete_utterance_restoration).


### Контакты

Если у Вас есть какие-то вопросы по использованию этой модели, или предложения по ее улучшению - пишите мне mentalcomputing@gmail.com


### Citation:

```
@MISC{rugpt_interpreter,
    author  = {Ilya Koziev},
    title   = {Incomplete Utterance Restoration in Russian Chit-Chat conversations},
    url     = {https://huggingface.co/inkoziev/rugpt_interpreter},
    year    = 2022
}
```