muryshev commited on
Commit
01f0b80
·
1 Parent(s): a5177da
Files changed (3) hide show
  1. .gitignore +0 -1
  2. app.py +7 -4
  3. 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 llm_2
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 = llm_2.getApplicationInfo(text_data)
63
-
64
- return Response(json.dumps(app_info, sort_keys=False, ensure_ascii=False), content_type='application/json; charset=utf-8')
 
 
 
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
+ # 'Проблема': 'Иные виды (КО)'}