File size: 5,787 Bytes
027752b
 
2a3953c
027752b
 
 
 
6fbc552
21cfc32
 
7cc9972
1848b14
 
 
 
7cc9972
 
 
027752b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1848b14
bc562ae
97ab975
2a3953c
 
027752b
 
7cc9972
 
 
027752b
7cc9972
027752b
 
6fbc552
7cc9972
 
 
 
 
 
027752b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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() # для вывода ответа в читаемом виде
)