update
Browse files- .gitignore +0 -1
- app.py +7 -4
- lib/llm_3.py +610 -0
.gitignore
CHANGED
|
@@ -15,7 +15,6 @@ dist/
|
|
| 15 |
downloads/
|
| 16 |
eggs/
|
| 17 |
.eggs/
|
| 18 |
-
lib/
|
| 19 |
lib64/
|
| 20 |
parts/
|
| 21 |
sdist/
|
|
|
|
| 15 |
downloads/
|
| 16 |
eggs/
|
| 17 |
.eggs/
|
|
|
|
| 18 |
lib64/
|
| 19 |
parts/
|
| 20 |
sdist/
|
app.py
CHANGED
|
@@ -6,7 +6,7 @@ import pytesseract
|
|
| 6 |
from pdf2image import convert_from_bytes
|
| 7 |
from flask_cors import CORS
|
| 8 |
from lib import ocr_1
|
| 9 |
-
from lib import
|
| 10 |
|
| 11 |
os.environ['TESSDATA_PREFIX'] = '/usr/share/tesseract-ocr/5/tessdata'
|
| 12 |
|
|
@@ -59,9 +59,12 @@ def upload_file():
|
|
| 59 |
def analize():
|
| 60 |
# Get the text data from the request
|
| 61 |
text_data = request.json.get('text')
|
| 62 |
-
app_info =
|
| 63 |
-
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
if __name__ == '__main__':
|
| 67 |
app.run(debug=False)
|
|
|
|
| 6 |
from pdf2image import convert_from_bytes
|
| 7 |
from flask_cors import CORS
|
| 8 |
from lib import ocr_1
|
| 9 |
+
from lib import llm_3 as llm
|
| 10 |
|
| 11 |
os.environ['TESSDATA_PREFIX'] = '/usr/share/tesseract-ocr/5/tessdata'
|
| 12 |
|
|
|
|
| 59 |
def analize():
|
| 60 |
# Get the text data from the request
|
| 61 |
text_data = request.json.get('text')
|
| 62 |
+
app_info = llm.getApplicationInfo(text_data)
|
| 63 |
+
result = {
|
| 64 |
+
"application": app_info,
|
| 65 |
+
"debug": {}
|
| 66 |
+
}
|
| 67 |
+
return Response(json.dumps(result, sort_keys=False, ensure_ascii=False), content_type='application/json; charset=utf-8')
|
| 68 |
|
| 69 |
if __name__ == '__main__':
|
| 70 |
app.run(debug=False)
|
lib/llm_3.py
ADDED
|
@@ -0,0 +1,610 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import numpy as np
|
| 3 |
+
import requests
|
| 4 |
+
import json
|
| 5 |
+
import pandas as pd
|
| 6 |
+
|
| 7 |
+
typedf = pd.read_excel('types.xlsx')
|
| 8 |
+
verbose = False
|
| 9 |
+
# s = 'Тип обращения: Жалобы > Сектор: Акционерные общества/эмитенты эмиссионных ценных бумаг > Продукт: Дивиденды'
|
| 10 |
+
# s = 'Тип обращения: Прочие обращения (запрос, заявление, вопрос) > Сектор: Субъекты страхового дела > Продукт: Прочие обращения (страхование) > Проблема: Иные обращения: Страхование > Обращение может быть типологизировано по иной проблеме: Нет'
|
| 11 |
+
level = 'Тип обращения'
|
| 12 |
+
level = 'Сектор'
|
| 13 |
+
level = 'Продукт'
|
| 14 |
+
level = 'Проблема'
|
| 15 |
+
level = 'Проблема'
|
| 16 |
+
|
| 17 |
+
def getType(str, level) :
|
| 18 |
+
type = ''
|
| 19 |
+
t = level + ': [^>]+'
|
| 20 |
+
# t = r'Сектор\: \w+/\w+ >'
|
| 21 |
+
m = re.search(t, str)
|
| 22 |
+
if m :
|
| 23 |
+
substr = str[m.start() : m.end()]
|
| 24 |
+
substr
|
| 25 |
+
m = re.search('\: [\w ]+', substr)
|
| 26 |
+
subsubstr = substr[m.start() + 2 : ]
|
| 27 |
+
# subsubstr
|
| 28 |
+
type = subsubstr.strip()
|
| 29 |
+
|
| 30 |
+
return type
|
| 31 |
+
|
| 32 |
+
def getQuestionAnswer(str) :
|
| 33 |
+
q = ''
|
| 34 |
+
a = ''
|
| 35 |
+
l = str.split('>')
|
| 36 |
+
if len(l) == 5 :
|
| 37 |
+
q = l[4][1 :]
|
| 38 |
+
x = q.find(':')
|
| 39 |
+
a = q[x + 2 :]
|
| 40 |
+
q = q[: x]
|
| 41 |
+
|
| 42 |
+
return q, a
|
| 43 |
+
|
| 44 |
+
types = []
|
| 45 |
+
sectors = []
|
| 46 |
+
products = {}
|
| 47 |
+
problems = {}
|
| 48 |
+
for index, row in typedf.iterrows() :
|
| 49 |
+
text = row['Путь до вершины']
|
| 50 |
+
text = str(text)
|
| 51 |
+
if text != '' :
|
| 52 |
+
apptype = getType(text, 'Тип обращения')
|
| 53 |
+
sector = getType(text, 'Сектор')
|
| 54 |
+
product = getType(text, 'Продукт')
|
| 55 |
+
problem = getType(text, 'Проблема')
|
| 56 |
+
sector = sector.replace(' ', ' ')
|
| 57 |
+
product = product.replace(' ', ' ')
|
| 58 |
+
problem = problem.replace(' ', ' ')
|
| 59 |
+
|
| 60 |
+
if apptype == 'Жалобы' and sector != '' and product != '' and problem != '' :
|
| 61 |
+
if sector not in sectors :
|
| 62 |
+
sectors.append(sector)
|
| 63 |
+
|
| 64 |
+
if sector not in products :
|
| 65 |
+
products[sector] = []
|
| 66 |
+
|
| 67 |
+
if product not in products[sector] :
|
| 68 |
+
products[sector].append(product)
|
| 69 |
+
|
| 70 |
+
if sector not in problems :
|
| 71 |
+
problems[sector] = {}
|
| 72 |
+
|
| 73 |
+
if product not in problems[sector] :
|
| 74 |
+
problems[sector][product] = []
|
| 75 |
+
|
| 76 |
+
if problem not in problems[sector][product] :
|
| 77 |
+
problems[sector][product].append(problem)
|
| 78 |
+
|
| 79 |
+
def getCategory(text, categories) :
|
| 80 |
+
found = False
|
| 81 |
+
text = text.lower()
|
| 82 |
+
for category in categories :
|
| 83 |
+
if category.lower() in text :
|
| 84 |
+
found = True
|
| 85 |
+
break
|
| 86 |
+
|
| 87 |
+
if found == False :
|
| 88 |
+
category = ''
|
| 89 |
+
|
| 90 |
+
return category
|
| 91 |
+
|
| 92 |
+
def getResponse(prompt) :
|
| 93 |
+
url = "https://muryshev-mixtral-api.hf.space/completion"
|
| 94 |
+
|
| 95 |
+
payload = json.dumps({
|
| 96 |
+
"prompt": '[INST]' + prompt + '[/INST]'
|
| 97 |
+
})
|
| 98 |
+
|
| 99 |
+
headers = {
|
| 100 |
+
'Content-Type': 'application/json'
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
response = requests.request("POST", url, headers = headers, data = payload)
|
| 104 |
+
result = response.content.decode('utf-8')
|
| 105 |
+
return result
|
| 106 |
+
|
| 107 |
+
def getCategoryFromLLM(prompt, categories) :
|
| 108 |
+
category = ''
|
| 109 |
+
for j in range(5) :
|
| 110 |
+
result = getResponse(prompt)
|
| 111 |
+
category = getCategory(result, categories)
|
| 112 |
+
if category != '' :
|
| 113 |
+
break
|
| 114 |
+
|
| 115 |
+
prompt += '.'
|
| 116 |
+
|
| 117 |
+
return category, result
|
| 118 |
+
|
| 119 |
+
def getAccuracy(answers, trueanswers) :
|
| 120 |
+
count = 0
|
| 121 |
+
for i in range(len(trueanswers)) :
|
| 122 |
+
if answers[i] == trueanswers[i] :
|
| 123 |
+
count += 1
|
| 124 |
+
|
| 125 |
+
return count / len(trueanswers)
|
| 126 |
+
|
| 127 |
+
def getAnswers(applications, prefix, categories, answers) :
|
| 128 |
+
# print(categories)
|
| 129 |
+
output = []
|
| 130 |
+
for i in range(len(applications)) :
|
| 131 |
+
text = applications[i]
|
| 132 |
+
prompt = prefix + text
|
| 133 |
+
category, response = getCategoryFromLLM(prompt, categories)
|
| 134 |
+
|
| 135 |
+
answer = ''
|
| 136 |
+
for j in range(len(categories)) :
|
| 137 |
+
if category == categories[j] :
|
| 138 |
+
answer = answers[j]
|
| 139 |
+
break
|
| 140 |
+
|
| 141 |
+
brief = response.replace('\n', '')
|
| 142 |
+
if len(brief) > 80 :
|
| 143 |
+
brief = brief[:80] + '...'
|
| 144 |
+
|
| 145 |
+
if verbose :
|
| 146 |
+
print(i, ':', answer, ' \tLLM output :', brief)
|
| 147 |
+
|
| 148 |
+
output.append(answer)
|
| 149 |
+
|
| 150 |
+
return output
|
| 151 |
+
|
| 152 |
+
def getSector(application) :
|
| 153 |
+
|
| 154 |
+
sectortext = ''
|
| 155 |
+
for j in range(len(sectors)) :
|
| 156 |
+
sectortext += str(j) + '. ' + sectors[j] + '. '
|
| 157 |
+
|
| 158 |
+
prompt = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов.
|
| 159 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме заявления.
|
| 160 |
+
Ты извлекаешь информацию. Ты не анализируешь.
|
| 161 |
+
Ты выполняешь только эту задачу: ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю.
|
| 162 |
+
Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует обращению. Проверь свой ответ дважды.
|
| 163 |
+
Ты всегда используешь такой формат ответа: "название категории".
|
| 164 |
+
Если в тексте обращения есть аббревиатуры "МФО", "МФК" или "МКК", ты должен выбрать категорию "Микрофинансовые организации".
|
| 165 |
+
Если в тексте обращения есть аббревиатуры "ОСАГО" или "КАСКО", ты должен выбрать категорию "Субъекты страхового дела".
|
| 166 |
+
Список категорий:
|
| 167 |
+
''' + sectortext + '\nЗаявление: ' + application
|
| 168 |
+
|
| 169 |
+
# prompt = '''<s>[INST]Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов.
|
| 170 |
+
# Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме заявления.
|
| 171 |
+
# Ты извлекаешь информацию. Ты не анализируешь.
|
| 172 |
+
# Ты выполняешь только эту задачу: ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю.
|
| 173 |
+
# Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует обращению. Проверь свой ответ дважды.
|
| 174 |
+
# Ты всегда используешь такой формат ответа: "название категории".
|
| 175 |
+
# Если в тексте обращения есть аббревиатуры "МФО", "МФК" или "МКК", ты должен выбрать категорию "Микрофинансовые организации".
|
| 176 |
+
# Если в тексте обращения есть аббревиатуры "ОСАГО" или "КАСКО", ты должен выбрать категорию "Субъекты страхового дела".
|
| 177 |
+
# Список категорий:
|
| 178 |
+
# ''' + sectortext + 'Заявление: ' + application + '/INST'
|
| 179 |
+
|
| 180 |
+
sector, response = getCategoryFromLLM(prompt, sectors)
|
| 181 |
+
|
| 182 |
+
if verbose :
|
| 183 |
+
print(i, ':', sector)
|
| 184 |
+
|
| 185 |
+
return sector
|
| 186 |
+
|
| 187 |
+
def getProduct(application, sector) :
|
| 188 |
+
product = ''
|
| 189 |
+
# sector = appsectors[i]
|
| 190 |
+
if sector != '' :
|
| 191 |
+
subproducts = products[sector]
|
| 192 |
+
|
| 193 |
+
producttext = ''
|
| 194 |
+
for j in range(len(subproducts)) :
|
| 195 |
+
producttext += str(j) + '. ' + subproducts[j] + '. '
|
| 196 |
+
|
| 197 |
+
prompt = 'Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов. Ты не отвечаешь на вопросы, не комментируешь, \
|
| 198 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения. Ты извлекаешь персональные данные. Ты не анализируешь. \
|
| 199 |
+
Ты выполняешь только эту задачу: \
|
| 200 |
+
ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю. \
|
| 201 |
+
Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует заявлению. Проверь свой ответ дважды. \
|
| 202 |
+
Ты всегда используешь такой формат ответа: "название категории". \n\
|
| 203 |
+
Список категорий:\n' + producttext + '\nЗаявление: ' + application
|
| 204 |
+
|
| 205 |
+
product, response = getCategoryFromLLM(prompt, subproducts)
|
| 206 |
+
|
| 207 |
+
if verbose :
|
| 208 |
+
print(product)
|
| 209 |
+
|
| 210 |
+
return product
|
| 211 |
+
|
| 212 |
+
def getProblem(application, sector, product) :
|
| 213 |
+
problem = ''
|
| 214 |
+
if sector != '' and product != '':
|
| 215 |
+
subpproblems = problems[sector][product]
|
| 216 |
+
|
| 217 |
+
problemtext = ''
|
| 218 |
+
for j in range(len(subpproblems)) :
|
| 219 |
+
problemtext += str(j) + '. ' + subpproblems[j] + '. '
|
| 220 |
+
|
| 221 |
+
prompt = 'Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов. Ты не отвечаешь на вопросы, не комментируешь, \
|
| 222 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения. Ты извлекаешь персональные данные. Ты не анализируешь. \
|
| 223 |
+
Ты выполняешь только эту задачу: \
|
| 224 |
+
ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю. \
|
| 225 |
+
Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует заявлению. Проверь свой ответ дважды. \
|
| 226 |
+
Ты всегда используешь такой формат ответа: "название категории". \n\
|
| 227 |
+
Список категорий:\n' + problemtext + '\nЗаявление: ' + application
|
| 228 |
+
|
| 229 |
+
problem, response = getCategoryFromLLM(prompt, subpproblems)
|
| 230 |
+
|
| 231 |
+
if verbose :
|
| 232 |
+
print(problem)
|
| 233 |
+
|
| 234 |
+
return problem
|
| 235 |
+
|
| 236 |
+
def getAuthor(application) :
|
| 237 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты не отвечаешь на вопросы, не комментируешь,
|
| 238 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
| 239 |
+
Ты извлекаешь информацию из заявления. Ты отвечаешь на МОЙ вопрос:
|
| 240 |
+
"Кто является заявителем в заявлении?". Ты называешь имя заявителя в формате: "Заявитель: Фамилия Имя Отчество".
|
| 241 |
+
Если заявиитель не указан в заявлении, ты отвечаешь: "Заявитель: не указан".
|
| 242 |
+
Ты не комментируешь, не обясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
| 243 |
+
Обращение: '''
|
| 244 |
+
|
| 245 |
+
prompt = prefix + application
|
| 246 |
+
# prompt = prefix + appdata.loc[i, 'Текст обращения обезличенный']
|
| 247 |
+
response = getResponse(prompt)
|
| 248 |
+
response = response.replace('.', '. ')
|
| 249 |
+
name = 'не указан'
|
| 250 |
+
if name not in response :
|
| 251 |
+
m = re.search(r'Заявитель: [А-Я][а-я][\w\.]+ [А-Я][\w\.]+ [А-Я][\w\.]+', response)
|
| 252 |
+
if m :
|
| 253 |
+
name = response[m.start() + 11 : m.end()]
|
| 254 |
+
else :
|
| 255 |
+
m = re.search(r'Заявитель: [А-Я][а-я][\w]+ [А-Я][а-я][\w]+', response)
|
| 256 |
+
if m :
|
| 257 |
+
name = response[m.start() + 11 : m.end()]
|
| 258 |
+
|
| 259 |
+
if verbose :
|
| 260 |
+
print(name, '\n', response[:100].replace('\n', ' '))
|
| 261 |
+
|
| 262 |
+
return name
|
| 263 |
+
|
| 264 |
+
def checkContractNumber(application) :
|
| 265 |
+
categories = ['да', 'нет']
|
| 266 |
+
answers = ['да', 'нет']
|
| 267 |
+
|
| 268 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты извлекаешь информацию из заявлений.
|
| 269 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
| 270 |
+
Ты только отвечаешь на МОЙ вопрос: "Имеется ли в заявлении указанный номер договора?".
|
| 271 |
+
Ты отвечаешь либо ТАК "ответ: да, имеется" ЛИБО так "ответ: нет, не имеется". Конец ответа.
|
| 272 |
+
Если в заявлении нет слова "договор", ты отвечаешь "ответ: нет, не имеется"
|
| 273 |
+
Ты не комментируешь, не объясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
| 274 |
+
Заявление: '''
|
| 275 |
+
|
| 276 |
+
ifcontract = getAnswers([application], prefix, categories, answers)
|
| 277 |
+
|
| 278 |
+
return ifcontract[0]
|
| 279 |
+
|
| 280 |
+
def checkIfIdentified(application) :
|
| 281 |
+
сategories = ['нельзя', 'можно']
|
| 282 |
+
answers = ['нет', 'да']
|
| 283 |
+
|
| 284 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке.
|
| 285 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме жалобы.
|
| 286 |
+
Ты ищешь в заявлении объект жалобы: "Можно ли идентицифировать в заявлении объект жалобы (тот, на кого жалуется заявитель)?".
|
| 287 |
+
Твой ответ ВСЕГДА состоит из ��РЕХ слов: ты отвечаешь либо ТАК "да, можно", ЛИБО так "нет, нельзя".
|
| 288 |
+
Ты не комментируешь, не объясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
| 289 |
+
Жалоба: '''
|
| 290 |
+
|
| 291 |
+
ifidentified = getAnswers([application], prefix, сategories, answers)
|
| 292 |
+
|
| 293 |
+
return ifidentified[0]
|
| 294 |
+
|
| 295 |
+
def checkIfPerson(application) :
|
| 296 |
+
categories = ['физическое лицо', 'юридическое лицо']
|
| 297 |
+
answers = ['Физ.лицо', 'Юр.лицо']
|
| 298 |
+
|
| 299 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь "заявления" клиентов.
|
| 300 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
| 301 |
+
Ты извлекаешь информацию. Ты не анализируешь.
|
| 302 |
+
Ты отвечаешь ТОЛЬКО на мои вопросы. Ты определяешь кем является заявитель: "физическое лицо" или "юридическое лицо".
|
| 303 |
+
Условие: если заявление написано в первом лице (местоимения Я, МНЕ, МНОЮ, МОЕ, МЕНЯ), то это физическое лицо, НО если заявление написано в третьем лице, то это юридическое лицо.
|
| 304 |
+
Ты отвечаешь только так: "Заявитель: юрдическое лицо" или "Заявитель: физическое лицо".
|
| 305 |
+
Ты не комментируешь, не обясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
| 306 |
+
Заявление: '''
|
| 307 |
+
|
| 308 |
+
ifperson = getAnswers([application], prefix, categories, answers)
|
| 309 |
+
|
| 310 |
+
return ifperson[0]
|
| 311 |
+
|
| 312 |
+
def checkIfcomission(application) :
|
| 313 |
+
categories = ['не касается', 'касается']
|
| 314 |
+
answers = ['нет', 'да']
|
| 315 |
+
|
| 316 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты извлекаешь информацию из заявлений.
|
| 317 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
| 318 |
+
Ты только отвечаешь на МОЙ вопрос: "Касается ли заявление комиссии за обслуживание рублевого счета?".
|
| 319 |
+
Ты отвечаешь либо ТАК "ответ: да, касается" ЛИБО так "ответ: нет, не касается". Конец ответа.
|
| 320 |
+
Если в заявлении нет слова "комиссия", ты отвечаешь "ответ: нет, не касается"
|
| 321 |
+
Ты не комментируешь, не объясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
| 322 |
+
Заявление: '''
|
| 323 |
+
|
| 324 |
+
ifсomission = getAnswers([application], prefix, categories, answers)
|
| 325 |
+
|
| 326 |
+
return ifсomission[0]
|
| 327 |
+
|
| 328 |
+
def getContractData(application) :
|
| 329 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты не отвечаешь на вопросы, не комментируешь,
|
| 330 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения.Ты выполняешь только эту задачу:
|
| 331 |
+
ты извлекаешь из заявления только *номер ДОГОВОРА* и "дата ДОГОВОРА".
|
| 332 |
+
Ты всегда используешь только такой формат: "Номер договора: *номер ДОГОВОРА*, Дата: *дата этого договора*;".
|
| 333 |
+
Если указан любой другой номер, но НЕ номер ДОГОВОРА, то ты отвечаешь так: "Номер договора не указан."
|
| 334 |
+
Ты должен убедиться, что слово "договор" присутствует рядом с указанным номером и исключить другие документы, такие как счета или заказы,
|
| 335 |
+
например: "В соответствии с Договором № 0001 от 01.01.2022 года...".
|
| 336 |
+
В этом примере номером договора является "0001" и датой договора является "01.01.2022".
|
| 337 |
+
Даты договоров должны быть указаны в формате "дд.мм.гггг", где "дд" - это число от 01 до 31, "мм" - число от 01 до 12,
|
| 338 |
+
а "гггг" - четырехзначное число года. Между днями, месяцами и годами должны быть разделители, например, точки или тире.
|
| 339 |
+
Ты больше НИЧЕГО не говоришь, не комментируешь, не объясняешь, не добавляешь.
|
| 340 |
+
Заявление: '''
|
| 341 |
+
|
| 342 |
+
prompt = prefix + application
|
| 343 |
+
response = getResponse(prompt)
|
| 344 |
+
response = response.replace(';', '\n')
|
| 345 |
+
response = response.replace('\\\\', '')
|
| 346 |
+
l = response.split('\n')
|
| 347 |
+
ll = []
|
| 348 |
+
for s in l :
|
| 349 |
+
s = s.strip()
|
| 350 |
+
if 'Номер договора:' == s[:15] :
|
| 351 |
+
ll.append(s)
|
| 352 |
+
|
| 353 |
+
result = '\n'.join(ll)
|
| 354 |
+
|
| 355 |
+
if result == '' :
|
| 356 |
+
result = 'не указаны'
|
| 357 |
+
|
| 358 |
+
if verbose :
|
| 359 |
+
print(result)
|
| 360 |
+
# print(name, '\n', response.strip()[:100].replace('\n', ' '))
|
| 361 |
+
|
| 362 |
+
return result
|
| 363 |
+
|
| 364 |
+
def getPersons(application) :
|
| 365 |
+
# prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов. Ты не отвечаешь на вопросы, не комментируешь,
|
| 366 |
+
# не выражаешь эмоций, не выражаешь соображений по теме заявления. Ты извлекаешь ВСЕ персональные данные из заявлений. Ты не анализируешь.
|
| 367 |
+
# Ты выполняешь только эту задачу:
|
| 368 |
+
# ты читаешь заявление и извлекаешь из заявления все встретившиеся Фамилии Имена Отчества.
|
| 369 |
+
# Ты всегда используешь только такой формат: "ФИО пользователя". Перед ответом убедись, что "ФИО" - это человеческие фамилия, имя, отчество.
|
| 370 |
+
# Ты больше ничего не говоришь, не комментируешь, не объясняешь, не добавляешь. Отвечай так: "ФИО;"; ЛИБО: "ФИО не указано".
|
| 371 |
+
# Заявление: '''
|
| 372 |
+
|
| 373 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты излекаешь информацию из заявления. Ты не отвечаешь на вопросы, не комментируешь,
|
| 374 |
+
не выражаешь эмоций, не выражаешь соображений по теме заявления. Ты извлекаешь персональные данные. Ты не анализируешь.
|
| 375 |
+
Ты выполняешь только эту задачу:
|
| 376 |
+
ты читаешь заявление и извлекаешь из заявления все встретившиеся Фамилии Имена Отчества.
|
| 377 |
+
Ты отвечаешь в формате: "ФИО: Фамилия Имя Отчество ;" или "ФИО: Фамилия И. О. ;".
|
| 378 |
+
Если в заявлении не указаны имена людей, ты отвечаешь "ФИО не указаны".
|
| 379 |
+
Перед ответом убедись, что "ФИО" - это человеческие фамилия, имя, отчество.
|
| 380 |
+
Ты больше ничего не говоришь, не комментируешь, не объясняешь, не добавляешь.
|
| 381 |
+
Заявление: '''
|
| 382 |
+
|
| 383 |
+
prompt = prefix + application
|
| 384 |
+
# prompt = prefix + appdata.loc[i, 'Текст обращения обезличенный']
|
| 385 |
+
response = getResponse(prompt)
|
| 386 |
+
response = response.replace('указаны.', 'указаны')
|
| 387 |
+
response = response.replace('.', '. ')
|
| 388 |
+
response = response.replace(';', '\n')
|
| 389 |
+
# response = response.replace('\\\\', '')
|
| 390 |
+
l = response.split('\n')
|
| 391 |
+
ll = []
|
| 392 |
+
for s in l :
|
| 393 |
+
s = s.strip()
|
| 394 |
+
if 'ФИО: ' == s[:5] and 'ФИО: не указаны' not in s:
|
| 395 |
+
ss = ''
|
| 396 |
+
s = s[5:]
|
| 397 |
+
s = re.sub('\(.+\)', '', s)
|
| 398 |
+
s = s.replace('ч.', 'ч')
|
| 399 |
+
s = s.replace('а.', 'а')
|
| 400 |
+
s = s.replace('Президент Российской Федерации', '')
|
| 401 |
+
s = s.replace(',', '').strip()
|
| 402 |
+
# n = len(s.split(' '))
|
| 403 |
+
# print(n, s.split(' '))
|
| 404 |
+
# if n > 1 and n < 4 :
|
| 405 |
+
# ll.append(s)
|
| 406 |
+
m = re.search(r'[А-Я][а-я][\w\.]+ [А-Я][\w\.]+ [А-Я][\w\.]+', s)
|
| 407 |
+
if m :
|
| 408 |
+
ss = s[m.start() : m.end()]
|
| 409 |
+
else :
|
| 410 |
+
m = re.search(r'[А-Я][а-я][\w]+ [А-Я][а-я][\w]+', s)
|
| 411 |
+
if m :
|
| 412 |
+
ss = s[m.start(): m.end()]
|
| 413 |
+
|
| 414 |
+
if ss != '' :
|
| 415 |
+
ll.append(ss)
|
| 416 |
+
|
| 417 |
+
result = '\n'.join(ll)
|
| 418 |
+
|
| 419 |
+
if result == '' :
|
| 420 |
+
result = 'не указаны'
|
| 421 |
+
|
| 422 |
+
names = result
|
| 423 |
+
|
| 424 |
+
if verbose :
|
| 425 |
+
print(names, '\n', response[:100].replace('\n', ' '))
|
| 426 |
+
|
| 427 |
+
return names
|
| 428 |
+
|
| 429 |
+
def ifLatin(s) :
|
| 430 |
+
ss = s.lower()
|
| 431 |
+
result = False
|
| 432 |
+
for c in ss :
|
| 433 |
+
if c in 'abcdefghijklmnopqrstuvwxyz' :
|
| 434 |
+
result = True
|
| 435 |
+
break
|
| 436 |
+
|
| 437 |
+
return result
|
| 438 |
+
|
| 439 |
+
stoplist = ['микрофинансовые организации',
|
| 440 |
+
'полиция',
|
| 441 |
+
'Мурманский край',
|
| 442 |
+
'Перми',
|
| 443 |
+
'Краснодар',
|
| 444 |
+
'центр занятости населения Владимирской области',
|
| 445 |
+
'банкомат N 7032 банка РСБ',
|
| 446 |
+
'банк',
|
| 447 |
+
'Криптобиржа',
|
| 448 |
+
'Nasdaq',
|
| 449 |
+
'Государство',
|
| 450 |
+
'Департаменты Москвы',
|
| 451 |
+
'"Волгабанк" и Никулин',
|
| 452 |
+
'Тендеры',
|
| 453 |
+
'Уголовные дела',
|
| 454 |
+
'Управляющими финансовой пирамидой "Волгабанк"',
|
| 455 |
+
'Санации банка',
|
| 456 |
+
'Криптобиржи',
|
| 457 |
+
'Уголовная ответственность',
|
| 458 |
+
'Статьей 185.3 УК РФ',
|
| 459 |
+
'С ТОЙОТА КРАУН Х568ПУ69',
|
| 460 |
+
'Республика Беларусь',
|
| 461 |
+
'Минфин Республики Беларусь',
|
| 462 |
+
'Московская биржа (АО НРД)',
|
| 463 |
+
'АО',
|
| 464 |
+
'прокуратура РФ',
|
| 465 |
+
'приемная президента РФ',
|
| 466 |
+
'страховая компания.',
|
| 467 |
+
'микрофинансовые организации',
|
| 468 |
+
'Следственный комитет',
|
| 469 |
+
'прокуратура',
|
| 470 |
+
'юристы',
|
| 471 |
+
'ИНН 7854523125',
|
| 472 |
+
'кредитная организация',
|
| 473 |
+
'прокуратура РФ',
|
| 474 |
+
'приемная президента РФ.',
|
| 475 |
+
'фин услуги',
|
| 476 |
+
'суд',
|
| 477 |
+
'банк',
|
| 478 |
+
'микрофинансовые организации',
|
| 479 |
+
'Государственный рееestr МФО',
|
| 480 |
+
'полиция',
|
| 481 |
+
'Прокуратура РФ',
|
| 482 |
+
'Приемная президента РФ',
|
| 483 |
+
'фирма',
|
| 484 |
+
'скоринг бюро',
|
| 485 |
+
'правоохранительные органы',
|
| 486 |
+
'Департамент здравоохранения г',
|
| 487 |
+
'Страховщик',
|
| 488 |
+
'Статьей 185']
|
| 489 |
+
|
| 490 |
+
def getCompanies(application) :
|
| 491 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты извлекаешь информацию из заявления.
|
| 492 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме заявления.
|
| 493 |
+
Ты выполняешь только эту задачу: ты извлекаешь из заявления только *названия юридических ОРГАНИЗАЦИЙ*.
|
| 494 |
+
Ты всегда используешь только этот формат: "Организация: *название организации*;".
|
| 495 |
+
Ты больше НИЧЕГО не говоришь, не комментируешь, не объясняешь, не добавляешь.
|
| 496 |
+
Если названия организаций отсутствуют, то ты даешь только ТАКОЙ ответ: "не указано".
|
| 497 |
+
Твой ответ состоит только из одного слова - *название организации.* Тебе запрещено общаться, ты всегда следуешь формату.
|
| 498 |
+
Польуйся моими советами, как определить, что это действительно название организации:
|
| 499 |
+
Памятка: Юридическая форма: Название может содержать слова, указывающие на юридическую форму организации, такие как "корпорация",
|
| 500 |
+
"общество с ограниченной ответственностью", "партнерство" и т.д. Название может состоять из аббревиатуры,
|
| 501 |
+
которая представляет собой сокращение от полного названия организации. Название может содержать описательные слова или фразы,
|
| 502 |
+
которые указывают на вид деятельности организации, ее цели или ценности.
|
| 503 |
+
Соответствие формальным требованиям: Названия организаций, связанных с денежно-кредитной политикой, платёжной системой и финансовым регулированием,
|
| 504 |
+
обычно соответствуют определенным формальным требованиям, таким как использование определенных слов, например "банк", "компания", "организация" и т.д.
|
| 505 |
+
Заявление: '''
|
| 506 |
+
|
| 507 |
+
prompt = prefix + application
|
| 508 |
+
response = getResponse(prompt)
|
| 509 |
+
l = response.split('Организация: ')
|
| 510 |
+
ll = []
|
| 511 |
+
for i in range(len(l)) :
|
| 512 |
+
Inf = 1000000
|
| 513 |
+
s = l[i]
|
| 514 |
+
x = s.find(';')
|
| 515 |
+
y = s.find('.')
|
| 516 |
+
z = s.find('(')
|
| 517 |
+
if x == -1 :
|
| 518 |
+
x = Inf
|
| 519 |
+
|
| 520 |
+
if y == -1 :
|
| 521 |
+
y = Inf
|
| 522 |
+
|
| 523 |
+
if z == -1 :
|
| 524 |
+
z = Inf
|
| 525 |
+
|
| 526 |
+
x = min(x, y, z)
|
| 527 |
+
|
| 528 |
+
if x != -1 :
|
| 529 |
+
s = l[i][:x]
|
| 530 |
+
|
| 531 |
+
s = s.strip()
|
| 532 |
+
if s != '' and not ifLatin(s) and s not in ll and s not in stoplist:
|
| 533 |
+
ll.append(s)
|
| 534 |
+
|
| 535 |
+
result = '\n'.join(ll)
|
| 536 |
+
|
| 537 |
+
if result == '' :
|
| 538 |
+
result = 'не указаны'
|
| 539 |
+
|
| 540 |
+
if verbose :
|
| 541 |
+
print(result)
|
| 542 |
+
|
| 543 |
+
return result
|
| 544 |
+
|
| 545 |
+
def getApplicationInfo(application) :
|
| 546 |
+
author = getAuthor(application)
|
| 547 |
+
persons = getPersons(application)
|
| 548 |
+
companies = getCompanies(application)
|
| 549 |
+
contractdata = getContractData(application)
|
| 550 |
+
sector = getSector(application)
|
| 551 |
+
product = getProduct(application, sector)
|
| 552 |
+
problem = getProblem(application, sector, product)
|
| 553 |
+
|
| 554 |
+
ifcontract = checkContractNumber(application)
|
| 555 |
+
ifidentified = checkIfIdentified(application)
|
| 556 |
+
ifperson = checkIfPerson(application)
|
| 557 |
+
ifcomission = checkIfcomission(application)
|
| 558 |
+
|
| 559 |
+
app_info = {}
|
| 560 |
+
app_info['Заявитель'] = author
|
| 561 |
+
app_info['Физлица'] = persons
|
| 562 |
+
app_info['Организации'] = companies
|
| 563 |
+
app_info['Данные договора'] = contractdata
|
| 564 |
+
app_info['Заявитель физическое или юридическое лицо?'] = ifperson
|
| 565 |
+
app_info['Можно ли идентифицировать лицо, на которого пожаловались?'] = ifidentified
|
| 566 |
+
app_info['Указан ли в обращении номер договора?'] = ifcontract
|
| 567 |
+
app_info['Жалоба касается комиссии за обслуживание рублевого счета?'] = ifcomission
|
| 568 |
+
app_info['Сектор'] = sector
|
| 569 |
+
app_info['Продукт'] = product
|
| 570 |
+
app_info['Проблема'] = problem
|
| 571 |
+
|
| 572 |
+
if verbose :
|
| 573 |
+
print()
|
| 574 |
+
print(i)
|
| 575 |
+
print('Заявитель', author)
|
| 576 |
+
print('Физлица', persons)
|
| 577 |
+
print('Организации', companies)
|
| 578 |
+
print('Данные договора', contractdata)
|
| 579 |
+
print('Заявитель физическое или юридическое лицо?', ifperson)
|
| 580 |
+
print('Можно ли идентифицировать лицо, на которого пожаловались?', ifidentified)
|
| 581 |
+
print('Указан ли в обращении номер договора?', ifcontract)
|
| 582 |
+
print('Жалоба касается комиссии за обслуживание рублевого счета?', ifcomission)
|
| 583 |
+
print('Сектор', sector)
|
| 584 |
+
print('Продукт', product)
|
| 585 |
+
print('Проблема', problem)
|
| 586 |
+
|
| 587 |
+
return app_info
|
| 588 |
+
|
| 589 |
+
# application = '''Я, Кристенгоф Оксана Михайловна, заключила кредитный договор с ПАО Камабанк № 59875 и № 456835645645654
|
| 590 |
+
# и договор на выдачу кредитной карты с ПАО "БСТ-Банк" №4567652124534235 и №4561254153412.
|
| 591 |
+
# 12.08.2020 года направила в банки заявление на истребование кредитной документации заказным письмом с уведомлением,
|
| 592 |
+
# но банки мне так ничего и не прислали. Прошу поспособствовать в том,что кредитные организации выслали мне кредитные договоры.
|
| 593 |
+
# '''
|
| 594 |
+
|
| 595 |
+
# verbose = False
|
| 596 |
+
# app_info = getApplicationInfo(application)
|
| 597 |
+
# print(app_info)
|
| 598 |
+
|
| 599 |
+
# Результат:
|
| 600 |
+
# {'Заявитель': 'Кристенгоф Оксана Михайловна',
|
| 601 |
+
# 'Физлица': 'Кристенгоф Оксана Михайловна',
|
| 602 |
+
# 'Организации': 'ПАО Камабанк\nПАО "БСТ-Банк"',
|
| 603 |
+
# 'Данные договора': 'Номер договора: 59875, Дата: 12.08.2020\nНомер договора: 456835645645654, Дата: 12.08.2020',
|
| 604 |
+
# 'Заявитель физическое или юридическое лицо?': 'Физ.лицо',
|
| 605 |
+
# 'Можно ли идентифицировать лицо, на которого пожаловались?': 'да',
|
| 606 |
+
# 'Указан ли в обращении номер договора?': 'да',
|
| 607 |
+
# 'Жалоба касается комиссии за обслуживание рублевого счета?': 'нет',
|
| 608 |
+
# 'Сектор': 'Кредитные организации',
|
| 609 |
+
# 'Продукт': 'Кредитные истории',
|
| 610 |
+
# 'Проблема': 'Иные виды (КО)'}
|