|
import openai |
|
from openai import OpenAI |
|
import difflib |
|
|
|
prompt_fix_text_gpt = "Исправь ошибки в данном тексте:\n{}" |
|
|
|
prompt_compare_get_comment = """ |
|
Ты должен писать комментарии об ошибках в тексте. |
|
Тебе дан кусок текст, в котором есть одна или несколько ошибок и этот же кусок текста с исправленными ошибками. |
|
Твоя задача - кратко описать суть каждой ошибки и, если необходимо, исправить её. Отвечай на русском языке. |
|
|
|
|
|
### Пример 1: |
|
original text: |
|
"кросивую" |
|
|
|
corrected text: |
|
"красивую" |
|
|
|
Твой ответ: |
|
Орфографическая ошибка: "кросивую" -> "красивую". |
|
|
|
|
|
### Пример 2: |
|
original: |
|
"я решил пойти в" |
|
|
|
corrected text: |
|
"я решил пойти в" |
|
|
|
Твой ответ: |
|
Опечатка: повтор пробла. |
|
|
|
|
|
Теперь твоя очередь: |
|
original: |
|
"{}" |
|
|
|
corrected text: |
|
"{}" |
|
""" |
|
|
|
prompt = """ |
|
Ты должен писать комментарии об ошибках в тексте. |
|
Тебе дан кусок текст, в котором есть ошибка, контекст, в котором стоит это слово и сообщение об ошибке. Твоя задача - кратко описать суть ошибки и, если необходимо, исправить её. |
|
Исправляй только ту ошибку, на которую указывает сообщение. Отвечай на русском языке. |
|
|
|
### Пример 1: |
|
Кусок текста: |
|
"кросивую" |
|
|
|
Сообщение об ошибке: |
|
"Возможно найдена орфографическая ошибка." |
|
|
|
Текст: |
|
"...т! Сегодня я был в парке и встретил там кросивую собаку. Она повиляла хвостом и побежа..." |
|
|
|
Твой ответ: |
|
Орфографическая ошибка в слове "кросивую" - правильно "красивую". |
|
|
|
### Пример 2: |
|
Кусок текста: |
|
" " |
|
|
|
Сообщение об ошибке: |
|
"Повтор пробела." |
|
|
|
Текст: |
|
"...ретил там кросивую собаку. Она повиляла хвостом и побежала к речке. Я решил что ..." |
|
|
|
Твой ответ: |
|
Обнаружен повтор пробела между словами. |
|
|
|
Теперь твоя очередь: |
|
Кусок текста: |
|
"{}" |
|
|
|
Сообщение об ошибке: |
|
"{}" |
|
|
|
Текст: |
|
"{}" |
|
""" |
|
|
|
|
|
def get_gpt_response_openai(inp): |
|
response = openai.ChatCompletion.create( |
|
model="gpt-4o-mini", |
|
messages=[ |
|
{"role": "user", "content": inp} |
|
] |
|
) |
|
return response.choices[0].message['content'] |
|
|
|
|
|
def get_gpt_response_vsegpt(inp): |
|
client = OpenAI( |
|
api_key='sk-or-vv-44ca318747a45e810149bf769e9dfbe5f42046695875efd7c9121cca590d6906', |
|
base_url='https://api.vsegpt.ru/v1' |
|
) |
|
response = client.chat.completions.create( |
|
model="gpt-4o-mini", |
|
messages=[{"role": "user", "content": inp}] |
|
).choices[0].message.content |
|
|
|
return response |
|
|
|
|
|
def get_gpt_response(inp, client_name): |
|
if client_name == "openai": |
|
return get_gpt_response_openai(inp) |
|
elif client_name == "vsegpt": |
|
return get_gpt_response_vsegpt(inp) |
|
else: |
|
raise ValueError(f"Unsupported client: {client_name}") |
|
|
|
|
|
def find_corrected_positions(original, corrected): |
|
matcher = difflib.SequenceMatcher(None, original, corrected) |
|
changes = [] |
|
|
|
for opcode in matcher.get_opcodes(): |
|
tag, i1, i2, j1, j2 = opcode |
|
if tag != 'equal': |
|
changes.append({ |
|
'original': (i1, i2), |
|
'corrected': (j1, j2), |
|
'operation': tag |
|
}) |
|
|
|
return changes |
|
|
|
|
|
def get_piece_of_text_bounds(s, start, end): |
|
if start != 0: start -= 1 |
|
while start != 0 and s[start] not in [' ', "\n", '\t']: |
|
start -= 1 |
|
start += 1 |
|
|
|
if end < len(s) - 1: end += 1 |
|
while end < len(s) - 1 and s[end] not in [' ', "\n", '\t']: |
|
end += 1 |
|
return start, end |
|
|
|
|
|
def add_comments_to_text(text, errors): |
|
errors = sorted(errors, key=lambda x: x['end']) |
|
|
|
shift = 0 |
|
for i, error in enumerate(errors, 1): |
|
error['start'] += shift |
|
error['end'] += shift |
|
inp = f"({i})" |
|
text = text[:error['end']] + inp + text[error['end']:] |
|
shift += len(inp) |
|
|
|
return text.replace("\n", " ") |
|
|
|
|
|
def check_text_chat_gpt(text, *args, **kwargs): |
|
fixed_text = get_gpt_response(prompt_fix_text_gpt.format(text), "vsegpt") |
|
changes = find_corrected_positions(text, fixed_text) |
|
errors = [] |
|
for change in changes: |
|
start_orig, end_orid = get_piece_of_text_bounds(text, change['original'][0], change['original'][1]) |
|
start_corr, end_corr = get_piece_of_text_bounds(fixed_text, change['corrected'][0], change['corrected'][1]) |
|
inp = prompt_compare_get_comment.format(text[start_orig:end_orid], fixed_text[start_corr:end_corr]) |
|
errors.append({ |
|
'start': start_orig, |
|
'end': end_orid, |
|
'message': get_gpt_response(inp, client_name="vsegpt"), |
|
}) |
|
|
|
text_with_comments = add_comments_to_text(text, errors) |
|
return text_with_comments, errors |
|
|
|
def check_text(text, tool): |
|
matches = tool.check(text) |
|
errors = [] |
|
for match in matches: |
|
inp = prompt.format(text[match.offset:match.offset + match.errorLength], |
|
match.message, match.context) |
|
error_info = { |
|
'start': match.offset, |
|
'end': match.offset + match.errorLength, |
|
'message': get_gpt_response(inp, client_name="vsegpt"), |
|
} |
|
errors.append(error_info) |
|
|
|
text_with_comments = add_comments_to_text(text, errors) |
|
return text_with_comments, errors |
|
|