Spaces:
Sleeping
Sleeping
File size: 6,258 Bytes
0f8f1e7 74cc79a 0f8f1e7 86841b5 493753d 86841b5 493753d 86841b5 184c970 493753d 86841b5 0f8f1e7 493753d 0f8f1e7 493753d 0f8f1e7 493753d 0f8f1e7 493753d 285ac79 493753d 285ac79 0ca2eec 0f8f1e7 184c970 0f8f1e7 1e14a8c 0f8f1e7 493753d 0f8f1e7 493753d 74cc79a 493753d 0f8f1e7 493753d f67e311 493753d 1e14a8c 493753d 1e14a8c 493753d 05dc960 493753d 1e14a8c 493753d 485cccf 493753d 627080f 485cccf 627080f 0f8f1e7 493753d 0f8f1e7 493753d 0f8f1e7 493753d |
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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
import os
import gradio as gr
import spaces
from datasets import load_dataset, concatenate_datasets
from langchain.docstore.document import Document
from langchain.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from tqdm import tqdm
from dotenv import load_dotenv
import pickle
# Импорты для перевода
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import ChatPromptTemplate
from uz_translit import to_latin
# Загружаем переменные окружения
load_dotenv()
hf_key = os.getenv("HF_KEY")
# Путь для сохранения FAISS-индекса
INDEX_PATH = "./faiss_index"
# Инициализируем эмбеддинг-модель
embeddings = HuggingFaceEmbeddings(model_name="fitlemon/bge-m3-uz-legal-matryoshka")
translations = pickle.load(open("translations.pkl", "rb"))
def update_faiss_index():
"""
Загружает датасеты, преобразует данные в документы с метаданными,
создаёт FAISS-индекс и сохраняет его локально.
"""
train_dataset = load_dataset("fitlemon/rag-labor-codex-dataset", token=hf_key)[
"train"
]
test_dataset = load_dataset("fitlemon/rag-labor-codex-dataset", token=hf_key)[
"test"
]
dataset = concatenate_datasets([train_dataset, test_dataset])
# dataset = dataset.select(range(5)) # Для тестирования на небольшом количестве данных
docs = []
unique_chunks = set()
for row in tqdm(dataset, desc="Загрузка документов..."):
chunk = row["chunk"]
if chunk in unique_chunks:
continue
unique_chunks.add(chunk)
doc = Document(
page_content=chunk,
metadata={
"section": row["section"],
"section_name": row["section_name"],
"chapter_name": row["chapter"],
},
)
docs.append(doc)
print(f"Документы успешно загружены и преобразованы. Длина документов: {len(docs)}")
db = FAISS.from_documents(docs, embeddings)
os.makedirs(INDEX_PATH, exist_ok=True)
db.save_local(INDEX_PATH)
print("FAISS индекс обновлён и сохранён в:", INDEX_PATH)
return db
if not os.path.exists(INDEX_PATH):
db = update_faiss_index()
else:
db = FAISS.load_local(INDEX_PATH, embeddings, allow_dangerous_deserialization=True)
print("Загружен существующий FAISS индекс из:", INDEX_PATH)
def translate_ru_uz(message: str) -> str:
"""
Переводит текст с русского на узбекский с использованием ChatOpenAI.
Пример: input: "отпуск" → output: "tatil".
"""
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a helpful assistant that translates {input_language} to {output_language}. The subject of Text is Human Resources. Example input: отпуск. Output: tatil.",
),
("human", "{input}"),
]
)
llm = ChatOpenAI(
api_key=os.environ["OPENAI_API_KEY"], model="gpt-4o-mini-2024-07-18"
)
chain = prompt | llm
response = chain.invoke(
{
"input_language": "Russian",
"output_language": "Uzbek",
"input": message,
}
)
return response.content
@spaces.GPU
def retrieve_articles(query, language):
"""
Если выбран язык "Russian", переводит запрос с русского на узбекский.
Затем ищет в FAISS-индексе топ-3 наиболее релевантных документа и возвращает результат в Markdown.
"""
if language == "Russian":
translated_query = translate_ru_uz(query)
else:
translated_query = to_latin(query)
results = db.similarity_search(translated_query, k=3)
result_text = ""
for doc in results:
result_text += (
f"### {doc.metadata['section']}: {doc.metadata['section_name']}\n"
)
if language == "Russian":
result_text += f"**Текст статьи на русском:** {translations.get(doc.page_content, 'Не найден')}\n\n"
result_text += f"**Bo'lim:** {doc.metadata['chapter_name']}\n\n"
result_text += f"**Modda teksti:**\n{doc.page_content}\n\n"
result_text += "---\n\n"
return result_text
# return "Привет, мир!" if language == "Russian" else "Salom Dunyo!"
def toggle_language(current_language: str) -> gr.update:
"""
Переключает язык между "Russian" и "Uzbek".
"""
new_language = "Uzbek" if current_language == "Russian" else "Russian"
return gr.update(value=new_language)
# Создаём Gradio-интерфейс на основе Blocks
with gr.Blocks() as demo:
gr.Markdown("# Поиск по Трудовому Кодексу Республики Узбекистан (через Эмбеддинг Модель)")
gr.Markdown(
"Введите ваш вопрос и выберите язык запроса. Если выбран русский, запрос будет переведен на узбекский перед поиском."
)
with gr.Row():
language_radio = gr.Radio(
choices=["Russian", "Uzbek"], label="Язык запроса", value="Russian"
)
query_input = gr.Textbox(
lines=3, placeholder="Введите ваш вопрос о трудовом кодексе...", label="Запрос"
)
search_button = gr.Button("Поиск")
output_markdown = gr.Markdown()
search_button.click(
fn=retrieve_articles,
inputs=[query_input, language_radio],
outputs=output_markdown,
)
query_input.submit(
fn=retrieve_articles,
inputs=[query_input, language_radio],
outputs=output_markdown,
)
if __name__ == "__main__":
demo.launch()
|