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 |
+
# 'Проблема': 'Иные виды (КО)'}
|