Dobin Yim commited on
Commit
6acb7ee
1 Parent(s): 77aeb3d

hugging face

Browse files
Files changed (8) hide show
  1. .gitattributes +0 -35
  2. .gitignore +6 -0
  3. Dockerfile +11 -0
  4. README.md +1 -2
  5. app.py +169 -0
  6. chainlit.md +1 -0
  7. data/paul_graham_essays.txt +0 -0
  8. requirements.txt +8 -0
.gitattributes DELETED
@@ -1,35 +0,0 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ .env
2
+ __pycache__/
3
+ .chainlit
4
+ *.faiss
5
+ *.pkl
6
+ .files
Dockerfile ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+ RUN useradd -m -u 1000 user
3
+ USER user
4
+ ENV HOME=/home/user \
5
+ PATH=/home/user/.local/bin:$PATH
6
+ WORKDIR $HOME/app
7
+ COPY --chown=user . $HOME/app
8
+ COPY ./requirements.txt ~/app/requirements.txt
9
+ RUN pip install -r requirements.txt
10
+ COPY . .
11
+ CMD ["chainlit", "run", "app.py", "--port", "7860"]
README.md CHANGED
@@ -6,5 +6,4 @@ 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
 
6
  sdk: docker
7
  pinned: false
8
  ---
9
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
app.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 TextLoader
7
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
8
+ from langchain_community.vectorstores import FAISS
9
+ from langchain_huggingface import HuggingFaceEndpointEmbeddings
10
+ from langchain_core.prompts import PromptTemplate
11
+ from langchain.schema.output_parser import StrOutputParser
12
+ from langchain.schema.runnable import RunnablePassthrough
13
+ from langchain.schema.runnable.config import RunnableConfig
14
+
15
+ # GLOBAL SCOPE - ENTIRE APPLICATION HAS ACCESS TO VALUES SET IN THIS SCOPE #
16
+ # ---- ENV VARIABLES ---- #
17
+ """
18
+ This function will load our environment file (.env) if it is present.
19
+
20
+ NOTE: Make sure that .env is in your .gitignore file - it is by default, but please ensure it remains there.
21
+ """
22
+ load_dotenv()
23
+
24
+ """
25
+ We will load our environment variables here.
26
+ """
27
+ HF_LLM_ENDPOINT = os.environ["HF_LLM_ENDPOINT"]
28
+ HF_EMBED_ENDPOINT = os.environ["HF_EMBED_ENDPOINT"]
29
+ HF_TOKEN = os.environ["HF_TOKEN"]
30
+
31
+ # ---- GLOBAL DECLARATIONS ---- #
32
+
33
+ # -- RETRIEVAL -- #
34
+ """
35
+ 1. Load Documents from Text File
36
+ 2. Split Documents into Chunks
37
+ 3. Load HuggingFace Embeddings (remember to use the URL we set above)
38
+ 4. Index Files if they do not exist, otherwise load the vectorstore
39
+ """
40
+ ### 1. CREATE TEXT LOADER AND LOAD DOCUMENTS
41
+ ### NOTE: PAY ATTENTION TO THE PATH THEY ARE IN.
42
+ text_loader = TextLoader("./data/paul_graham_essays.txt")
43
+ documents = text_loader.load()
44
+
45
+ ### 2. CREATE TEXT SPLITTER AND SPLIT DOCUMENTS
46
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=30)
47
+ split_documents = text_splitter.split_documents(documents)
48
+
49
+ ### 3. LOAD HUGGINGFACE EMBEDDINGS
50
+ hf_embeddings = HuggingFaceEndpointEmbeddings(
51
+ model=HF_EMBED_ENDPOINT,
52
+ task="feature-extraction",
53
+ huggingfacehub_api_token=HF_TOKEN,
54
+ )
55
+ vectorstore_path = "./data/vectorstore"
56
+ index_file = os.path.join(vectorstore_path, "index.faiss")
57
+
58
+ if os.path.exists(index_file):
59
+ vectorstore = FAISS.load_local(
60
+ vectorstore_path,
61
+ hf_embeddings,
62
+ allow_dangerous_deserialization=True
63
+ )
64
+ hf_retriever = vectorstore.as_retriever()
65
+ print("Loaded Vectorstore")
66
+ else:
67
+ print("Indexing Files")
68
+ os.makedirs(vectorstore_path, exist_ok=True)
69
+ ### 4. INDEX FILES
70
+ vectorstore = None
71
+ for i in range(0, len(split_documents), 32):
72
+ batch = split_documents[i:i+32]
73
+ if vectorstore is None:
74
+ vectorstore = FAISS.from_documents(batch, hf_embeddings)
75
+ else:
76
+ vectorstore.add_documents(batch)
77
+ vectorstore.save_local(vectorstore_path)
78
+ print("Vectorstore created and saved")
79
+
80
+ hf_retriever = vectorstore.as_retriever()
81
+
82
+ # -- AUGMENTED -- #
83
+ """
84
+ 1. Define a String Template
85
+ 2. Create a Prompt Template from the String Template
86
+ """
87
+ ### 1. DEFINE STRING TEMPLATE
88
+ RAG_PROMPT_TEMPLATE = """\
89
+ <|start_header_id|>system<|end_header_id|>
90
+ 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|>
91
+
92
+ <|start_header_id|>user<|end_header_id|>
93
+ User Query:
94
+ {query}
95
+
96
+ Context:
97
+ {context}<|eot_id|>
98
+
99
+ <|start_header_id|>assistant<|end_header_id|>
100
+ """
101
+
102
+ ### 2. CREATE PROMPT TEMPLATE
103
+ rag_prompt = PromptTemplate.from_template(RAG_PROMPT_TEMPLATE)
104
+
105
+ # -- GENERATION -- #
106
+ """
107
+ 1. Create a HuggingFaceEndpoint for the LLM
108
+ """
109
+ ### 1. CREATE HUGGINGFACE ENDPOINT FOR LLM
110
+ hf_llm = HuggingFaceEndpoint(
111
+ endpoint_url=HF_LLM_ENDPOINT,
112
+ max_new_tokens=512,
113
+ top_k=10,
114
+ top_p=0.95,
115
+ temperature=0.1,
116
+ repetition_penalty=1.0,
117
+ huggingfacehub_api_token=HF_TOKEN,
118
+ )
119
+
120
+ @cl.author_rename
121
+ def rename(original_author: str):
122
+ """
123
+ This function can be used to rename the 'author' of a message.
124
+
125
+ In this case, we're overriding the 'Assistant' author to be 'Paul Graham Essay Bot'.
126
+ """
127
+ rename_dict = {
128
+ "Assistant" : "Paul Graham Essay Bot"
129
+ }
130
+ return rename_dict.get(original_author, original_author)
131
+
132
+ @cl.on_chat_start
133
+ async def start_chat():
134
+ """
135
+ This function will be called at the start of every user session.
136
+
137
+ We will build our LCEL RAG chain here, and store it in the user session.
138
+
139
+ The user session is a dictionary that is unique to each user session, and is stored in the memory of the server.
140
+ """
141
+
142
+ ### BUILD LCEL RAG CHAIN THAT ONLY RETURNS TEXT
143
+ lcel_rag_chain = (
144
+ {"context": itemgetter("query") | hf_retriever, "query": itemgetter("query")}
145
+ | rag_prompt | hf_llm
146
+ )
147
+
148
+ cl.user_session.set("lcel_rag_chain", lcel_rag_chain)
149
+
150
+ @cl.on_message
151
+ async def main(message: cl.Message):
152
+ """
153
+ This function will be called every time a message is recieved from a session.
154
+
155
+ We will use the LCEL RAG chain to generate a response to the user query.
156
+
157
+ 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.
158
+ """
159
+ lcel_rag_chain = cl.user_session.get("lcel_rag_chain")
160
+
161
+ msg = cl.Message(content="")
162
+
163
+ async for chunk in lcel_rag_chain.astream(
164
+ {"query": message.content},
165
+ config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
166
+ ):
167
+ await msg.stream_token(chunk)
168
+
169
+ await msg.send()
chainlit.md ADDED
@@ -0,0 +1 @@
 
 
1
+ # End to End RAG using Hugging Face, FAISS as vector store, and LangCzhain as orchestrator
data/paul_graham_essays.txt ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ chainlit==1.1.302
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
+ python-dotenv==1.0.1
8
+ faiss-cpu