Loversofdeath commited on
Commit
235412b
·
verified ·
1 Parent(s): c6a0dd1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -102
app.py CHANGED
@@ -1,117 +1,168 @@
1
- import os
2
  import gradio as gr
3
- from langchain.document_loaders import TextLoader
4
- from langchain.text_splitter import RecursiveCharacterTextSplitter
5
- from langchain.vectorstores import FAISS
6
- from langchain.chains import RetrievalQA
7
- from langchain.llms import HuggingFaceHub
8
- from langchain.embeddings import HuggingFaceEmbeddings
9
- import warnings
10
 
11
- # Фикс для предупреждений
12
- warnings.filterwarnings("ignore")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
- # Конфигурация
15
- DOCS_DIR = "lore"
16
- EMBEDDINGS_MODEL = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
17
- LLM_REPO = "IlyaGusev/saiga_mistral_7b"
18
- HF_TOKEN = os.getenv("HF_TOKEN") # Добавьте в Secrets Space
19
 
20
- # 1. Проверка зависимостей
21
- def check_dependencies():
 
 
22
  try:
23
- from sentence_transformers import SentenceTransformer
24
- import torch
25
- from transformers import pipeline
26
- print("✔ Все зависимости установлены")
27
- except ImportError as e:
28
- raise ImportError(
29
- f"❌ Не хватает пакетов. Убедитесь, что requirements.txt содержит:\n"
30
- f"- sentence-transformers\n- torch\n- transformers\n\n"
31
- f"Ошибка: {str(e)}"
32
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- # 2. Загрузка документов
35
- def load_docs():
36
- docs = []
37
- if not os.path.exists(DOCS_DIR):
38
- raise FileNotFoundError(f"Папка {DOCS_DIR} не найдена!")
39
-
40
- for file in os.listdir(DOCS_DIR):
41
- if file.endswith(".txt"):
42
- try:
43
- loader = TextLoader(os.path.join(DOCS_DIR, file), encoding="utf-8")
44
- docs.extend(loader.load())
45
- print(f"✓ Загружен файл: {file}")
46
- except Exception as e:
47
- print(f"⚠ Ошибка в файле {file}: {str(e)}")
48
- return docs
49
-
50
- # 3. Инициализация модели эмбеддингов
51
- def get_embeddings():
52
- try:
53
- return HuggingFaceEmbeddings(model_name=EMBEDDINGS_MODEL)
54
- except Exception as e:
55
- raise RuntimeError(f"Ошибка инициализации эмбеддингов: {str(e)}")
56
-
57
- # 4. Основная логика
58
- def setup_qa_system():
59
- check_dependencies()
60
-
61
- # Загрузка и обработка документов
62
- documents = load_docs()
63
- if not documents:
64
- raise ValueError("Нет документов для обработки!")
65
-
66
- text_splitter = RecursiveCharacterTextSplitter(
67
- chunk_size=300,
68
- chunk_overlap=30,
69
- separators=["\n\n", "\n", " ", ""]
70
  )
71
- splits = text_splitter.split_documents(documents)
72
-
73
- # Создание векторного хранилища
74
- embeddings = get_embeddings()
75
- db = FAISS.from_documents(splits, embeddings)
76
-
77
- # Инициализация языковой модели
78
- llm = HuggingFaceHub(
79
- repo_id=LLM_REPO,
80
- huggingfacehub_api_token=HF_TOKEN,
81
- model_kwargs={
82
- "temperature": 0.2,
83
- "max_length": 300
84
- }
85
  )
86
 
87
- return RetrievalQA.from_chain_type(
88
- llm=llm,
89
- chain_type="stuff",
90
- retriever=db.as_retriever(search_kwargs={"k": 2}),
91
- return_source_documents=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  )
 
 
93
 
94
- # 5. Функция для интерфейса
95
- def answer_question(question):
 
96
  try:
97
- qa = setup_qa_system()
98
- result = qa({"query": question})
99
- answer = result["result"]
100
-
101
- # Форматирование ответа
102
- sources = list({os.path.basename(doc.metadata["source"]) for doc in result["source_documents"]})
103
- return f"{answer}\n\n(Источники: {', '.join(sources)})"
104
- except Exception as e:
105
- return f"⚠ Произошла ошибка: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- # Интерфейс
108
- with gr.Blocks(title="📚 Лор-бот") as app:
109
- gr.Markdown("## 🧛 Справочник по сверхъестественному")
110
- with gr.Row():
111
- question = gr.Textbox(label="Ваш вопрос", placeholder="Какие слабости у вампиров?")
112
- submit = gr.Button("Спросить")
113
- answer = gr.Textbox(label="Ответ", interactive=False)
114
-
115
- submit.click(answer_question, inputs=question, outputs=answer)
 
 
 
 
 
 
 
116
 
117
- app.launch(server_name="0.0.0.0", server_port=7860)
 
 
1
  import gradio as gr
2
+ from sentence_transformers import SentenceTransformer
3
+ import chromadb
4
+ from chromadb.utils import embedding_functions
5
+ import os
6
+ from langdetect import detect
 
 
7
 
8
+ # Проверяем наличие текстовых файлов и читаем их
9
+ def load_text_files():
10
+ files = {
11
+ "vampires": "vampires.txt",
12
+ "werewolves": "werewolves.txt",
13
+ "humans": "humans.txt"
14
+ }
15
+
16
+ loaded_data = {}
17
+ for key, filename in files.items():
18
+ try:
19
+ with open(filename, 'r', encoding='utf-8') as file:
20
+ loaded_data[key] = file.read()
21
+ except FileNotFoundError:
22
+ print(f"Файл {filename} не найден")
23
+ loaded_data[key] = ""
24
+
25
+ return loaded_data
26
 
27
+ # Инициализация модели для эмбеддингов
28
+ def initialize_embedding_model():
29
+ return embedding_functions.SentenceTransformerEmbeddingFunction(
30
+ model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
31
+ )
32
 
33
+ # Создание базы знаний
34
+ def create_knowledge_base(text_data, embed_fn):
35
+ client = chromadb.Client()
36
+
37
  try:
38
+ collection = client.get_collection(name="knowledge_base")
39
+ except:
40
+ collection = client.create_collection(
41
+ name="knowledge_base",
42
+ embedding_function=embed_fn
 
 
 
 
43
  )
44
+
45
+ # Добавляем документы в коллекцию
46
+ documents = []
47
+ metadatas = []
48
+ ids = []
49
+
50
+ for category, text in text_data.items():
51
+ if text: # только если текст не пустой
52
+ # Разбиваем текст на предложения или абзацы
53
+ paragraphs = [p for p in text.split('\n') if p.strip()]
54
+
55
+ for i, paragraph in enumerate(paragraphs):
56
+ documents.append(paragraph)
57
+ metadatas.append({"category": category})
58
+ ids.append(f"{category}_{i}")
59
+
60
+ if documents:
61
+ collection.add(
62
+ documents=documents,
63
+ metadatas=metadatas,
64
+ ids=ids
65
+ )
66
+
67
+ return collection
68
 
69
+ # Инициализация модели для ответов
70
+ def initialize_llm_model():
71
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
72
+
73
+ model_name = "IlyaGusev/saiga_mistral_7b"
74
+ tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=False)
75
+ model = AutoModelForCausalLM.from_pretrained(model_name)
76
+
77
+ pipe = pipeline(
78
+ "text-generation",
79
+ model=model,
80
+ tokenizer=tokenizer,
81
+ device="cpu"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  )
83
+
84
+ return pipe
85
+
86
+ # Поиск релевантной информации
87
+ def find_relevant_info(question, collection, embed_fn, n_results=3):
88
+ results = collection.query(
89
+ query_texts=[question],
90
+ n_results=n_results
 
 
 
 
 
 
91
  )
