SergeyO7's picture
Update app.py
e1c91d4 verified
import gradio as gr
from langchain_community.document_loaders import UnstructuredMarkdownLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.documents import Document
from langchain_huggingface import HuggingFaceEmbeddings, HuggingFaceEndpoint
from langchain_community.vectorstores import FAISS # Обновленный импорт
# from langchain_community.llms import HuggingFaceHub
from langchain.prompts import ChatPromptTemplate
from dotenv import load_dotenv
import os
# Загрузка переменных окружения
load_dotenv()
DATA_PATH = "" # Укажите путь к вашему файлу
PROMPT_TEMPLATE = """
Ответь на вопрос, используя только следующий контекст:
{context}
---
Ответь на вопрос на основе приведенного контекста: {question}
"""
# Глобальная переменная для статуса
status_message = "Инициализация..."
def initialize_vectorstore():
global status_message
try:
status_message = "Загрузка и обработка документов..."
documents = load_documents()
chunks = split_text(documents)
status_message = "Создание векторной базы..."
vectorstore = save_to_faiss(chunks)
status_message = "База данных готова к использованию."
return vectorstore
except Exception as e:
status_message = f"Ошибка инициализации: {str(e)}"
raise
def load_documents():
file_path = os.path.join(DATA_PATH, "pl250320252.md")
if not os.path.exists(file_path):
raise FileNotFoundError(f"Файл {file_path} не найден")
loader = UnstructuredMarkdownLoader(file_path)
return loader.load()
def split_text(documents: list[Document]):
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=900,
chunk_overlap=300,
length_function=len,
add_start_index=True,
)
return text_splitter.split_documents(documents)
def save_to_faiss(chunks: list[Document]):
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
return FAISS.from_documents(chunks, embeddings)
def process_query(query_text: str, vectorstore):
if vectorstore is None:
return "База данных не инициализирована", []
try:
results = vectorstore.similarity_search_with_relevance_scores(query_text, k=3)
global status_message
status_message += f"\nНайдено {len(results)} результатов"
if not results:
return "Не найдено результатов.", []
context_text = "\n\n---\n\n".join([
f"Релевантность: {score:.2f}\n{doc.page_content}"
for doc, score in results
])
# Формируем строковый промпт для модели
prompt = f"Answer the question based on the following context:\n{context_text}\n\nQuestion: {query_text}"
# Используем модель t5-base для text2text-generation
model = HuggingFaceEndpoint(
repo_id="t5-base",
task="text2text-generation",
temperature=0.5,
max_length=512,
# huggingfacehub_api_token=os.getenv("HUGGINGFACEHUB_API_TOKEN") # Раскомментируйте, если нужен токен
)
# Передаем строковый промпт
response_text = model.invoke(prompt)
sources = list(set([doc.metadata.get("source", "") for doc, _ in results]))
return response_text, sources
except Exception as e:
return f"Ошибка обработки запроса: {str(e)}", []
def chat_interface(query_text):
global status_message
try:
vectorstore = initialize_vectorstore()
response, sources = process_query(query_text, vectorstore)
full_response = f"{status_message}\n\nОтвет: {response}\n\nИсточники: {', '.join(sources) if sources else 'Нет источников'}"
return full_response
except Exception as e:
return f"Критическая ошибка: {str(e)}"
# Интерфейс Gradio
interface = gr.Interface(
fn=chat_interface,
inputs=gr.Textbox(lines=2, placeholder="Введите ваш вопрос здесь..."),
outputs="text",
title="Чат с документами",
description="Задайте вопрос, и я отвечу на основе загруженных документов."
)
if __name__ == "__main__":
interface.launch()