gkbalu commited on
Commit
db9f86a
·
1 Parent(s): 68e39f3

Midterm project

Browse files
.chainlit/config.toml ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ # Whether to enable telemetry (default: true). No personal data is collected.
3
+ enable_telemetry = true
4
+
5
+ # List of environment variables to be provided by each user to use the app.
6
+ user_env = []
7
+
8
+ # Duration (in seconds) during which the session is saved when the connection is lost
9
+ session_timeout = 3600
10
+
11
+ # Enable third parties caching (e.g LangChain cache)
12
+ cache = false
13
+
14
+ # Follow symlink for asset mount (see https://github.com/Chainlit/chainlit/issues/317)
15
+ # follow_symlink = false
16
+
17
+ [features]
18
+ # Show the prompt playground
19
+ prompt_playground = true
20
+
21
+ # Process and display HTML in messages. This can be a security risk (see https://stackoverflow.com/questions/19603097/why-is-it-dangerous-to-render-user-generated-html-or-javascript)
22
+ unsafe_allow_html = false
23
+
24
+ # Process and display mathematical expressions. This can clash with "$" characters in messages.
25
+ latex = false
26
+
27
+ # Authorize users to upload files with messages
28
+ multi_modal = true
29
+
30
+ # Allows user to use speech to text
31
+ [features.speech_to_text]
32
+ enabled = false
33
+ # See all languages here https://github.com/JamesBrill/react-speech-recognition/blob/HEAD/docs/API.md#language-string
34
+ # language = "en-US"
35
+
36
+ [UI]
37
+ # Name of the app and chatbot.
38
+ name = "Chatbot"
39
+
40
+ # Show the readme while the conversation is empty.
41
+ show_readme_as_default = true
42
+
43
+ # Description of the app and chatbot. This is used for HTML tags.
44
+ # description = ""
45
+
46
+ # Large size content are by default collapsed for a cleaner ui
47
+ default_collapse_content = true
48
+
49
+ # The default value for the expand messages settings.
50
+ default_expand_messages = false
51
+
52
+ # Hide the chain of thought details from the user in the UI.
53
+ hide_cot = false
54
+
55
+ # Link to your github repo. This will add a github button in the UI's header.
56
+ # github = ""
57
+
58
+ # Specify a CSS file that can be used to customize the user interface.
59
+ # The CSS file can be served from the public directory or via an external link.
60
+ # custom_css = "/public/test.css"
61
+
62
+ # Override default MUI light theme. (Check theme.ts)
63
+ [UI.theme.light]
64
+ #background = "#FAFAFA"
65
+ #paper = "#FFFFFF"
66
+
67
+ [UI.theme.light.primary]
68
+ #main = "#F80061"
69
+ #dark = "#980039"
70
+ #light = "#FFE7EB"
71
+
72
+ # Override default MUI dark theme. (Check theme.ts)
73
+ [UI.theme.dark]
74
+ #background = "#FAFAFA"
75
+ #paper = "#FFFFFF"
76
+
77
+ [UI.theme.dark.primary]
78
+ #main = "#F80061"
79
+ #dark = "#980039"
80
+ #light = "#FFE7EB"
81
+
82
+
83
+ [meta]
84
+ generated_by = "0.7.700"
Dockerfile ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11
2
+ RUN useradd -m -u 1000 user
3
+ ENV HOME=/home/user \
4
+ PATH=/home/user/.local/bin:$PATH
5
+ WORKDIR $HOME/app
6
+ COPY . .
7
+ RUN chown -R user:user .
8
+ RUN pip install -r requirements.txt
9
+ USER user
10
+ CMD ["chainlit", "run", "app.py", "--port", "7860"]
README.md CHANGED
@@ -1,10 +1,11 @@
1
  ---
2
- title: Midterm Airbnb
3
- emoji: 🦀
4
- colorFrom: yellow
5
- colorTo: indigo
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: AirBnB Auditor
3
+ emoji: 🧐
4
+ colorFrom: red
5
+ colorTo: gray
6
  sdk: docker
7
  pinned: false
8
+ app_port: 7860
9
  ---
