fitlemon commited on
Commit
493753d
·
verified ·
1 Parent(s): 5fbde21

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -42
app.py CHANGED
@@ -1,51 +1,49 @@
1
  import os
2
  import gradio as gr
3
- import spaces
4
  from datasets import load_dataset, concatenate_datasets
5
  from langchain.docstore.document import Document
6
  from langchain.vectorstores import FAISS
7
  from langchain_huggingface import HuggingFaceEmbeddings
8
  from tqdm import tqdm
9
-
10
- import torch
11
- print(torch.__version__)
12
- print(torch.cuda.is_available())
13
-
14
- # load env
15
  from dotenv import load_dotenv
 
16
 
17
- load_dotenv()
 
 
18
 
19
- key = os.getenv("HF_KEY")
 
 
20
 
21
  # Путь для сохранения FAISS-индекса
22
  INDEX_PATH = "./faiss_index"
23
 
24
- # Инициализируем эмбеддинг-модель (используем модель из Hugging Face)
25
  embeddings = HuggingFaceEmbeddings(model_name="fitlemon/bge-m3-uz-legal-matryoshka")
 
26
 
27
 
28
  def update_faiss_index():
29
  """
30
- Загружает датасет, преобразует данные в документы с метаданными,
31
  создаёт FAISS-индекс и сохраняет его локально.
32
  """
33
- # Загружаем датасет (например, сплит "train")
34
- train_dataset = load_dataset("fitlemon/rag-labor-codex-dataset", token=key)["train"]
35
- test_dataset = load_dataset("fitlemon/rag-labor-codex-dataset", token=key)["test"]
36
- # combine train and test datasets
 
 
37
  dataset = concatenate_datasets([train_dataset, test_dataset])
38
- # get rid off duplicate chunks
39
 
40
  docs = []
41
  unique_chunks = set()
42
  for row in tqdm(dataset, desc="Загрузка документов..."):
43
  chunk = row["chunk"]
44
- # Если chunk уже добавлен, пропускаем его
45
  if chunk in unique_chunks:
46
  continue
47
  unique_chunks.add(chunk)
