File size: 3,416 Bytes
c4c5bb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.chains import create_history_aware_retriever, create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

def create_rag_chain(database: Chroma):
    """
    Tworzy 艂a艅cuch RAG z obs艂ug膮 historii konwersacji.
    """
    llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.0)
    retriever = database.as_retriever(search_kwargs={"k": 3})

    # Prompt do kontekstualizacji pytania
    contextualize_q_system_prompt = (
        "Bior膮c pod uwag臋 histori臋 czatu i ostatnie pytanie u偶ytkownika, "
        "kt贸re mo偶e odnosi膰 si臋 do kontekstu w historii czatu, "
        "sformu艂uj samodzielne pytanie, kt贸re mo偶na zrozumie膰 bez historii czatu. "
        "NIE odpowiadaj na pytanie, po prostu przeformu艂uj je, je艣li to konieczne, "
        "a w przeciwnym razie zwr贸膰 je w niezmienionej formie."
    )
    contextualize_q_prompt = ChatPromptTemplate.from_messages([
        ("system", contextualize_q_system_prompt),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}"),
    ])

    history_aware_retriever = create_history_aware_retriever(
        llm, retriever, contextualize_q_prompt
    )

    # Prompt do generowania odpowiedzi
    qa_system_prompt = (
        "Jeste艣 asystentem do zadawania pyta艅 i odpowiedzi na temat tre艣ci ze strony mojaszuflada.pl. "
        "U偶yj poni偶szych fragment贸w odzyskanego kontekstu, aby odpowiedzie膰 na pytanie. "
        "Odpowiadaj zawsze w j臋zyku polskim. "
        "Je艣li nie znasz odpowiedzi, po prostu powiedz, 偶e tego nie wiesz. "
        "Zachowaj zwi臋z艂o艣膰 odpowiedzi, ale b膮d藕 pomocny i przyjazny."
        "\n\n{context}"
    )
    qa_prompt = ChatPromptTemplate.from_messages([
        ("system", qa_system_prompt),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}"),
    ])

    question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
    rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)

    return rag_chain

def format_sources(source_docs):
    """
    Formatuje list臋 藕r贸de艂 do wy艣wietlenia w odpowiedzi.
    """
    if not source_docs:
        return "?"
    
    sources = []
    for doc in source_docs:
        metadata = doc.metadata
        title = metadata.get("title", "Brak tytu艂u")
        source_url = metadata.get("source", "Brak URL")
        
        pub_date_raw = metadata.get("published_time")
        if pub_date_raw:
            pub_date = pub_date_raw.split("T")[0]
            sources.append(f"- [{title}]({source_url}) ({pub_date})")
        else:
            sources.append(f"- [{title}]({source_url})")
    return "\n".join(sources)

def create_session_history_manager():
    """
    Tworzy mened偶er historii sesji.
    """
    store = {}
    
    def get_session_history(session_id: str) -> BaseChatMessageHistory:
        if session_id not in store:
            store[session_id] = ChatMessageHistory()
        return store[session_id]
    
    return get_session_history