Upload 15 files
Browse files- .gitattributes +2 -0
- app.py +27 -0
- data/chunks.json +3 -0
- data/embeddings.index +3 -0
- data/metadata.json +0 -0
- requirements.txt +0 -0
- src/__init__.py +0 -0
- src/__pycache__/__init__.cpython-311.pyc +0 -0
- src/__pycache__/generator.cpython-311.pyc +0 -0
- src/__pycache__/model.cpython-311.pyc +0 -0
- src/__pycache__/retriever.cpython-311.pyc +0 -0
- src/config.py +0 -0
- src/generator.py +35 -0
- src/model.py +13 -0
- src/retriever.py +30 -0
- src/utils.py +0 -0
.gitattributes
CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
data/chunks.json filter=lfs diff=lfs merge=lfs -text
|
37 |
+
data/embeddings.index filter=lfs diff=lfs merge=lfs -text
|
app.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from src.retriever import CustomRetriever
|
3 |
+
from src.generator import CustomGenerator
|
4 |
+
from src.model import MyRagModel
|
5 |
+
|
6 |
+
retriever = CustomRetriever(r'data/chunks.json', r'data/embeddings.index', r'data/metadata.json')
|
7 |
+
generator = CustomGenerator()
|
8 |
+
rag = MyRagModel(retriever, generator)
|
9 |
+
|
10 |
+
|
11 |
+
def generate_response(query):
|
12 |
+
return rag.get_answer(query)
|
13 |
+
|
14 |
+
|
15 |
+
interface = gr.Interface(
|
16 |
+
fn=generate_response,
|
17 |
+
inputs=gr.Textbox(label='Введите ваш вопрос: '),
|
18 |
+
outputs=gr.Textbox(label='Ответ модели: '),
|
19 |
+
title='Rag Model Demo',
|
20 |
+
description='QA ассистент по вопросам законов Кыргызской Республики. Может отвечать на вопросы по типу: '
|
21 |
+
'"Сколько лет дают за убийство человека?"',
|
22 |
+
allow_flagging='never',
|
23 |
+
)
|
24 |
+
|
25 |
+
|
26 |
+
if __name__ == '__main__':
|
27 |
+
interface.launch(share=True)
|
data/chunks.json
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:5490a3392697cd1e719445197aa3ebf4bc1ee6e3b954f231c1cc1ba97e740b61
|
3 |
+
size 19871573
|
data/embeddings.index
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:feb52c93f3dbfe55c29a6fd605898862ea2fe483687451f0706c07fa06984118
|
3 |
+
size 46215213
|
data/metadata.json
ADDED
The diff for this file is too large to render.
See raw diff
|
|
requirements.txt
ADDED
Binary file (2.46 kB). View file
|
|
src/__init__.py
ADDED
File without changes
|
src/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (170 Bytes). View file
|
|
src/__pycache__/generator.cpython-311.pyc
ADDED
Binary file (3.1 kB). View file
|
|
src/__pycache__/model.cpython-311.pyc
ADDED
Binary file (1.12 kB). View file
|
|
src/__pycache__/retriever.cpython-311.pyc
ADDED
Binary file (3.32 kB). View file
|
|
src/config.py
ADDED
File without changes
|
src/generator.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from groq import Client
|
2 |
+
|
3 |
+
|
4 |
+
class CustomGenerator:
|
5 |
+
def __init__(self, model_name='llama-3.3-70b-versatile',
|
6 |
+
api_key='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'):
|
7 |
+
self.model = model_name
|
8 |
+
self.client = Client(api_key=api_key)
|
9 |
+
self.system_prompt = """
|
10 |
+
Ты Q&A ассистент по вопросам законов Кыргызской Республики (Кыргызстана).
|
11 |
+
Твоя задача - ответить на заданный вопрос на основе переданной тебе информации.
|
12 |
+
Если вопрос касается законов Кыргызской республики, но в контексте нет ответа,
|
13 |
+
то ответь, что ты не знаешь ответа на этот вопрос. А если же вопрос не касается
|
14 |
+
законов Кыргызской Республики, то ответь только то, что ты не знаешь, потому что
|
15 |
+
ты помощник по вопросам законов Кыргызской Республики!
|
16 |
+
Укажи исходя из какой книги ответ, и сошлись на номер статьи, в конце ответа приведи добавь ссылку на книгу.
|
17 |
+
Ответ обязательно должен быть на русском, если ты придумал его на другом языке, то потом обязательно переведи на русский.
|
18 |
+
"""
|
19 |
+
|
20 |
+
def generate(self, query, context):
|
21 |
+
query_wrapper = f"""
|
22 |
+
На основе вот этой информации {context},
|
23 |
+
ответь на вопрос клиента {query},
|
24 |
+
не забудь добавить источник ответа и
|
25 |
+
не забудь, что ответ должен быть на русском.
|
26 |
+
"""
|
27 |
+
response = self.client.chat.completions.create(
|
28 |
+
model=self.model,
|
29 |
+
messages=[
|
30 |
+
{"role": "system", "content": self.system_prompt},
|
31 |
+
{"role": "user", "content": query_wrapper},
|
32 |
+
]
|
33 |
+
)
|
34 |
+
|
35 |
+
return response.choices[0].message.content
|
src/model.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .retriever import CustomRetriever
|
2 |
+
from .generator import CustomGenerator
|
3 |
+
|
4 |
+
|
5 |
+
class MyRagModel:
|
6 |
+
def __init__(self, retriever: CustomRetriever, generator: CustomGenerator):
|
7 |
+
self.retriever = retriever
|
8 |
+
self.generator = generator
|
9 |
+
|
10 |
+
def get_answer(self, query):
|
11 |
+
context = self.retriever.retrieve(query)
|
12 |
+
response = self.generator.generate(query, context)
|
13 |
+
return response
|
src/retriever.py
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sentence_transformers import CrossEncoder
|
2 |
+
from sentence_transformers import SentenceTransformer
|
3 |
+
import faiss
|
4 |
+
import json
|
5 |
+
|
6 |
+
|
7 |
+
class CustomRetriever:
|
8 |
+
def __init__(self, chunks_path, embeddings_path, metadata_path, top_k=50):
|
9 |
+
self.model_bi = SentenceTransformer("deepvk/USER-bge-m3")
|
10 |
+
self.model_cross = CrossEncoder("DiTy/cross-encoder-russian-msmarco")
|
11 |
+
with open(chunks_path, "r") as f:
|
12 |
+
self.chunks = json.load(f)
|
13 |
+
self.index = faiss.read_index(embeddings_path)
|
14 |
+
self.top_k = top_k
|
15 |
+
with open(metadata_path, "r") as f:
|
16 |
+
self.metadata = json.load(f)
|
17 |
+
|
18 |
+
def retrieve(self, query):
|
19 |
+
query_vector = self.model_bi.encode([query])
|
20 |
+
faiss.normalize_L2(query_vector)
|
21 |
+
distances, indices = self.index.search(query_vector, self.top_k)
|
22 |
+
possible_answers = list()
|
23 |
+
for i in range(len(indices[0])):
|
24 |
+
possible_answers.append(self.chunks[indices[0][i]])
|
25 |
+
s = self.model_cross.rank(query, possible_answers)
|
26 |
+
context = ''
|
27 |
+
for i in range(5):
|
28 |
+
meta = self.metadata[str(indices[0][s[i]["corpus_id"]])]
|
29 |
+
context += f"Факт {str(i + 1)}: {possible_answers[s[i]['corpus_id']]}. Источник:\nкнига - {meta['book']}\nномер статьи - {meta['article_num']}\nссылка на книгу - {meta['link']}\n"
|
30 |
+
return context
|
src/utils.py
ADDED
File without changes
|