48
-
49
  doc = Document(
50
  page_content=chunk,
51
  metadata={
@@ -57,53 +55,112 @@ def update_faiss_index():
57
  docs.append(doc)
58
 
59
  print(f"Документы успешно загружены и преобразованы. Длина документов: {len(docs)}")
60
- # Создаём FAISS-индекс на основе документов
61
  db = FAISS.from_documents(docs, embeddings)
62
-
63
- # Сохраняем индекс в указанную директорию
64
  os.makedirs(INDEX_PATH, exist_ok=True)
65
  db.save_local(INDEX_PATH)
66
  print("FAISS индекс обновлён и сохранён в:", INDEX_PATH)
67
  return db
68
 
69
 
70
- # Если индекс ещё не создан, обновляем его, иначе загружаем существующий
71
  if not os.path.exists(INDEX_PATH):
72
  db = update_faiss_index()
73
  else:
74
  db = FAISS.load_local(INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
75
  print("Загружен существующий FAISS индекс из:", INDEX_PATH)
76
 
77
- @spaces.GPU
78
- def retrieve_articles(query):
 
 
 
79
  """
80
- Принимает запрос пользователя, ищет в FAISS-индексе топ-3 наиболее релевантных документа
81
- и возвращает отформатированный результат в Markdown.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  """
83
- # Поиск по индексу: возвращает список из документов
84
- results = db.similarity_search(query, k=3)
 
 
 
 
 
 
 
85
 
86
- # Форматируем результаты для вывода
87
  result_text = ""
88
  for doc in results:
89
  result_text += (
90
- f"### Статья {doc.metadata['section']}: {doc.metadata['section_name']}\n"
91
  )
92
- result_text += f"**Глава:** {doc.metadata['chapter_name']}\n\n"
93
- result_text += f"**Текст статьи:**\n{doc.page_content}\n\n"
 
 
94
  result_text += "---\n\n"
95
  return result_text
96
- # return "### Hello World"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
 
98
 
99
- # Создаём Gradio-интерфейс
100
- iface = gr.Interface(
101
- fn=retrieve_articles,
102
- inputs=gr.Textbox(lines=3, placeholder="Введите ваш вопрос о кодексе..."),
103
- outputs=gr.Markdown(),
104
- title="Поиск по Кодексу через FAISS",
105
- description="Введите вопрос, и получите топ-3 наиболее релевантные статьи из кодекса.",
106
- )
 
 
107
 
108
  if __name__ == "__main__":
109
- iface.launch()
 
1
  import os
2
  import gradio as gr
 
3
  from datasets import load_dataset, concatenate_datasets
4
  from langchain.docstore.document import Document
5
  from langchain.vectorstores import FAISS
6
  from langchain_huggingface import HuggingFaceEmbeddings
7
  from tqdm import tqdm
 
 
 
 
 
 
8
  from dotenv import load_dotenv
9
+ import pickle
10
 
11
+ # Импорты для перевода
12
+ from langchain.chat_models import ChatOpenAI
13
+ from langchain.prompts.chat import ChatPromptTemplate
14
 
15
+ # Загружаем переменные окружения
16
+ load_dotenv()
17
+ hf_key = os.getenv("HF_KEY")
18
 
19
  # Путь для сохранения FAISS-индекса
20
  INDEX_PATH = "./faiss_index"
21
 
22
+ # Инициализируем эмбеддинг-модель
23
  embeddings = HuggingFaceEmbeddings(model_name="fitlemon/bge-m3-uz-legal-matryoshka")
24
+ translations = pickle.load(open("translations.pkl", "rb"))
25
 
26
 
27
  def update_faiss_index():
28
  """
29
+ Загружает датасеты, преобразует данные в документы с метаданными,
30
  создаёт FAISS-индекс и сохраняет его локально.
31
  """
32
+ train_dataset = load_dataset("fitlemon/rag-labor-codex-dataset", token=hf_key)[
33
+ "train"
34
+ ]
35
+ test_dataset = load_dataset("fitlemon/rag-labor-codex-dataset", token=hf_key)[
36
+ "test"
37
+ ]
38
  dataset = concatenate_datasets([train_dataset, test_dataset])
 
39
 
40
  docs = []
41
  unique_chunks = set()
42
  for row in tqdm(dataset, desc="Загрузка документов..."):
43
  chunk = row["chunk"]
 
44
  if chunk in unique_chunks:
45
  continue
46
  unique_chunks.add(chunk)
 
47
  doc = Document(
48
  page_content=chunk,
49
  metadata={
 
55
  docs.append(doc)
56
 
57
  print(f"Документы успешно загружены и преобразованы. Длина документов: {len(docs)}")
 
58
  db = FAISS.from_documents(docs, embeddings)
 
 
59
  os.makedirs(INDEX_PATH, exist_ok=True)
60
  db.save_local(INDEX_PATH)
61
  print("FAISS индекс обновлён и сохранён в:", INDEX_PATH)
62
  return db
63
 
64
 
 
65
  if not os.path.exists(INDEX_PATH):
66
  db = update_faiss_index()
67
  else:
68
  db = FAISS.load_local(INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
69
  print("Загружен существующий FAISS индекс из:", INDEX_PATH)
70
 
71
+
72
+ def translate_ru_uz(message: str) -> str:
73
+ """
74
+ Переводит текст с русского на узбекский с использованием ChatOpenAI.
75
+ Пример: input: "отпуск" → output: "tatil".
76
  """
77
+ prompt = ChatPromptTemplate.from_messages(
78
+ [
79
+ (
80
+ "system",
81
+ "You are a helpful assistant that translates {input_language} to {output_language}. The subject of Text is Human Resources. Example input: отпуск. Output: tatil.",
82
+ ),
83
+ ("human", "{input}"),
84
+ ]
85
+ )
86
+ llm = ChatOpenAI(
87
+ api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o-mini-2024-07-18"
88
+ )
89
+ chain = prompt | llm
90
+ response = chain.invoke(
91
+ {
92
+ "input_language": "Russian",
93
+ "output_language": "Uzbek",
94
+ "input": message,
95
+ }
96
+ )
97
+ return response.content
98
+
99
+
100
+ def retrieve_articles(query, language):
101
  """
102
+ Если выбран язык "Russian", переводит запрос с русского на уз��екский.
103
+ Затем ищет в FAISS-индексе топ-3 наиболее релевантных документа и возвращает результат в Markdown.
104
+ """
105
+ if language == "Russian":
106
+ translated_query = translate_ru_uz(query)
107
+ else:
108
+ translated_query = query
109
+
110
+ results = db.similarity_search(translated_query, k=3)
111
 
 
112
  result_text = ""
113
  for doc in results:
114
  result_text += (
115
+ f"### {doc.metadata['section']}: {doc.metadata['section_name']}\n"
116
  )
117
+ if language == "Russian":
118
+ result_text += f"**Текст статьи на русском:** {translations[doc.metadata['section']]}\n\n"
119
+ result_text += f"**Bo'lim:** {doc.metadata['chapter_name']}\n\n"
120
+ result_text += f"**Modda teksti:**\n{doc.page_content}\n\n"
121
  result_text += "---\n\n"
122
  return result_text
123
+ # return "Привет, мир!" if language == "Russian" else "Salom Dunyo!"
124
+
125
+
126
+ def toggle_language(current_language: str) -> gr.update:
127
+ """
128
+ Переключает язык между "Russian" и "Uzbek".
129
+ """
130
+ new_language = "Uzbek" if current_language == "Russian" else "Russian"
131
+ return gr.update(value=new_language)
132
+
133
+
134
+ # Создаём Gradio-интерфейс на основе Blocks
135
+ with gr.Blocks() as demo:
136
+ gr.Markdown("# Поиск по Кодексу через Эмбеддинг Модель")
137
+ gr.Markdown(
138
+ "Введите ваш вопрос и выберите язык запроса. Если выбран русский, запрос будет переведен на узбекский перед поиском."
139
+ )
140
+
141
+ with gr.Row():
142
+ language_radio = gr.Radio(
143
+ choices=["Russian", "Uzbek"], label="Язык запроса", value="Russian"
144
+ )
145
+
146
+ with gr.Row():
147
+ query_input = gr.Textbox(
148
+ lines=3, placeholder="Введите ваш вопрос о кодексе...", label="Запрос"
149
+ )
150
+ search_button = gr.Button("Поиск")
151
 
152
+ output_markdown = gr.Markdown()
153
 
154
+ search_button.click(
155
+ fn=retrieve_articles,
156
+ inputs=[query_input, language_radio],
157
+ outputs=output_markdown,
158
+ )
159
+ query_input.submit(
160
+ fn=retrieve_articles,
161
+ inputs=[query_input, language_radio],
162
+ outputs=output_markdown,
163
+ )
164
 
165
  if __name__ == "__main__":
166
+ demo.launch()