File size: 3,760 Bytes
e7127be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5dec041
 
e7127be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5dec041
 
e7127be
 
 
5dec041
 
e7127be
 
 
5dec041
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
import os, dotenv, anthropic, panel, platform
from langchain_community.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader

panel.extension()

# Set API key
dotenv.load_dotenv()
ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY')

@panel.cache
def load_vectorstore():
    if "macOS" in platform.platform():
        device="mps"
    else:
        device="cpu"

    # Create the HF embeddings
    model_name = "sentence-transformers/all-mpnet-base-v2"
    model_kwargs = {'device': device}
    encode_kwargs = {'normalize_embeddings': False}

    hf_embeddings = HuggingFaceEmbeddings(
                        model_name=model_name,
                        model_kwargs=model_kwargs,
                        encode_kwargs=encode_kwargs
                    )

    # If the vector embeddings of the documents have not been created
    if not os.path.isfile('chroma_db/chroma.sqlite3'):

        # Load the documents
        loader = DirectoryLoader('Docs/', glob="./*.pdf", loader_cls=PyPDFLoader)
        data = loader.load()

        # Split the docs into chunks
        splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000,
            chunk_overlap=50
        )
        docs = splitter.split_documents(data)

        # Embed the documents and store them in a Chroma DB
        vectorstore = Chroma.from_documents(documents=docs,embedding=hf_embeddings, persist_directory="./chroma_db")
    else:
        # load ChromaDB from disk
        vectorstore = Chroma(persist_directory="./chroma_db", embedding_function=hf_embeddings)

    return vectorstore

# Initialize the chat history
chat_history = []

async def get_response(contents, user, instance):

    # Load the vectorstore
    vectorstore = load_vectorstore()

    question = contents

    # Get the relevant information to form the context on which to query with the LLM
    docs = vectorstore.similarity_search(question)

    context = "\n"
    for doc in docs:
        context += "\n" + doc.page_content + "\n"

    # Update the global chat_history with the user's question
    global chat_history
    chat_history.append({"role": "user", "content": question})

    # Define prompt template
    prompt = f"""
    Here are the Task Context and History

    - Context: {context}
    - Chat History: {chat_history}
    - User Question: {question}
    """

    # Create the Anthropic client
    client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)

    response = ''
    # Generate the completion with the updated chat_history
    with client.messages.stream(
        max_tokens=1024,
        messages=[
            {"role": "user", "content": prompt}
        ],
        model="claude-3-haiku-20240307",
    ) as stream:
      for text in stream.text_stream:
          response += text
          yield response

    # Append the assistant's response to the chat_history
    chat_history.append({"role": "assistant", "content": response})

chat_interface = panel.chat.ChatInterface(
    callback=get_response, 
    callback_user="Sarathi",
    sizing_mode="stretch_width", 
    callback_exception='verbose',
    message_params=dict(
                default_avatars={"Sarathi": "S", "User": "U"},
                reaction_icons={"like": "thumb-up"},
            ),
)

chat_interface.send(
    {"user": "Sarathi", "value": '''Welcome to Sarathi, your personal assistant for Assam Tourism.'''},
    respond=False,
)

template = panel.template.BootstrapTemplate(title="Sarathi", favicon="favicon.png", header_background = "#000000", main=[panel.Tabs( ('Chat', chat_interface), dynamic=True )])

template.servable()