VVI_team / src /rag.py
SuHoU's picture
Update src/rag.py
97ab975 verified
from qdrant_client import QdrantClient
from langchain_huggingface import HuggingFaceEmbeddings
# from langchain_community.chat_models import GigaChat
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_qdrant import QdrantVectorStore
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain.retrievers import ContextualCompressionRetriever
from sentence_transformers import CrossEncoder
from langchain_groq import ChatGroq
client = QdrantClient(
url="https://7acfa434-9e7d-4ff3-bc16-98679211cca6.europe-west3-0.gcp.cloud.qdrant.io",
api_key="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIn0.Fb6pTw9_wQqEPMe3kcAW0o-VobmCUOjlpIMHJep5UpU", # ← обязательно!
https=True
)
model_name = "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"
model_kwargs = {'device': 'cuda'}
encode_kwargs = {'normalize_embeddings': True, 'batch_size':1024}
embeddings_model = HuggingFaceEmbeddings(
model_name="sentence-transformers/paraphrase-multilingual-mpnet-base-v2",
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True, 'batch_size':1024},
)
vector_store = QdrantVectorStore(
client=client,
collection_name='film_col_1',
embedding=embeddings_model
)
llm = ChatGroq(
model="llama-3.1-8b-instant", # или "llama3-70b-8192", "mixtral-8x7b-32768"
api_key="your_key", # ← замените на свой!
temperature=0.7,
max_tokens=512,
)
base_retriever = vector_store.as_retriever(
search_type="similarity",
search_kwargs={"k": 20}
)
model_r = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-v2-m3")
compressor = CrossEncoderReranker(model=model_r, top_n=5)
retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=base_retriever
)
def format_docs(docs):
"""Форматирует документы для передачи в промпт"""
formatted = []
for i, doc in enumerate(docs, 1):
metadata = doc.metadata
vacancy_info = f"""
=== ФИЛЬМ {i} ===
Название: {metadata.get('title', 'Не указано')}
Год: {metadata.get('year', 'Не указано')}
Жанр: {metadata.get('genres', 'Не указано')}
Директор: {metadata.get('directors', 'Не указано')}
Оценка: {metadata.get('vote_average', 'Не указано')}
Количество оценок: {metadata.get('vote_count', 'Не указано')}
Ссылка: {metadata.get('tmdb_url', 'Не указано')}
Описание: {doc.page_content[:300]}...
"""
formatted.append(vacancy_info)
return "\n".join(formatted)
rag_prompt = ChatPromptTemplate.from_messages([
(
"system",
"""Ты — кинокритик с 20-летним стажем, бывший сценарист, а ныне саркастичный эксперт по мировому кинематографу! 🎬
Твоя задача — проанализировать предоставленные фильмы и дать остроумную, но профессиональную оценку с лёгкой долей цинизма и любви к кино.
Стиль анализа:
- Глубоко разбирай контекст: жанры, режиссёры, годы, рейтинги — но без занудства
- Используй кинематографические мемы и отсылки («Оскар убежал», «это не фильм — это терапия», «как в советском»)
- Подмечай абсурдные или трогательные детали: «режиссёр снял 3 фильма, а актёр — 200», «рейтинг 2.0, но постер шедевр»
- Давай рекомендации с иронией: «Смотреть только если вы фанат страданий» или «Идеально для просмотра после третьего кофе»
- Структурируй ответ с эмодзи, краткими заголовками и живыми комментариями
- Отвечай на русском языке — умно, ярко и с характером!
Помни: сарказм — да, злоба — нет. Цель — чтобы читатель улыбнулся и захотел посмотреть фильм (или хотя бы посмеялся над ним). 😏
Если среди фильмов есть что-то эпически странное, гениальное или настолько плохое, что становится хорошим — обязательно выдели это! 🍿"""
),
(
"human",
"""📽️ КОНТЕКСТ (или как говорят в индустрии — «наши материалы»):
{context}
🎯 ЗАПРОС ОТ РЕДАКЦИИ: {question}"""
)
])
# Создаем RAG цепочку
rag_chain = (
{
"context": retriever | format_docs,
"question": RunnablePassthrough()
} # словарь, в котором ключи - это переменные, которые будут переданы в промпт
| rag_prompt # промпт для RAG
| llm # тут можно поставить любую llm-модель
| StrOutputParser() # для вывода ответа в читаемом виде
)