Wplotnikow commited on
Commit
f60d0cc
·
verified ·
1 Parent(s): 53d6f1a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -61
app.py CHANGED
@@ -1,72 +1,135 @@
1
- import gradio as gr
2
  import os
3
- import nltk # Импортируем новую библиотеку
4
- from langchain_community.embeddings import HuggingFaceEmbeddings
5
- from langchain_community.vectorstores import FAISS
6
- from langchain.chains import RetrievalQA
7
- from langchain_community.llms import HuggingFaceHub
8
  from huggingface_hub import login
9
- from langchain_community.document_loaders import UnstructuredWordDocumentLoader
10
- from langchain.text_splitter import RecursiveCharacterTextSplitter
11
 
12
- # --- ЗАГРУЗКА ДОПОЛНИТЕЛЬНЫХ КОМПОНЕНТОВ ДЛЯ ОБРАБОТКИ ТЕКСТА ---
13
- # Эти строки решают ошибку 'LookupError: Resource punkt not found'
14
- # Они скачивают необходимые языковые модели для разделения текста на предложения.
15
- nltk.download('punkt')
 
 
 
 
 
 
16
 
17
- # --- КОНФИГУРАЦИЯ ---
18
- HF_TOKEN = os.environ.get("HUGGINGFACEHUB_API_TOKEN")
19
- login(token=HF_TOKEN)
20
 
21
- EMBEDDING_MODEL = "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"
22
- LLM_REPO_ID = "mistralai/Mistral-7B-Instruct-v0.2"
 
 
 
 
 
 
 
23
  FAISS_INDEX_PATH = "faiss_index"
24
- SOURCE_DOCUMENT = "Правила подготовки ВКР_СУЛ_набор 2024.docx"
 
 
 
25
 
26
- # --- АВТОМАТИЧЕСКАЯ ПОДГОТОВКА БАЗЫ ЗНАНИЙ (ПРИ ПЕРВОМ ЗАПУСКЕ) ---
27
  def create_vector_db_if_not_exists():
28
- if not os.path.exists(FAISS_INDEX_PATH):
29
- print("База знаний не найдена. Запускаю процесс создания...")
30
- if not os.path.exists(SOURCE_DOCUMENT):
31
- raise FileNotFoundError(f"Ошибка: Файл '{SOURCE_DOCUMENT}' не найден.")
32
-
33
- loader = UnstructuredWordDocumentLoader(SOURCE_DOCUMENT)
34
- documents = loader.load()
35
- text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
36
- docs = text_splitter.split_documents(documents)
37
- embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
38
- db = FAISS.from_documents(docs, embeddings)
39
- db.save_local(FAISS_INDEX_PATH)
40
- print(f"База знаний успешно создана.")
41
- else:
42
- print(f"Обнаружена существующая база знаний. Загружаю ее.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  create_vector_db_if_not_exists()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- # --- ЗАГРУЗКА КОМПОНЕНТОВ ДЛЯ ЧАТ-БОТА ---
47
- embeddings = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL)
48
- db = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
49
- llm = HuggingFaceHub(repo_id=LLM_REPO_ID, model_kwargs={"temperature": 0.1, "max_new_tokens": 1024})
50
- qa_chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=db.as_retriever(search_kwargs={"k": 3}), return_source_documents=True)
51
-
52
- # --- ФУНКЦИЯ ДЛЯ ИНТЕРФЕЙСА ---
53
- def get_response(message, history):
54
- prompt = f"Инструкция: Ты — вежливый и точный ассистент для студентов. Отвечай на вопрос пользователя строго на основе предоставленного контекста. Если в контексте нет ответа, вежливо сообщи, что не можешь ответить. Отвечай на русском языке. Вопрос: {message}"
55
- result = qa_chain({"query": prompt})
56
- return result["result"].split("Ответ:")[-1].strip()
57
-
58
- # --- СОЗДАНИЕ ИНТЕРФЕЙСА GRADIO ---
59
- demo = gr.ChatInterface(
60
- fn=get_response,
61
- title="🎓 Ассистент по написанию ВКР",
62
- description="Задайте свой вопрос по правилам оформления, срокам или структуре выпускной квалификационной работы.",
63
- examples=[
64
- "Какой должен быть объем работы в страницах?",
65
- "Как правильно оформить ссылку на интернет-источник?",
66
- "Что делать, если таблица не помещается на одну страницу?",
67
- "Какие требования к оригинальности текста?"
68
- ]
69
- )
70
-
71
- if __name__ == "__main__":
72
- demo.launch()
 
 
1
  import os
2
+ import glob
3
+ import nltk
 
 
 
4
  from huggingface_hub import login
5
+ import gradio as gr
 
6
 
7
+ # ШАГ 1: Гарантированная загрузка необходимого компонента NLTK
8
+ # Эта команда выполняется в самом начале и решает ошибку 'LookupError'.
9
+ try:
10
+ print("Проверяем наличие NLTK компонента 'punkt'...")
11
+ nltk.data.find('tokenizers/punkt')
12
+ print("'punkt' уже на месте.")
13
+ except LookupError:
14
+ print("Компонент 'punkt' не найден. Запускаю принудительную загрузку...")
15
+ nltk.download('punkt', quiet=False)
16
+ print("Загрузка 'punkt' завершена.")
17
 
 
 
 
18
 
