Upload llm_2.py
Browse files- lib/llm_2.py +478 -0
lib/llm_2.py
ADDED
@@ -0,0 +1,478 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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] + '\n'
|
157 |
+
|
158 |
+
prompt = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов.
|
159 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме заявления.
|
160 |
+
Ты извлекаешь информацию. Ты не анализируешь.
|
161 |
+
Ты выполняешь только эту задачу: ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю.
|
162 |
+
Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует обращению. Проверь свой ответ дважды.
|
163 |
+
Ты всегда используешь такой формат ответа: "название категории".
|
164 |
+
Если в тексте обращения есть аббревиатуры "МФО", "МФК" или "МКК", ты должен выбрать категорию "Микрофинансовые организации".
|
165 |
+
Если в тексте обращения есть аббревиатуры "ОСАГО" или "КАСКО", ты должен выбрать категорию "Субъекты страхового дела".
|
166 |
+
Список категорий:
|
167 |
+
''' + sectortext + '\nЗаявление: ' + application
|
168 |
+
|
169 |
+
sector, response = getCategoryFromLLM(prompt, sectors)
|
170 |
+
|
171 |
+
if verbose :
|
172 |
+
print(i, ':', sector)
|
173 |
+
|
174 |
+
return sector
|
175 |
+
|
176 |
+
def getProduct(application, sector) :
|
177 |
+
product = ''
|
178 |
+
# sector = appsectors[i]
|
179 |
+
if sector != '' :
|
180 |
+
subproducts = products[sector]
|
181 |
+
|
182 |
+
producttext = ''
|
183 |
+
for j in range(len(subproducts)) :
|
184 |
+
producttext += str(j) + '. ' + subproducts[j] + '\n'
|
185 |
+
|
186 |
+
prompt = 'Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов. Ты не отвечаешь на вопросы, не комментируешь, \
|
187 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения. Ты извлекаешь персональные данные. Ты не анализируешь. \
|
188 |
+
Ты выполняешь только эту задачу: \
|
189 |
+
ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю. \
|
190 |
+
Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует заявлению. Проверь свой ответ дважды. \
|
191 |
+
Ты всегда используешь такой формат ответа: "название категории". \n\
|
192 |
+
Список категорий:\n' + producttext + '\nЗаявление: ' + application
|
193 |
+
|
194 |
+
product, response = getCategoryFromLLM(prompt, subproducts)
|
195 |
+
|
196 |
+
if verbose :
|
197 |
+
print(product)
|
198 |
+
|
199 |
+
return product
|
200 |
+
|
201 |
+
def getProblem(application, sector, product) :
|
202 |
+
problem = ''
|
203 |
+
if sector != '' and product != '':
|
204 |
+
subpproblems = problems[sector][product]
|
205 |
+
|
206 |
+
problemtext = ''
|
207 |
+
for j in range(len(subpproblems)) :
|
208 |
+
problemtext += str(j) + '. ' + subpproblems[j] + '\n'
|
209 |
+
|
210 |
+
prompt = 'Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов. Ты не отвечаешь на вопросы, не комментируешь, \
|
211 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения. Ты извлекаешь персональные данные. Ты не анализируешь. \
|
212 |
+
Ты выполняешь только эту задачу: \
|
213 |
+
ты определяешь категорию заявления. Для этого ты используешь ТОЛЬКО список возможных категорий, который я тебе предоставляю. \
|
214 |
+
Ты выбираешь только ТУ категорию, которая на сто процентов соответсвует заявлению. Проверь свой ответ дважды. \
|
215 |
+
Ты всегда используешь такой формат ответа: "название категории". \n\
|
216 |
+
Список категорий:\n' + problemtext + '\nЗаявление: ' + application
|
217 |
+
|
218 |
+
problem, response = getCategoryFromLLM(prompt, subpproblems)
|
219 |
+
|
220 |
+
if verbose :
|
221 |
+
print(problem)
|
222 |
+
|
223 |
+
return problem
|
224 |
+
|
225 |
+
def getAuthor(application) :
|
226 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты не отвечаешь на вопросы, не комментируешь,
|
227 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
228 |
+
Ты извлекаешь информацию из заявления. Ты отвечаешь на МОЙ вопрос:
|
229 |
+
"Кто является заявителем в заявлении?". Ты называешь имя заявителя в формате: "Заявитель: Фамилия Имя Отчество".
|
230 |
+
Если заявиитель не указан в заявлении, ты отвечаешь: "Заявитель: не указан".
|
231 |
+
Ты не комментируешь, не обясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
232 |
+
Обращение: '''
|
233 |
+
|
234 |
+
prompt = prefix + application
|
235 |
+
# prompt = prefix + appdata.loc[i, 'Текст обращения обезличенный']
|
236 |
+
response = getResponse(prompt)
|
237 |
+
response = response.replace('.', '. ')
|
238 |
+
name = 'не указан'
|
239 |
+
if name not in response :
|
240 |
+
m = re.search(r'Заявитель: [А-Я][а-я][\w\.]+ [А-Я][\w\.]+ [А-Я][\w\.]+', response)
|
241 |
+
if m :
|
242 |
+
name = response[m.start() + 11 : m.end()]
|
243 |
+
else :
|
244 |
+
m = re.search(r'Заявитель: [А-Я][а-я][\w]+ [А-Я][а-я][\w]+', response)
|
245 |
+
if m :
|
246 |
+
name = response[m.start() + 11 : m.end()]
|
247 |
+
|
248 |
+
if verbose :
|
249 |
+
print(name, '\n', response[:100].replace('\n', ' '))
|
250 |
+
|
251 |
+
return name
|
252 |
+
|
253 |
+
def checkContractNumber(application) :
|
254 |
+
categories = ['да', 'нет']
|
255 |
+
answers = ['да', 'нет']
|
256 |
+
|
257 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты извлекаешь информацию из заявлений.
|
258 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
259 |
+
Ты только отвечаешь на МОЙ вопрос: "Имеется ли в заявлении указанный номер договора?".
|
260 |
+
Ты отвечаешь либо ТАК "ответ: да, имеется" ЛИБО так "ответ: нет, не имеется". Конец ответа.
|
261 |
+
Если в заявлении нет слова "договор", ты отвечаешь "ответ: нет, не имеется"
|
262 |
+
Ты не комментируешь, не объясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
263 |
+
Заявление: '''
|
264 |
+
|
265 |
+
ifcontract = getAnswers([application], prefix, categories, answers)
|
266 |
+
|
267 |
+
return ifcontract[0]
|
268 |
+
|
269 |
+
def checkIfIdentified(application) :
|
270 |
+
сategories = ['нельзя', 'можно']
|
271 |
+
answers = ['нет', 'да']
|
272 |
+
|
273 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке.
|
274 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме жалобы.
|
275 |
+
Ты ищешь в заявлении объект жалобы: "Можно ли идентицифировать в заявлении объект жалобы (тот, на кого жалуется заявитель)?".
|
276 |
+
Твой ответ ВСЕГДА состоит из ТРЕХ слов: ты отвечаешь либо ТАК "да, можно", ЛИБО так "нет, нельзя".
|
277 |
+
Ты не комментируешь, не объясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
278 |
+
Жалоба: '''
|
279 |
+
|
280 |
+
ifidentified = getAnswers([application], prefix, сategories, answers)
|
281 |
+
|
282 |
+
return ifidentified[0]
|
283 |
+
|
284 |
+
def checkIfPerson(application) :
|
285 |
+
categories = ['физическое лицо', 'юридическое лицо']
|
286 |
+
answers = ['Физ.лицо', 'Юр.лицо']
|
287 |
+
|
288 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь "заявления" клиентов.
|
289 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
290 |
+
Ты извлекаешь информацию. Ты не анализируешь.
|
291 |
+
Ты отвечаешь ТОЛЬКО на мои вопросы. Ты определяешь кем является заявитель: "физическое лицо" или "юридическое лицо".
|
292 |
+
Условие: если заявление написано в первом лице (местоимения Я, МНЕ, МНОЮ, МОЕ, МЕНЯ), то это физическое лицо, НО если заявление написано в третьем лице, то это юридическое лицо.
|
293 |
+
Ты отвечаешь только так: "Заявитель: юрдическое лицо" или "Заявитель: физическое лицо".
|
294 |
+
Ты не комментируешь, не обясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
295 |
+
Заявление: '''
|
296 |
+
|
297 |
+
ifperson = getAnswers([application], prefix, categories, answers)
|
298 |
+
|
299 |
+
return ifperson[0]
|
300 |
+
|
301 |
+
def checkIfcomission(application) :
|
302 |
+
categories = ['не касается', 'касается']
|
303 |
+
answers = ['нет', 'да']
|
304 |
+
|
305 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты извлекаешь информацию из заявлений.
|
306 |
+
Ты не отвечаешь на вопросы, не комментируешь, не выражаешь эмоций, не выражаешь соображений по теме обращения.
|
307 |
+
Ты только отвечаешь на МОЙ вопрос: "Касается ли заявление комиссии за обслуживание рублевого счета?".
|
308 |
+
Ты отвечаешь либо ТАК "ответ: да, касается" ЛИБО так "ответ: нет, не касается". Конец ответа.
|
309 |
+
Если в заявлении нет слова "комиссия", ты отвечаешь "ответ: нет, не касается"
|
310 |
+
Ты не комментируешь, не объясняешь, не выражаешь мысли, вообще ничего больше не говоришь.
|
311 |
+
Заявление: '''
|
312 |
+
|
313 |
+
ifсomission = getAnswers([application], prefix, categories, answers)
|
314 |
+
|
315 |
+
return ifсomission[0]
|
316 |
+
|
317 |
+
def getContractData(application) :
|
318 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты не отвечаешь на вопросы, не комментируешь,
|
319 |
+
не выражаешь эмоций, не выражаешь соображений по теме обращения.Ты выполняешь только эту задачу:
|
320 |
+
ты извлекаешь из заявления только *номер ДОГОВОРА* и "дата ДОГОВОРА".
|
321 |
+
Ты всегда используешь только такой формат: "Номер договора: *номер ДОГОВОРА*, Дата: *дата этого договора*;".
|
322 |
+
Если указан любой другой номер, но НЕ номер ДОГОВОРА, то ты отвечаешь так: "Номер договора не указан."
|
323 |
+
Ты должен убедиться, что слово "договор" присутствует рядом с указанным номером и исключить другие документы, такие как счета или заказы,
|
324 |
+
например: "В соответствии с Договором № 0001 от 01.01.2022 года...".
|
325 |
+
В этом примере номером договора является "0001" и датой договора является "01.01.2022".
|
326 |
+
Даты договоров должны быть указаны в формате "дд.мм.гггг", где "дд" - это число от 01 до 31, "мм" - число от 01 до 12,
|
327 |
+
а "гггг" - четырехзначное число года. Между днями, месяцами и годами должны быть разделители, например, точки или тире.
|
328 |
+
Ты больше НИЧЕГО не говоришь, не комментируешь, не объясняешь, не добавляешь.
|
329 |
+
Заявление: '''
|
330 |
+
|
331 |
+
prompt = prefix + application
|
332 |
+
response = getResponse(prompt)
|
333 |
+
response = response.replace(';', '\n')
|
334 |
+
response = response.replace('\\\\', '')
|
335 |
+
l = response.split('\n')
|
336 |
+
ll = []
|
337 |
+
for s in l :
|
338 |
+
s = s.strip()
|
339 |
+
if 'Номер договора:' == s[:15] :
|
340 |
+
ll.append(s)
|
341 |
+
|
342 |
+
result = '\n'.join(ll)
|
343 |
+
|
344 |
+
if result == '' :
|
345 |
+
result = 'не указаны'
|
346 |
+
|
347 |
+
if verbose :
|
348 |
+
print(result)
|
349 |
+
# print(name, '\n', response.strip()[:100].replace('\n', ' '))
|
350 |
+
|
351 |
+
return result
|
352 |
+
|
353 |
+
def getPersons(application) :
|
354 |
+
# prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты сортируешь заявления клиентов. Ты не отвечаешь на вопросы, не комментируешь,
|
355 |
+
# не выражаешь эмоций, не выражаешь соображений по теме заявления. Ты извлекаешь ВСЕ персональные данные из заявлений. Ты не анализируешь.
|
356 |
+
# Ты выполняешь только эту задачу:
|
357 |
+
# ты читаешь заявление и извлекаешь из заявления все встретившиеся Фамилии Имена Отчества.
|
358 |
+
# Ты всегда используешь только такой формат: "ФИО пользователя". Перед ответом убедись, что "ФИО" - это человеческие фамилия, имя, отчество.
|
359 |
+
# Ты больше ничего не говоришь, не комментируешь, не объясняешь, не добавляешь. Отвечай так: "ФИО;"; ЛИБО: "ФИО не указано".
|
360 |
+
# Заявление: '''
|
361 |
+
|
362 |
+
prefix = '''Ты мой помощник. Ты отвечаешь только на РУССКОМ языке. Ты излекаешь информацию из заявления. Ты не отвечаешь на вопросы, не комментируешь,
|
363 |
+
не выражаешь эмоций, не выражаешь соображений по теме заявления. Ты извлекаешь персональные данные. Ты не анализируешь.
|
364 |
+
Ты выполняешь только эту задачу:
|
365 |
+
ты читаешь заявление и извлекаешь из заявления все встретившиеся Фамилии Имена Отчества.
|
366 |
+
Ты отвечаешь в формате: "ФИО: Фамилия Имя Отчество ;" или "ФИО: Фамилия И. О. ;".
|
367 |
+
Если в заявлении не указаны имена людей, ты отвечаешь "ФИО не указаны".
|
368 |
+
Перед ответом убедись, что "ФИО" - это человеческие фамилия, имя, отчество.
|
369 |
+
Ты больше ничего не говоришь, не комментируешь, не объясняешь, не добавляешь.
|
370 |
+
Заявление: '''
|
371 |
+
|
372 |
+
prompt = prefix + application
|
373 |
+
# prompt = prefix + appdata.loc[i, 'Текст обращения обезличенный']
|
374 |
+
response = getResponse(prompt)
|
375 |
+
response = response.replace('указаны.', 'указаны')
|
376 |
+
response = response.replace('.', '. ')
|
377 |
+
response = response.replace(';', '\n')
|
378 |
+
# response = response.replace('\\\\', '')
|
379 |
+
l = response.split('\n')
|
380 |
+
ll = []
|
381 |
+
for s in l :
|
382 |
+
s = s.strip()
|
383 |
+
if 'ФИО: ' == s[:5] and 'ФИО: не указаны' not in s:
|
384 |
+
ss = ''
|
385 |
+
s = s[5:]
|
386 |
+
s = re.sub('\(.+\)', '', s)
|
387 |
+
s = s.replace('ч.', 'ч')
|
388 |
+
s = s.replace('а.', 'а')
|
389 |
+
s = s.replace('Президент Российской Федерации', '')
|
390 |
+
s = s.replace(',', '').strip()
|
391 |
+
# n = len(s.split(' '))
|
392 |
+
# print(n, s.split(' '))
|
393 |
+
# if n > 1 and n < 4 :
|
394 |
+
# ll.append(s)
|
395 |
+
m = re.search(r'[А-Я][а-я][\w\.]+ [А-Я][\w\.]+ [А-Я][\w\.]+', s)
|
396 |
+
if m :
|
397 |
+
ss = s[m.start() : m.end()]
|
398 |
+
else :
|
399 |
+
m = re.search(r'[А-Я][а-я][\w]+ [А-Я][а-я][\w]+', s)
|
400 |
+
if m :
|
401 |
+
ss = s[m.start(): m.end()]
|
402 |
+
|
403 |
+
if ss != '' :
|
404 |
+
ll.append(ss)
|
405 |
+
|
406 |
+
result = '\n'.join(ll)
|
407 |
+
|
408 |
+
if result == '' :
|
409 |
+
result = 'не указаны'
|
410 |
+
|
411 |
+
names = result
|
412 |
+
|
413 |
+
if verbose :
|
414 |
+
print(names, '\n', response[:100].replace('\n', ' '))
|
415 |
+
|
416 |
+
return names
|
417 |
+
|
418 |
+
def getApplicationInfo(application, verbose=False):
|
419 |
+
sector = getSector(application)
|
420 |
+
product = getProduct(application, sector)
|
421 |
+
problem = getProblem(application, sector, product)
|
422 |
+
author = getAuthor(application)
|
423 |
+
persons = getPersons(application)
|
424 |
+
contractdata = getContractData(application)
|
425 |
+
|
426 |
+
ifcontract = checkContractNumber(application)
|
427 |
+
ifidentified = checkIfIdentified(application)
|
428 |
+
ifperson = checkIfPerson(application)
|
429 |
+
ifcomission = checkIfcomission(application)
|
430 |
+
|
431 |
+
app_info = {}
|
432 |
+
app_info['Сектор'] = sector
|
433 |
+
app_info['Продукт'] = product
|
434 |
+
app_info['Проблема'] = problem
|
435 |
+
app_info['Заявитель'] = author
|
436 |
+
app_info['Физлица'] = persons
|
437 |
+
app_info['Данные договора'] = contractdata
|
438 |
+
app_info['Заявитель физическое или юридическое лицо?'] = ifperson
|
439 |
+
app_info['Можно ли идентифицировать лицо, на которого пожаловались?'] = ifidentified
|
440 |
+
app_info['Указан ли в обращении номер договора?'] = ifcontract
|
441 |
+
app_info['Жалоба касается комиссии за обслуживание рублевого счета?'] = ifcomission
|
442 |
+
|
443 |
+
if verbose :
|
444 |
+
print()
|
445 |
+
print('Сектор', sector)
|
446 |
+
print('Продукт', product)
|
447 |
+
print('Проблема', problem)
|
448 |
+
print('Заявитель', author)
|
449 |
+
print('Физлица', persons)
|
450 |
+
print('Данные договора', contractdata)
|
451 |
+
print('Заявитель физическое или юридическое лицо?', ifperson)
|
452 |
+
print('Можно ли идентифициров��ть лицо, на которого пожаловались?', ifidentified)
|
453 |
+
print('Указан ли в обращении номер договора?', ifcontract)
|
454 |
+
print('Жалоба касается комиссии за обслуживание рублевого счета?', ifcomission)
|
455 |
+
|
456 |
+
return app_info
|
457 |
+
|
458 |
+
# application = '''Я, Кристенгоф Оксана Михайловна, заключила кредитный договор с ПАО Камабанк № 59875 и № 456835645645654
|
459 |
+
# и договор на выдачу кредитной карты с ПАО "БСТ-Банк" №4567652124534235 и №4561254153412.
|
460 |
+
# 12.08.2020 года направила в банки заявление на истребование кредитной документации заказным письмом с уведомлением,
|
461 |
+
# но банки мне так ничего и не прислали. Прошу поспособствовать в том,что кредитные организации выслали мне кредитные договоры.
|
462 |
+
# '''
|
463 |
+
|
464 |
+
# verbose = False
|
465 |
+
# app_info = getApplicationInfo(application)
|
466 |
+
# print(app_info)
|
467 |
+
|
468 |
+
# Результат:
|
469 |
+
# {'Сектор': 'Кредитные организации',
|
470 |
+
# 'Продукт': 'Качество обслуживания',
|
471 |
+
# 'Проблема': 'Проблемы, связанные с качеством обслуживания',
|
472 |
+
# 'Заявитель': 'Кристенгоф Оксана Михайловна',
|
473 |
+
# 'Физлица': 'Кристенгоф Оксана Михайловна',
|
474 |
+
# 'Данные договора': 'Номер договора: 59875, Дата: 12.08.2020\nНомер договора: 456835645645654, Дата: 12.08.2020',
|
475 |
+
# 'Заявитель физическое или юридическое лицо?': 'Физ.лицо',
|
476 |
+
# 'Можно ли идентифицировать лицо, на которого пожаловались?': 'да',
|
477 |
+
# 'Указан ли в обращении номер договора?': 'да',
|
478 |
+
# 'Жалоба касается комиссии за обслуживание рублевого счета?': 'нет'}
|