File size: 3,640 Bytes
a14e12b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
005ee00
a14e12b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98e1cdc
a14e12b
98e1cdc
a14e12b
 
 
28ed6f2
a14e12b
 
 
 
 
 
 
 
 
23c0047
a14e12b
 
 
 
 
 
 
 
 
 
 
 
 
713d963
 
 
 
e14fc2a
 
 
 
713d963
 
 
 
 
7a945f6
713d963
7a945f6
713d963
 
 
 
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
import os 
import openai
import chainlit as cl
from chainlit.prompt import Prompt, PromptMessage
from langchain.chat_models import ChatOpenAI
from dotenv import load_dotenv
import pinecone
from langchain.vectorstores import Pinecone
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import LocalFileStore
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from operator import itemgetter
from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
from langchain.schema import format_document
from langchain.prompts.prompt import PromptTemplate
from langchain.schema.output_parser import StrOutputParser

store = LocalFileStore("./cache/")

load_dotenv()

# PINECONE
index_name = 'berkshire-letters'
core_embeddings_model = OpenAIEmbeddings()
embedder = CacheBackedEmbeddings.from_bytes_store(
    core_embeddings_model, store, namespace=core_embeddings_model.model
)

pinecone.init(
    api_key=os.getenv("PINECONE_API_KEY"),
    environment=os.getenv("PINECONE_ENVIRONMENT")
)

text_field = "text"

index = pinecone.Index(index_name)


vectorstore = Pinecone(
    index,
    embedder.embed_query,
    text_field
)



# chainlit app development STARTS here



@cl.on_chat_start  # marks a function that will be executed at the start of a user session
async def start_chat():
    settings = {
        "model": "gpt-3.5-turbo-1106",
        "temperature": 0,
        "max_tokens": 1000,
        "top_p": 1,
        "frequency_penalty": 0,
        "presence_penalty": 0,
    }

    cl.user_session.set("settings", settings)

@cl.on_message  # marks a function that should be run each time the chatbot receives a message from a user
async def main(message: cl.Message):

    settings = cl.user_session.get("settings")

    llm = ChatOpenAI(
        model = settings["model"],
        temperature=settings["temperature"]
    )
   
    
    retriever = vectorstore.as_retriever()
    

    # Craft a prompt with context and question
    template = """
        You are Morgan Freeman. You answer questions based on the provided context in a way of speech that Morgan Freeman would answer. If you don't know how to answer based on the context provided below, just say you don't know the answer.
        Provided Context
        {context}
        User Question
        {question}
        At the end of your answer, add a quote from Morgan Freeman
        """ 
    prompt = ChatPromptTemplate.from_template(template)
    
    retrieval_augmented_qa_chain = (
    {"context": itemgetter("question") | retriever,
     "question": itemgetter("question")
    }
    | RunnablePassthrough.assign(
        context=itemgetter("context")
      )
    | {
         "response": prompt | llm,
         "context": itemgetter("context"),
      }
    )
    
    res = retrieval_augmented_qa_chain.invoke({"question" : message.content})
    direct_response = res['response'].content
    all_context = res['context']

    # Generate the refs list
    refs = []
    if all_context:
        for context_doc_object in all_context:
            ref_link = f"Link - {context_doc_object.metadata['source_document']}, at page {context_doc_object.metadata['page_number']}"
            refs.append(ref_link)

    text_elements = []
    if refs:
        for source_idx, link in enumerate(refs):
            source_name = f"source {source_idx}"
            text_elements.append(
                cl.Text(content=link, name=source_name)
            )
      
    await cl.Message(
        content=direct_response, elements=text_elements        
    ).send()