checked / app.py
bvd757's picture
several_clients
a19b099
raw
history blame
8.75 kB
import language_tool_python
import openai
import streamlit as st
import subprocess
from pathlib import Path
import html
import docx
from io import BytesIO
is_java_installed = False
prompt = """
Ты должен писать комментарии об ошибках в тексте.
Тебе дан кусок текст, в котором есть ошибка, контекст, в котором стоит это слово и сообщение об ошибке. Твоя задача - кратко описать суть ошибки и, если необходимо, исправить её.
Исправляй только ту ошибку, на которую указывает сообщение. Отвечай на русском языке.
### Пример 1:
Кусок текста:
"кросивую"
Сообщение об ошибке:
"Возможно найдена орфографическая ошибка."
Текст:
"...т! Сегодня я был в парке и встретил там кросивую собаку. Она повиляла хвостом и побежа..."
Твой ответ:
Орфографическая ошибка в слове "кросивую" - правильно "красивую".
### Пример 2:
Кусок текста:
" "
Сообщение об ошибке:
"Повтор пробела."
Текст:
"...ретил там кросивую собаку. Она повиляла хвостом и побежала к речке. Я решил что ..."
Твой ответ:
Обнаружен повтор пробела между словами.
Теперь твоя очередь:
Кусок текста:
"{}"
Сообщение об ошибке:
"{}"
Текст:
"{}"
"""
def install_java():
global is_java_installed
if is_java_installed: return
try:
# Устанавливаем OpenJDK 17
subprocess.run(["apt-get", "update"], check=True)
subprocess.run(["apt-get", "install", "-y", "openjdk-17-jdk"], check=True)
#st.success("Java 17 установлена!")
is_java_installed = True
except Exception as e:
st.error(f"Ошибка установки Java: {e}")
@st.cache_resource
def load_assets():
openai.api_key = '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'
install_java()
tool = language_tool_python.LanguageTool('ru-RU',
language_tool_download_version="6.1")
return tool
def generate_gpt_comment_openai(inp):
response = openai.ChatCompletion.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": inp}
]
)
return response.choices[0].message['content']
def generate_gpt_comment_vsegpt(inp):
client = openai.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 generate_gpt_comment(inp, client_name):
if client_name == "openai":
return generate_gpt_comment_openai(inp)
elif client_name == "vsegpt":
return generate_gpt_comment_vsegpt(inp)
else:
raise ValueError(f"Unsupported client: {client_name}")
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': generate_gpt_comment(inp, client_name="openai"),
}
errors.append(error_info)
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", " "), errors
def extract_text_from_docx(file):
doc = docx.Document(BytesIO(file.getvalue()))
full_text = []
for para in doc.paragraphs:
full_text.append(para.text)
return "\n".join(full_text)
def main():
st.markdown("""
<style>
/* Сохраняем белый текст для темной темы */
.stApp, .stTextInput, .stTextArea, .stMarkdown {
color: white;
}
/* Специальный стиль для текста внутри выделенных ошибок */
.error-highlight {
background-color: #ffe066;
border-bottom: 2px dotted #ff9900;
position: relative;
color: black !important; /* Принудительно черный текст в выделениях */
}
/* Стиль для контейнера с результатом */
.result-container {
background: rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 8px;
border: 1px solid #444;
white-space: pre-wrap;
font-family: monospace;
}
</style>
""", unsafe_allow_html=True)
st.title('Проверка орфографии')
# Добавляем переключатель между режимами ввода
input_mode = st.radio(
"Выберите способ ввода текста:",
("Ввести текст вручную", "Загрузить Word документ"),
horizontal=True
)
text = ""
if input_mode == "Загрузить Word документ":
uploaded_file = st.file_uploader("Загрузите Word документ", type=['docx'])
if uploaded_file is not None:
try:
text = extract_text_from_docx(uploaded_file)
st.text_area("Текст из документа:", value=text, height=200, key="docx_text")
except Exception as e:
st.error(f"Ошибка при чтении файла: {e}")
else:
text = st.text_area("Введите текст для проверки:", height=200, key="manual_text")
tool = load_assets()
if st.button('Проверить текст'):
if not text.strip():
st.warning("Введите текст для проверки")
else:
text, errors = check_text(text, tool)
if not errors:
st.success("Ошибок не найдено! 👍")
else:
sorted_errors = sorted(errors, key=lambda x: x['start'])
highlighted = []
last_pos = 0
for error in sorted_errors:
highlighted.append(html.escape(text[last_pos:error['start']]))
highlighted.append(
f'<span style="background-color: #ffe066; border-bottom: 2px dotted #ff9900; '
f'position: relative;" title="{html.escape(error["message"])}">'
f'{html.escape(text[error["start"]:error["end"]])}'
f'</span>'
)
last_pos = error['end']
highlighted.append(html.escape(text[last_pos:]))
html_content = f"""
<div style="
background: white;
padding: 20px;
border-radius: 8px;
border: 1px solid #ddd;
white-space: pre-wrap;
font-family: monospace;
color: #000000;
">
{''.join(highlighted)}
</div>
"""
st.markdown("### Результат проверки:")
st.markdown(html_content, unsafe_allow_html=True)
st.markdown("### Найденные ошибки:")
for i, error in enumerate(errors, 1):
st.markdown(f"{i}. {error['message']}")
if __name__ == "__main__":
main()