File size: 3,780 Bytes
942c944
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import chainlit as cl
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
import tiktoken
from langchain.document_loaders import PyMuPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Qdrant
from operator import itemgetter
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser
from qdrant_client import QdrantClient
from langchain_core.prompts import ChatPromptTemplate

# Split documents into chunks
def tiktoken_len(text):
    tokens = tiktoken.encoding_for_model("gpt-3.5-turbo").encode(
        text,
    )
    return len(tokens)

# docs = PyMuPDFLoader("Meta10k.pdf").load()

# text_splitter = RecursiveCharacterTextSplitter(
#     chunk_size = 1000,
#     chunk_overlap = 200,
#     length_function = tiktoken_len,
# )

# split_chunks = text_splitter.split_documents(docs)

embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")

# qdrant_vectorstore = Qdrant.from_documents(
#     split_chunks, 
#     embedding_model, 
#     path="./data/embeddings",
#     collection_name="Meta10k",
# )

client = QdrantClient(path="./data/embeddings") 
db = Qdrant(client=client, collection_name="Meta10k", embeddings=embedding_model,)

qdrant_retriever = db.as_retriever()

@cl.on_chat_start
def chat_start():
    
    openai_chat_model = ChatOpenAI(model="gpt-3.5-turbo")
    openai_chat_model_4 = ChatOpenAI(model="gpt-4-turbo")

    RAG_PROMPT = """
    You are an expert financial analyst.  You will be provided CONTEXT excerpts from the META company 10K annual report.  Your job is to answer the QUERY as correctly as you can using the information provided by the CONTEXT and your skills as an expert financial analyst. IF the context provided does give you enough information to answer the question, respond "I do not know"

    CONTEXT:
    {context}

    QUERY:
    {question}
    """

    EVAL_SYSTEM_TEMPLATE = """You are an expert in analyzing the quality of a response.

    You should be hyper-critical.

    Provide scores (out of 10) for the following attributes:

    1. Clarity - how clear is the response
    2. Faithfulness - how related to the original query is the response and the provided context
    3. Correctness - was the response correct?

    Please take your time, and think through each item step-by-step, when you are done - please provide your response in the following format:

    """

    EVAL_USER_TEMPLATE = """Query: {input}
    Context: {context}
    Response: {response}"""

    rag_prompt = ChatPromptTemplate.from_template(RAG_PROMPT)
    eval_prompt = ChatPromptTemplate.from_messages([
        ("system", EVAL_SYSTEM_TEMPLATE),
        ("human", EVAL_USER_TEMPLATE)
    ])

    chain = ({"context": itemgetter("question") | qdrant_retriever, "question": itemgetter("question")} | RunnablePassthrough.assign(context=itemgetter("context")) | {"response": rag_prompt | openai_chat_model, "context": itemgetter("context")})
    eval_chain = eval_prompt | openai_chat_model_4

    cl.user_session.set("chain", chain)
    cl.user_session.set("eval_chain",eval_chain)

@cl.on_message
async def on_message(message: cl.Message):
    
    chain = cl.user_session.get("chain")
    eval_chain = cl.user_session.get("eval_chain")

    response = chain.invoke({"question":message.content})

    context = "\n".join([context.page_content for context in response["context"]])
    eval_response = eval_chain.invoke({"input":message.content, "context":context, "response":response["response"].content})

    await cl.Message(response["response"].content).send()
    await cl.Message(eval_response.content).send()