19
+ from langchain_community.document_loaders import UnstructuredWordDocumentLoader
20
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
21
+ from langchain_community.embeddings import HuggingFaceEmbeddings
22
+ from langchain_community.vectorstores import FAISS
23
+ from langchain.chains import RetrievalQA
24
+ from langchain_huggingface import HuggingFaceEndpoint
25
+
26
+ # --- Константы и настройки ---
27
+ DOCX_FILE_PATH = "" # Путь будет определен автоматически
28
  FAISS_INDEX_PATH = "faiss_index"
29
+ MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
30
+ REPO_ID = "mistralai/Mistral-7B-Instruct-v0.2"
31
+
32
+ # --- ШАГ 2: Автоматическое создание базы знаний ---
33
 
 
34
  def create_vector_db_if_not_exists():
35
+ """Создает векторную базу данных, если она еще не создана."""
36
+ if os.path.exists(FAISS_INDEX_PATH):
37
+ print(f"База знаний найдена в '{FAISS_INDEX_PATH}'. Пропускаю создание.")
38
+ return
39
+
40
+ print("База знаний не найдена. Запускаю процесс создания...")
41
+
42
+ # Автоматически находим первый .docx файл в репозитории
43
+ docx_files = glob.glob("*.docx")
44
+ if not docx_files:
45
+ raise FileNotFoundError("Ошибка: Не найден .docx файл в репозитории. Пожалуйста, загрузите ваш документ.")
46
+
47
+ global DOCX_FILE_PATH
48
+ DOCX_FILE_PATH = docx_files[0]
49
+ print(f"Найден документ для обработки: {DOCX_FILE_PATH}")
50
+
51
+ # Загрузка и обработка документа
52
+ loader = UnstructuredWordDocumentLoader(DOCX_FILE_PATH)
53
+ documents = loader.load()
54
+
55
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150)
56
+ docs = text_splitter.split_documents(documents)
57
+
58
+ print(f"Документ разделен на {len(docs)} частей.")
59
+
60
+ # Создание эмбеддингов и сохранение базы
61
+ embeddings = HuggingFaceEmbeddings(model_name=MODEL_NAME)
62
+ db = FAISS.from_documents(docs, embeddings)
63
+ db.save_local(FAISS_INDEX_PATH)
64
+
65
+ print(f"База знаний успешно создана и сохранена в '{FAISS_INDEX_PATH}'.")
66
+
67
+ # --- ШАГ 3: Загрузка AI и настройка логики чат-бота ---
68
+
69
+ def initialize_qa_chain():
70
+ """Инициализирует и возвращает готовую к работе цепочку QA."""
71
+ # Проверка наличия токена
72
+ HF_TOKEN = os.environ.get("HUGGINGFACEHUB_API_TOKEN")
73
+ if not HF_TOKEN:
74
+ raise ValueError("Секрет 'HUGGINGFACEHUB_API_TOKEN' не найден. Пожалуйста, добавьте его в настройках Space.")
75
+
76
+ login(token=HF_TOKEN)
77
+ print("Успешная аутентификация по токену.")
78
 
79
+ # Загрузка векторной базы
80
+ embeddings = HuggingFaceEmbeddings(model_name=MODEL_NAME)
81
+ db = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
82
+
83
+ # Настройка языковой модели (LLM) через новый класс HuggingFaceEndpoint
84
+ llm = HuggingFaceEndpoint(
85
+ repo_id=REPO_ID,
86
+ temperature=0.3,
87
+ max_new_tokens=512,
88
+ repetition_penalty=1.1,
89
+ huggingfacehub_api_token=HF_TOKEN
90
+ )
91
+
92
+ # Создание цепочки Вопрос-Ответ
93
+ qa_chain = RetrievalQA.from_chain_type(
94
+ llm=llm,
95
+ chain_type="stuff",
96
+ retriever=db.as_retriever(search_kwargs={"k": 3}),
97
+ return_source_documents=True
98
+ )
99
+ print("Цепочка QA успешно инициализирована.")
100
+ return qa_chain
101
+
102
+ # --- Основной код ---
103
  create_vector_db_if_not_exists()
104
+ qa_chain = initialize_qa_chain()
105
+
106
+ def chatbot_response(message, history):
107
+ """Основная функция для генерации ответа чат-бота."""
108
+ response = qa_chain.invoke({"query": message})
109
+ return response["result"]
110
+
111
+ # --- ШАГ 4: Создание веб-интерфейса ---
112
+
113
+ with gr.Blocks(theme='gradio/soft', title="AI-Ассистент по ВКР") as demo:
114
+ gr.Markdown("# 🤖 AI-Ассистент по вопросам ВКР")
115
+ gr.Markdown(f"Этот бот отвечает на вопросы на основе документа: **{os.path.basename(DOCX_FILE_PATH)}**.")
116
+
117
+ chatbot = gr.ChatInterface(
118
+ fn=chatbot_response,
119
+ chatbot=gr.Chatbot(height=400),
120
+ textbox=gr.Textbox(placeholder="Задайте свой вопрос о правилах оформления, сроках или структуре ВКР...", container=False, scale=7),
121
+ title=None,
122
+ examples=[
123
+ "Какие требования к объему магистерской диссертации?",
124
+ "Как правильно оформить список литературы?",
125
+ "Какие сроки сдачи и защиты ВКР в этом году?",
126
+ "Что должно быть во введении?",
127
+ "Какой процент оригинальности требуется?"
128
+ ],
129
+ clear_btn="🗑️ Очистить диалог",
130
+ retry_btn=None,
131
+ undo_btn=None,
132
+ )
133
 
134
+ # Запуск приложения
135
+ demo.launch()