File size: 4,730 Bytes
ac1079c
8edd424
cd75fd1
babb405
 
fecdf12
9088634
 
859a3f4
cd75fd1
fdcff15
 
cd75fd1
8edd424
cd75fd1
 
ac1079c
babb405
9088634
 
 
 
 
 
cd75fd1
ac1079c
 
99a8b0b
ac1079c
 
 
 
 
 
 
 
 
 
 
 
 
 
95f27d6
cd75fd1
 
8edd424
 
 
cd75fd1
 
fdcff15
8edd424
babb405
8edd424
03f014f
cd75fd1
 
 
 
 
073c315
 
cd75fd1
 
 
 
babb405
cd75fd1
 
99a8b0b
cd75fd1
babb405
cd75fd1
 
 
babb405
e3c118a
babb405
073c315
babb405
64fd4bf
e3c118a
 
babb405
cd75fd1
babb405
 
16919b8
022791c
babb405
cd75fd1
99a8b0b
 
ac1079c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99a8b0b
 
 
 
ac1079c
 
 
 
 
 
 
 
 
022791c
99a8b0b
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
from langchain_chroma import Chroma
from langchain_community.llms import HuggingFaceHub
from langchain.prompts import ChatPromptTemplate
from dotenv import load_dotenv
import os
import
 shutil

# Load environment variables
load_dotenv()

CHROMA_PATH = "/tmp/chroma"
DATA_PATH = ""  # Укажите путь к вашим данным
PROMPT_TEMPLATE = """
Ответь на вопрос, используя только следующий контекст:
{context}
---
Ответь на вопрос на основе приведенного контекста: {question}
"""

# Инициализация базы данных Chroma один раз при запуске
def initialize_chroma():
    
    if not os.path.exists(CHROMA_PATH):
        generate_data_store()
    embeddings = HuggingFaceEmbeddings(
        model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
        cache_folder="/tmp/model_cache",
        model_kwargs={'device': 'cpu'},
        encode_kwargs={'normalize_embeddings': True}
    )
    db = Chroma(
        persist_directory=CHROMA_PATH,
        embedding_function=embeddings
    )
    return db


def generate_data_store():
    documents = load_documents()
    if documents:
        chunks = split_text(documents)
        save_to_chroma(chunks)

def load_documents():
    file_path = os.path.join(DATA_PATH, "pl250320252.md")
    if not os.path.exists(file_path):
        print(f"Ошибка: Файл {file_path} не найден.")
        return []
    loader = UnstructuredMarkdownLoader(file_path)
    documents = loader.load()
    return documents

def split_text(documents: list[Document]):
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=900,
        chunk_overlap=300,
        length_function=len,
        add_start_index=True,
    )
    chunks = text_splitter.split_documents(documents)
    print(f"Разделено {len(documents)} документов на {len(chunks)} частей.")
    return chunks


def save_to_chroma(chunks: list[Document]):
    # Очищаем базу данных перед сохранением
    if os.path.exists(CHROMA_PATH):
        shutil.rmtree(CHROMA_PATH)

    # Инициализация эмбеддингов
    embeddings = HuggingFaceEmbeddings(
        model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
        # cache_folder="/tmp/model_cache",
        model_kwargs={'device': 'cpu'},
        encode_kwargs={'normalize_embeddings': True}
    )

    # Создание Chroma DB
    db = Chroma.from_documents(
        chunks,
        embeddings,
        persist_directory=CHROMA_PATH
    )
    print(f"Сохранено {len(chunks)} частей в {CHROMA_PATH}.")



# Обработка запроса пользователя
def process_query(query_text: str, db):
    results = db.similarity_search_with_relevance_scores(query_text, k=3)
    if not results or results[0][1] < 0.7:
        return "Не найдено подходящих результатов.", []
    context_text = "\n\n---\n\n".join([doc.page_content for doc, _ in results])
    prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
    prompt = prompt_template.format(context=context_text, question=query_text)
    model = HuggingFaceHub(
        repo_id="google/flan-t5-small",
        model_kwargs={"temperature": 0.5, "max_length": 512}
    )
    response_text = model.predict(prompt)
    sources = [doc.metadata.get("source", None) for doc, _ in results]
    return response_text, sources

# Функция для интерфейса Gradio
def chat_interface(query_text):
    db = initialize_chroma()
    response, sources = process_query(query_text, db)
    return f"Ответ: {response}\n\nИсточники: {', '.join(sources) if sources else 'Нет источников'}"

# Создаем папки при необходимости
os.makedirs("/tmp/model_cache", exist_ok=True)
os.makedirs("/tmp/chroma", exist_ok=True)

# Создание и запуск интерфейса Gradio
interface = gr.Interface(
    fn=chat_interface,
    inputs=gr.Textbox(lines=2, placeholder="Введите ваш вопрос здесь..."),
    outputs="text",
    title="Чат с документами",
    description="Задайте вопрос, и я отвечу на основе загруженных документов."
)

if __name__ == "__main__":
    interface.launch()