Много мелких доработок
- переименован input_md => data - добавление инфы о дате, версии и авторе изменений conf-страницы в индекс - вывод этой инфы в источниках - вывод статистики последнего ответа - указание имени коллекции для qdrant - мелочи по текстовкам
This commit is contained in:
54
rag/rag.py
54
rag/rag.py
@@ -6,7 +6,7 @@ from sentence_transformers import SentenceTransformer
|
||||
|
||||
class RagSystem:
|
||||
def __init__(self,
|
||||
md_folder: str = "input_md",
|
||||
md_folder: str = "data",
|
||||
ollama_url: str = "http://localhost:11434",
|
||||
qdrant_host: str = "localhost",
|
||||
qdrant_port: int = 6333,
|
||||
@@ -27,13 +27,14 @@ class RagSystem:
|
||||
body = {"model": self.chat_model}
|
||||
requests.post(url, json=body, timeout=600)
|
||||
|
||||
def search_qdrant(self, query: str, top_k: int = 6):
|
||||
def search_qdrant(self, query: str, top_k: int = 6, qdrant_collection="rag"):
|
||||
query_vec = self.emb_model.encode(query, show_progress_bar=False).tolist()
|
||||
url = f"http://{self.qdrant_host}:{self.qdrant_port}/collections/rag_collection/points/search"
|
||||
url = f"http://{self.qdrant_host}:{self.qdrant_port}/collections/{qdrant_collection}/points/search"
|
||||
payload = {
|
||||
"vector": query_vec,
|
||||
"top": top_k,
|
||||
"with_payload": True
|
||||
"with_payload": True,
|
||||
# "score_threshold": 0.6
|
||||
}
|
||||
resp = requests.post(url, json=payload)
|
||||
if resp.status_code != 200:
|
||||
@@ -114,7 +115,7 @@ Respond."""
|
||||
# "top_p": 0.1,
|
||||
# },
|
||||
}
|
||||
self.response = requests.post(url, json=body, timeout=600)
|
||||
self.response = requests.post(url, json=body, timeout=900)
|
||||
if self.response.status_code != 200:
|
||||
return f"Ошибка генерации ответа: {self.response.status_code} {self.response.text}"
|
||||
return self.response.json().get("response", "").strip()
|
||||
@@ -127,7 +128,7 @@ Respond."""
|
||||
"messages": self.conversation_history,
|
||||
"stream": True
|
||||
}
|
||||
resp = requests.post(url, json=body, stream=True, timeout=600)
|
||||
resp = requests.post(url, json=body, stream=True, timeout=900)
|
||||
if resp.status_code != 200:
|
||||
raise RuntimeError(f"Ошибка генерации ответа: {resp.status_code} {resp.text}")
|
||||
full_answer = ""
|
||||
@@ -148,18 +149,28 @@ Respond."""
|
||||
print(f"Error processing chunk: {e}")
|
||||
|
||||
def get_prompt_eval_count(self):
|
||||
if not self.response:
|
||||
return 0
|
||||
return self.response.json().get("prompt_eval_count", 0)
|
||||
|
||||
def get_prompt_eval_duration(self):
|
||||
if not self.response:
|
||||
return 0
|
||||
return self.response.json().get("prompt_eval_duration", 0) / (10 ** 9)
|
||||
|
||||
def get_eval_count(self):
|
||||
if not self.response:
|
||||
return 0
|
||||
return self.response.json().get("eval_count", 0)
|
||||
|
||||
def get_eval_duration(self):
|
||||
if not self.response:
|
||||
return 0
|
||||
return self.response.json().get("eval_duration", 0) / (10 ** 9)
|
||||
|
||||
def get_total_duration(self):
|
||||
if not self.response:
|
||||
return 0
|
||||
return self.response.json().get("total_duration", 0) / (10 ** 9)
|
||||
|
||||
def get_tps(self):
|
||||
@@ -172,19 +183,31 @@ Respond."""
|
||||
def print_sources(context_docs: list):
|
||||
print("\n\nИсточники:")
|
||||
for idx, doc in enumerate(context_docs, start=1):
|
||||
filename = doc['payload'].get("filename", None)
|
||||
title = doc['payload'].get("filename", None)
|
||||
url = doc['payload'].get("url", None)
|
||||
title = filename
|
||||
date = doc['payload'].get("date", None)
|
||||
version = doc['payload'].get("version", None)
|
||||
author = doc['payload'].get("author", None)
|
||||
|
||||
if url is None:
|
||||
url = "(нет веб-ссылки)"
|
||||
print(f"{idx}. {title}\n {url}\n")
|
||||
if date is None:
|
||||
date = "(неизвестно)"
|
||||
if version is None:
|
||||
version = "0"
|
||||
if author is None:
|
||||
author = "(неизвестен)"
|
||||
|
||||
print(f"{idx}. {title}")
|
||||
print(f" {url} (v{version} {author})")
|
||||
print(f" актуальность на {date}")
|
||||
|
||||
def print_v(text: str, is_verbose: bool):
|
||||
if is_verbose:
|
||||
print(text)
|
||||
|
||||
def print_stats(rag: RagSystem):
|
||||
print("Статистика:")
|
||||
print("\n\nСтатистика:")
|
||||
print(f"* Time: {rag.get_total_duration()}s")
|
||||
print(f"* TPS: {rag.get_tps()}")
|
||||
print(f"* PEC: {rag.get_prompt_eval_count()}")
|
||||
@@ -202,6 +225,7 @@ def main():
|
||||
parser.add_argument("--show-prompt", default=False, action=argparse.BooleanOptionalAction, help="Показать полный промпт перед обработкой запроса")
|
||||
parser.add_argument("--qdrant-host", default="localhost", help="Qdrant host")
|
||||
parser.add_argument("--qdrant-port", type=int, default=6333, help="Qdrant port")
|
||||
parser.add_argument("--qdrant-collection", type=str, default="rag", help="Название коллекции для поиска документов")
|
||||
parser.add_argument("--ollama-url", default="http://localhost:11434", help="Ollama API URL")
|
||||
parser.add_argument("--emb-model", default="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2", help="Модель эмбеддинга")
|
||||
parser.add_argument("--chat-model", default="phi4-mini:3.8b", help="Модель генерации Ollama")
|
||||
@@ -220,6 +244,7 @@ def main():
|
||||
print_v(f"Модель эмбеддинга: {args.emb_model}", args.verbose)
|
||||
print_v(f"Модель чата: {args.chat_model}", args.verbose)
|
||||
print_v(f"Документов для поиска: {args.topk}", args.verbose)
|
||||
print_v(f"Коллекция для поиска: {args.qdrant_collection}", args.verbose)
|
||||
if os.path.exists('sys_prompt.txt'):
|
||||
print_v("Будет использоваться sys_prompt.txt!", args.verbose)
|
||||
|
||||
@@ -252,8 +277,9 @@ def main():
|
||||
|
||||
if query.lower() == "help":
|
||||
print("<<< Команды итерактивного режима:")
|
||||
print("save -- сохранить диалог в файл")
|
||||
print("exit -- выход\n")
|
||||
print("save -- сохранить диалог в файл")
|
||||
print("stats -- вывести статистику последнего ответа")
|
||||
print("exit -- выход\n")
|
||||
query = None
|
||||
continue
|
||||
|
||||
@@ -290,9 +316,9 @@ def main():
|
||||
break
|
||||
|
||||
print_v("\nПоиск релевантных документов...", args.verbose)
|
||||
context_docs = rag.search_qdrant(query, top_k=args.topk)
|
||||
context_docs = rag.search_qdrant(query, top_k=args.topk, qdrant_collection=args.qdrant_collection)
|
||||
if not context_docs:
|
||||
print_v("Релевантные документы не найдены.", args.verbose)
|
||||
print("<<< Релевантные документы не найдены")
|
||||
if args.interactive:
|
||||
query = None
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user