File size: 3,727 Bytes
1ea88b6
f60d0cc
 
1ea88b6
f60d0cc
1ea88b6
21b6cd8
f60d0cc
 
 
21b6cd8
e30b3c2
f60d0cc
 
 
 
 
 
 
21b6cd8
1ea88b6
f60d0cc
21b6cd8
 
f60d0cc
21b6cd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192643b
 
 
f60d0cc
21b6cd8
f60d0cc
 
 
21b6cd8
f60d0cc
 
21b6cd8
f60d0cc
 
21b6cd8
f60d0cc
 
 
21b6cd8
f60d0cc
 
 
21b6cd8
 
f60d0cc
 
21b6cd8
f60d0cc
 
 
21b6cd8
f60d0cc
 
 
21b6cd8
f60d0cc
 
21b6cd8
f60d0cc
 
21b6cd8
 
f60d0cc
192643b
f60d0cc
 
 
 
 
 
 
 
192643b
f60d0cc
1ea88b6
f60d0cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import os
import glob
import nltk
from huggingface_hub import login
import gradio as gr

# --- Загрузка NLTK ---
try:
    nltk.data.find('tokenizers/punkt')
except LookupError:
    nltk.download('punkt', quiet=True)

from langchain_community.document_loaders import UnstructuredWordDocumentLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.chains import RetrievalQA
from langchain_huggingface import HuggingFaceEndpoint

# --- Константы ---
FAISS_INDEX_PATH = "faiss_index"
MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
REPO_ID = "google/flan-t5-large"
DOCX_FILE_PATH = ""

# --- Создание базы знаний ---
def create_vector_db():
    global DOCX_FILE_PATH
    if not os.path.exists(FAISS_INDEX_PATH):
        print("База знаний не найдена. Создаю новую...")
        docx_files = glob.glob("*.docx")
        if not docx_files:
            raise FileNotFoundError("Ошибка: Не найден .docx файл.")
        DOCX_FILE_PATH = docx_files[0]
        
        loader = UnstructuredWordDocumentLoader(DOCX_FILE_PATH)
        documents = loader.load()
        text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=150)
        docs = text_splitter.split_documents(documents)
        
        embeddings = HuggingFaceEmbeddings(model_name=MODEL_NAME)
        db = FAISS.from_documents(docs, embeddings)
        db.save_local(FAISS_INDEX_PATH)
        print("База знаний создана.")
    else:
        print("База знаний найдена.")
        docx_files = glob.glob("*.docx")
        if docx_files:
            DOCX_FILE_PATH = docx_files[0]

# --- Инициализация QA ---
def initialize_qa_chain():
    HF_TOKEN = os.environ.get("HUGGINGFACEHUB_API_TOKEN")
    if not HF_TOKEN:
        raise ValueError("Не найден HUGGINGFACEHUB_API_TOKEN.")
    
    login(token=HF_TOKEN)
    
    embeddings = HuggingFaceEmbeddings(model_name=MODEL_NAME)
    db = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
    
    llm = HuggingFaceEndpoint(
        repo_id=REPO_ID,
        max_new_tokens=512,
        temperature=0.3,
        repetition_penalty=1.1,
        huggingfacehub_api_token=HF_TOKEN
    )
    
    return RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=db.as_retriever(search_kwargs={"k": 3})
    )

# --- Основной код ---
create_vector_db()
qa_chain = initialize_qa_chain()

def chatbot_response(message, history):
    response = qa_chain.invoke(message)
    return response["result"]

# --- Интерфейс ---
with gr.Blocks(theme='gradio/soft', title="AI-Ассистент по ВКР") as demo:
    gr.Markdown("# 🤖 AI-Ассистент по вопросам ВКР")
    if DOCX_FILE_PATH:
        gr.Markdown(f"Бот отвечает на вопросы на основе документа: **{os.path.basename(DOCX_FILE_PATH)}**.")
    
    gr.ChatInterface(
        fn=chatbot_response,
        title=None,
        examples=[
            "Какие требования к объему магистерской диссертации?",
            "Как правильно оформить список литературы?",
            "Какие сроки сдачи и защиты ВКР в этом году?",
            "Что должно быть во введении?",
            "Какой процент оригинальности требуется?"
        ]
    )

demo.launch()