SergeyO7 commited on
Commit
2b5826f
·
verified ·
1 Parent(s): 7ae56f3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -84
app.py CHANGED
@@ -3,19 +3,16 @@ from langchain_community.document_loaders import UnstructuredMarkdownLoader
3
  from langchain.text_splitter import RecursiveCharacterTextSplitter
4
  from langchain_core.documents import Document
5
  from langchain_huggingface import HuggingFaceEmbeddings
6
- from langchain_chroma import Chroma
7
- from langchain.vectorstores import FAISS
8
  from langchain_community.llms import HuggingFaceHub
9
  from langchain.prompts import ChatPromptTemplate
10
  from dotenv import load_dotenv
11
  import os
12
- import shutil
13
 
14
  # Загрузка переменных окружения
15
  load_dotenv()
16
 
17
- CHROMA_PATH = "/tmp/chroma"
18
- DATA_PATH = "" # Укажите путь к вашим данным, например "data", если файл не в корне
19
  PROMPT_TEMPLATE = """
20
  Ответь на вопрос, используя только следующий контекст:
21
  {context}
@@ -26,47 +23,29 @@ PROMPT_TEMPLATE = """
26
  # Глобальная переменная для статуса
27
  status_message = "Инициализация..."
28
 
29
- def initialize_chroma():
30
  global status_message
31
- status_message = "Инициализация векторной базы..."
32
- else:
33
- status_message = "База данных Chroma уже существует. Пересоздаем базу данных..."
34
- shutil.rmtree(CHROMA_PATH)
35
 
36
- generate_data_store()
37
- status_message
38
- = "База данных Chroma создана и подготовлена."
39
-
40
- embeddings = HuggingFaceEmbeddings(
41
- model_name="sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
42
- cache_folder="/tmp/model_cache",
43
- model_kwargs={'device': 'cpu'},
44
- encode_kwargs={'normalize_embeddings': True}
45
- )
46
- db = Chroma(
47
- persist_directory=CHROMA_PATH,
48
- embedding_function=embeddings
49
- )
50
- return db
51
 
52
- def generate_data_store():
53
- documents = load_documents()
54
- if not documents:
55
- raise Exception("Документы не загружены!")
56
- chunks = split_text(documents)
57
- status_message = f"Первые 50 символов первого чанка: {chunks[0].page_content[:50]}"
58
- save_to_chroma(chunks)
59
-
60
-
61
  def load_documents():
62
  file_path = os.path.join(DATA_PATH, "pl250320252.md")
63
  if not os.path.exists(file_path):
64
- global status_message
65
- status_message = f"Ошибка: Файл {file_path} не найден."
66
- return []
67
  loader = UnstructuredMarkdownLoader(file_path)
68
- documents = loader.load()
69
- return documents
70
 
71
  def split_text(documents: list[Document]):
72
  text_splitter = RecursiveCharacterTextSplitter(
@@ -75,59 +54,58 @@ def split_text(documents: list[Document]):
75
  length_function=len,
76
  add_start_index=True,
77
  )
78
- chunks = text_splitter.split_documents(documents)
79
- global status_message
80
- status_message = f"\nРазделено {len(documents)} документов на {len(chunks)} частей."
81
- return chunks
82
 
83
- def save_to_chroma(chunks: list[Document]):
84
- if os.path.exists(CHROMA_PATH):
85
- shutil.rmtree(CHROMA_PATH)
86
  embeddings = HuggingFaceEmbeddings(
87
- model_name="sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
88
- model_kwargs={'device': 'cpu', 'trust_remote_code': True},
89
- encode_kwargs={'normalize_embeddings': False} # Экспериментируйте с этим
90
- )
91
- Chroma.from_documents(
92
- chunks,
93
- embeddings,
94
- persist_directory=CHROMA_PATH
95
  )
 
96
 
97
- def process_query(query_text: str, db):
98
- results = db.similarity_search_with_relevance_scores(query_text, k=3)
99
- global status_message
100
- status_message += f"\nНайдено {len(results)} результатов с релевантностью: {[round(score, 2) for _, score in results]}"
101
-
102
- if not results:
103
- return "Не найдено подходящих результатов.", []
104
 
105
- if results[0][1] < 0.5:
106
- response = "Нет высококачественных совпадений. Возможные варианты:\n"
107
- response += "\n".join([f"- {doc.page_content[:50]}..." for doc, _ in results])
108
- return response, [doc.metadata.get("source") for doc, _ in results]
109
-
110
- context_text = "\n\n---\n\n".join([doc.page_content for doc, _ in results])
111
- prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
112
- prompt = prompt_template.format(context=context_text, question=query_text)
113
- model = HuggingFaceHub(
114
- repo_id="google/flan-t5-small",
115
- model_kwargs={"temperature": 0.5, "max_length": 512}
116
- )
117
- response_text = model.predict(prompt)
118
- sources = [doc.metadata.get("source", None) for doc, _ in results]
119
- return response_text, sources
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  def chat_interface(query_text):
122
  global status_message