10
+ Midterm evaluation questions
11
+ ![airbnb-auditor](https://github.com/sivabalan/AIE3/assets/1521706/76d7cf32-fd80-4353-88d8-238157511c8a)
app.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import chainlit as cl
3
+ from dotenv import load_dotenv
4
+ from operator import itemgetter
5
+ from langchain_huggingface import HuggingFaceEndpoint
6
+ from langchain_community.document_loaders import PyMuPDFLoader
7
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
8
+ from langchain_community.vectorstores import Qdrant
9
+ from langchain_openai.embeddings import OpenAIEmbeddings
10
+ from langchain_core.prompts import PromptTemplate
11
+ from langchain.schema.runnable.config import RunnableConfig
12
+
13
+ # GLOBAL SCOPE - ENTIRE APPLICATION HAS ACCESS TO VALUES SET IN THIS SCOPE #
14
+ # ---- ENV VARIABLES ---- #
15
+ """
16
+ This function will load our environment file (.env) if it is present.
17
+
18
+ NOTE: Make sure that .env is in your .gitignore file - it is by default, but please ensure it remains there.
19
+ """
20
+ load_dotenv()
21
+
22
+ """
23
+ We will load our environment variables here.
24
+ """
25
+ HF_LLM_ENDPOINT = os.environ["HF_LLM_ENDPOINT"]
26
+ HF_TOKEN = os.environ["HF_TOKEN"]
27
+ VECTOR_STORE_PATH = "./data/vectorstore"
28
+
29
+ # ---- GLOBAL DECLARATIONS ---- #
30
+
31
+ # -- RETRIEVAL -- #
32
+ """
33
+ 1. Load Documents from PDF File
34
+ 2. Split Documents into Chunks
35
+ 3. Load HuggingFace Embeddings (remember to use the URL we set above)
36
+ 4. Index Files if they do not exist, otherwise load the vectorstore
37
+ """
38
+ document_loader = PyMuPDFLoader("./data/Airbnb_Q1_Filings.pdf")
39
+ documents = document_loader.load()
40
+
41
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=30)
42
+ split_documents = text_splitter.split_documents(documents)
43
+
44
+ # Note: Uses OPENAI_API_KEY env variable to make api calls
45
+ openai_embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
46
+
47
+ if os.path.exists(VECTOR_STORE_PATH):
48
+ vectorstore = Qdrant.from_existing_collection(
49
+ embeddings=openai_embeddings,
50
+ collection_name="airbnb_financials",
51
+ path=VECTOR_STORE_PATH,
52
+ batch_size=32,
53
+ )
54
+ print("Loaded Vectorstore")
55
+ else:
56
+ print("Indexing Files")
57
+ os.makedirs(VECTOR_STORE_PATH, exist_ok=True)
58
+ vectorstore = Qdrant.from_documents(
59
+ documents=split_documents,
60
+ embedding=openai_embeddings,
61
+ path=VECTOR_STORE_PATH,
62
+ collection_name="airbnb_financials",
63
+ batch_size=32,
64
+ )
65
+
66
+ retriever = vectorstore.as_retriever()
67
+
68
+ # -- AUGMENTED -- #
69
+ """
70
+ 1. Define a String Template
71
+ 2. Create a Prompt Template from the String Template
72
+ """
73
+ RAG_PROMPT_TEMPLATE = """\
74
+ <|start_header_id|>system<|end_header_id|>
75
+ You are a helpful assistant. You answer user questions based on provided context. If you can't answer the question with the provided context, say you don't know.<|eot_id|>
76
+
77
+ <|start_header_id|>user<|end_header_id|>
78
+ User Query:
79
+ {query}
80
+
81
+ Context:
82
+ {context}<|eot_id|>
83
+
84
+ <|start_header_id|>assistant<|end_header_id|>
85
+ """
86
+
87
+ rag_prompt = PromptTemplate.from_template(RAG_PROMPT_TEMPLATE)
88
+
89
+ # -- GENERATION -- #
90
+ """
91
+ 1. Create a HuggingFaceEndpoint for the LLM
92
+ """
93
+ hf_llm = HuggingFaceEndpoint(
94
+ endpoint_url=HF_LLM_ENDPOINT,
95
+ max_new_tokens=512,
96
+ top_k=10,
97
+ top_p=0.95,
98
+ temperature=0.3,
99
+ repetition_penalty=1.15,
100
+ huggingfacehub_api_token=HF_TOKEN,
101
+ )
102
+
103
+ @cl.author_rename
104
+ def rename(original_author: str):
105
+ """
106
+ This function can be used to rename the 'author' of a message.
107
+
108
+ In this case, we're overriding the 'Assistant' author to be 'Paul Graham Essay Bot'.
109
+ """
110
+ rename_dict = {
111
+ "Assistant" : "AirBnB Auditor"
112
+ }
113
+ return rename_dict.get(original_author, original_author)
114
+
115
+ @cl.on_chat_start
116
+ async def start_chat():
117
+ """
118
+ This function will be called at the start of every user session.
119
+
120
+ We will build our LCEL RAG chain here, and store it in the user session.
121
+
122
+ The user session is a dictionary that is unique to each user session, and is stored in the memory of the server.
123
+ """
124
+
125
+ lcel_rag_chain = (
126
+ {"context": itemgetter("query") | retriever, "query": itemgetter("query")}
127
+ | rag_prompt | hf_llm
128
+ )
129
+
130
+ cl.user_session.set("lcel_rag_chain", lcel_rag_chain)
131
+
132
+ @cl.on_message
133
+ async def main(message: cl.Message):
134
+ """
135
+ This function will be called every time a message is recieved from a session.
136
+
137
+ We will use the LCEL RAG chain to generate a response to the user query.
138
+
139
+ The LCEL RAG chain is stored in the user session, and is unique to each user session - this is why we can access it here.
140
+ """
141
+ lcel_rag_chain = cl.user_session.get("lcel_rag_chain")
142
+
143
+ msg = cl.Message(content="")
144
+
145
+ for chunk in await cl.make_async(lcel_rag_chain.stream)(
146
+ {"query": message.content},
147
+ config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
148
+ ):
149
+ # Note: Skip printing eot_id token at the end of response. A more elegant solution would be to fix the model's generator config.
150
+ if chunk != "<|eot_id|>":
151
+ await msg.stream_token(chunk)
152
+
153
+ await msg.send()
chainlit.md ADDED
@@ -0,0 +1 @@
 
 
1
+ # AirBnB Auditor
data/Airbnb_Q1_Filings.pdf ADDED
Binary file (596 kB). View file
 
data/vectorstore/.lock ADDED
@@ -0,0 +1 @@
 
 
1
+ tmp lock file
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ chainlit==0.7.700
2
+ langchain==0.2.5
3
+ langchain_community==0.2.5
4
+ langchain_core==0.2.9
5
+ langchain_huggingface==0.0.3
6
+ langchain_text_splitters==0.2.1
7
+ langchain_openai==0.1.9
8
+ python-dotenv==1.0.1
9
+ pymupdf==1.24.5
10
+ qdrant-client==1.9.2