92
 
93
+ context = "\n\n".join(results['documents'][0])
94
+ return context
95
+
96
+ # Генерация ответа
97
+ def generate_response(question, context, llm_pipe):
98
+ system_prompt = """Ты - помощник, который отвечает на вопросы пользователя, используя предоставленную информацию.
99
+ Отвечай только на основе предоставленного контекста. Если ответа нет в контексте, скажи, что не знаешь.
100
+ Отвечай на русском языке."""
101
+
102
+ prompt = f"""<s>{system_prompt}
103
+ Контекст: {context}
104
+ Вопрос: {question}
105
+ Ответ:"""
106
+
107
+ output = llm_pipe(
108
+ prompt,
109
+ max_new_tokens=512,
110
+ do_sample=True,
111
+ temperature=0.7,
112
+ top_p=0.9,
113
+ repetition_penalty=1.2,
114
+ eos_token_id=2
115
  )
116
+
117
+ return output[0]["generated_text"][len(prompt):].strip()
118
 
119
+ # Основная функция для обработки запросов
120
+ def answer_question(question, history):
121
+ # Определяем язык вопроса
122
  try:
123
+ lang = detect(question)
124
+ if lang != 'ru':
125
+ return "Пожалуйста, задавайте вопросы на русском языке."
126
+ except:
127
+ pass
128
+
129
+ # Загружаем данные (если еще не загружены)
130
+ if not hasattr(answer_question, 'text_data'):
131
+ answer_question.text_data = load_text_files()
132
+
133
+ # Инициализируем модели (если еще не инициализированы)
134
+ if not hasattr(answer_question, 'embed_fn'):
135
+ answer_question.embed_fn = initialize_embedding_model()
136
+
137
+ if not hasattr(answer_question, 'collection'):
138
+ answer_question.collection = create_knowledge_base(answer_question.text_data, answer_question.embed_fn)
139
+
140
+ if not hasattr(answer_question, 'llm_pipe'):
141
+ answer_question.llm_pipe = initialize_llm_model()
142
+
143
+ # Находим релевантный контекст
144
+ context = find_relevant_info(question, answer_question.collection, answer_question.embed_fn)
145
+
146
+ # Генерируем ответ
147
+ response = generate_response(question, context, answer_question.llm_pipe)
148
+
149
+ return response
150
 
151
+ # Создаем интерфейс Gradio
152
+ with gr.Blocks() as demo:
153
+ gr.Markdown("## Чат-бот с доступом к текстовым файлам")
154
+ gr.Markdown("Задавайте вопросы о вампирах, оборотнях или людях на русском языке")
155
+
156
+ chatbot = gr.Chatbot(label="Диалог")
157
+ msg = gr.Textbox(label="Ваш вопрос")
158
+ clear = gr.Button("Очистить")
159
+
160
+ def respond(message, chat_history):
161
+ bot_message = answer_question(message, chat_history)
162
+ chat_history.append((message, bot_message))
163
+ return "", chat_history
164
+
165
+ msg.submit(respond, [msg, chatbot], [msg, chatbot])
166
+ clear.click(lambda: None, None, chatbot, queue=False)
167
 
168
+ demo.launch()