123
- db = initialize_chroma()
124
- response, sources = process_query(query_text, db)
125
- full_response = f"{status_message}\n\nОтвет: {response}\n\nИсточники: {', '.join(sources) if sources else 'Нет источников'}"
126
- return full_response
127
-
128
- # Создание папок
129
- os.makedirs("/tmp/model_cache", exist_ok=True)
130
- os.makedirs("/tmp/chroma", exist_ok=True)
131
 
132
  # Интерфейс Gradio
133
  interface = gr.Interface(
 
3
  from langchain.text_splitter import RecursiveCharacterTextSplitter
4
  from langchain_core.documents import Document
5
  from langchain_huggingface import HuggingFaceEmbeddings
6
+ from langchain_community.vectorstores import FAISS # Обновленный импорт
 
7
  from langchain_community.llms import HuggingFaceHub
8
  from langchain.prompts import ChatPromptTemplate
9
  from dotenv import load_dotenv
10
  import os
 
11
 
12
  # Загрузка переменных окружения
13
  load_dotenv()
14
 
15
+ DATA_PATH = "" # Укажите путь к вашему файлу
 
16
  PROMPT_TEMPLATE = """
17
  Ответь на вопрос, используя только следующий контекст:
18
  {context}
 
23
  # Глобальная переменная для статуса
24
  status_message = "Инициализация..."
25
 
26
+ def initialize_vectorstore():
27
  global status_message
28
+ try:
29
+ status_message = "Загрузка и обработка документов..."
30
+ documents = load_documents()
31
+ chunks = split_text(documents)
32
 
33
+ status_message = "Создание векторной базы..."
34
+ vectorstore = save_to_faiss(chunks)
35
+
36
+ status_message = "База данных готова к использованию."
37
+ return vectorstore
38
+
39
+ except Exception as e:
40
+ status_message = f"Ошибка инициализации: {str(e)}"
41
+ raise
 
 
 
 
 
 
42
 
 
 
 
 
 
 
 
 
 
43
  def load_documents():
44
  file_path = os.path.join(DATA_PATH, "pl250320252.md")
45
  if not os.path.exists(file_path):
46
+ raise FileNotFoundError(f"Файл {file_path} не найден")
 
 
47
  loader = UnstructuredMarkdownLoader(file_path)
48
+ return loader.load()
 
49
 
50
  def split_text(documents: list[Document]):
51
  text_splitter = RecursiveCharacterTextSplitter(
 
54
  length_function=len,
55
  add_start_index=True,
56
  )
57
+ return text_splitter.split_documents(documents)
 
 
 
58
 
59
+ def save_to_faiss(chunks: list[Document]):
 
 
60
  embeddings = HuggingFaceEmbeddings(
61
+ model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
62
+ model_kwargs={'device': 'cpu'},
63
+ encode_kwargs={'normalize_embeddings': True}
 
 
 
 
 
64
  )
65
+ return FAISS.from_documents(chunks, embeddings)
66
 
67
+ def process_query(query_text: str, vectorstore):
68
+ if vectorstore is None:
69
+ return "База данных не инициализирована", []
 
 
 
 
70
 
71
+ try:
72
+ results = vectorstore.similarity_search_with_relevance_scores(query_text, k=3)
73
+ global status_message
74
+ status_message += f"\nНайдено {len(results)} результатов"
75
+
76
+ if not results:
77
+ return "Не найдено результатов.", []
78
+
79
+ context_text = "\n\n---\n\n".join([
80
+ f"Релевантность: {score:.2f}\n{doc.page_content}"
81
+ for doc, score in results
82
+ ])
83
+
84
+ prompt_template = ChatPromptTemplate.from_template(PROMPT_TEMPLATE)
85
+ prompt = prompt_template.format(context=context_text, question=query_text)
86
+
87
+ model = HuggingFaceHub(
88
+ repo_id="bert-base-multilingual-cased",
89
+ task="text2text-generation", # Указываем задачу
90
+ model_kwargs={"temperature": 0.5, "max_length": 512}
91
+ )
92
+ response_text = model.predict(prompt)
93
+
94
+ sources = list(set([doc.metadata.get("source", "") for doc, _ in results]))
95
+ return response_text, sources
96
+
97
+ except Exception as e:
98
+ return f"Ошибка обработки запроса: {str(e)}", []
99
 
100
  def chat_interface(query_text):
101
  global status_message
102
+ try:
103
+ vectorstore = initialize_vectorstore()
104
+ response, sources = process_query(query_text, vectorstore)
105
+ full_response = f"{status_message}\n\nОтвет: {response}\n\nИсточники: {', '.join(sources) if sources else 'Нет источников'}"
106
+ return full_response
107
+ except Exception as e:
108
+ return f"Критическая ошибка: {str(e)}"
 
109
 
110
  # Интерфейс Gradio
111
  interface = gr.Interface(