exyou commited on
Commit
8f1d29b
Β·
1 Parent(s): 4001149

add app.py

Browse files
Files changed (1) hide show
  1. app.py +148 -0
app.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess
2
+ import sys
3
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "langchain"])
4
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "sentence_transformers"])
5
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "faiss-gpu"])
6
+ subprocess.check_call([sys.executable, "-m", "pip", "install","accelerate"])
7
+ subprocess.check_call([sys.executable, "-m", "pip", "install","bitsandbytes"])
8
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "peft"])
9
+
10
+ import os
11
+ import glob
12
+
13
+ from langchain.document_loaders import UnstructuredMarkdownLoader
14
+ from langchain.text_splitter import CharacterTextSplitter
15
+ from langchain.vectorstores import FAISS
16
+ from langchain.embeddings import HuggingFaceEmbeddings
17
+ from langchain.schema import Document
18
+
19
+ from transformers import pipeline
20
+ from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
21
+
22
+ from peft import PeftModel, PeftConfig
23
+
24
+ import streamlit as st
25
+
26
+
27
+ def main():
28
+ # set page title
29
+ st.set_page_config(page_title="Project Nexodus Documentation Retreival", page_icon="πŸ“–", layout="wide")
30
+ st.header("πŸ“– Ask Project Nexodus Docs")
31
+ # set description
32
+ st.markdown("""
33
+ Generates answers to your questions about Project Nexodus by leveraging foundation models to perform search and retreival of Nexodus documentation.\n
34
+
35
+ Feeling stuck? Here are some examples of questions you can ask:
36
+ * How do I run the control plane for Nexodus?
37
+ * How do I monitor the Nexodus stack locally?
38
+ * How can I contribute to Project Nexodus?
39
+ """)
40
+ # set sidebar
41
+ with st.sidebar:
42
+ # create instructions for use
43
+ st.markdown("""
44
+ # How to use:\n
45
+ 1. Enter your HuggingFace API token below
46
+ 2. Select your answer generation strategy from the dropdown menu
47
+ 3. Ask a question about Linux networking
48
+ 4. Click on the `Submit` button or optionally, click on the `Feeling Lucky`
49
+ """)
50
+ # create input box for HF API token
51
+ API_KEY = st.text_input('Hugging Face API Token πŸ€—', type='password',
52
+ placeholder='Paste your HuggingFace token here (sk-...)',
53
+ help="You can get your API token from https://huggingface.co/docs/hub/security-tokens.")
54
+
55
+ st.markdown("""
56
+ # About
57
+ Talk to Project Nexodus is a web application that answers your questions about Nexodus,
58
+ with the goal of exploring the capabilities and limitations of Large Language Models (LLMs) for question and
59
+ answering tasks. It demonstrates the following strategies for question answering: extractive, abstractive, and
60
+ generative.
61
+
62
+ This project is still in beta and mainly used for research purposes. It is highly unadvised for users to rely on it for Project Nexodus troubleshooting.
63
+ Please refer to the [official Nexodus documentation](https://github.com/nexodus-io/nexodus) for help. Proceed at your own risk πŸ’€
64
+ """)
65
+ if API_KEY:
66
+ strategy = st.selectbox('Q&A Strategy', ['Extractive', 'Abstractive', 'Finetuned with LoRA'])
67
+ question = st.text_input("Enter your question here:")
68
+ col1, col2 = st.columns([1,1])
69
+ with col1:
70
+ generate_answer = st.button("Generate Answer")
71
+ with col2:
72
+ feeling_lucky = st.button("Feeling Lucky")
73
+
74
+ if question != "":
75
+ if strategy and generate_answer:
76
+ answer = get_answer(question, strategy)
77
+ st.write(answer)
78
+ elif feeling_lucky:
79
+ answer = get_answer(question, 'Generative')
80
+ st.write(answer)
81
+
82
+ def load_db():
83
+ # initalize embedder
84
+ print('Loading FAISS index...')
85
+ embeddings = HuggingFaceEmbeddings()
86
+ # load FAISS vector database storing Nexodus documentation
87
+ db = FAISS.load_local("/opt/app-root/src/nexodus-docs-qa/nexodus_index.faiss", embeddings)
88
+ return db
89
+
90
+ def load_model():
91
+ llm = "deepset/roberta-base-squad2"
92
+ return llm
93
+
94
+ def load_model_tokenizer():
95
+ model_name = "google/flan-t5-base"
96
+ print(f"Loading finetuned {model_name} with LoRA...")
97
+ model = AutoModelForSeq2SeqLM.from_pretrained(model_name,load_in_8bit=True, device_map='auto')
98
+ nexodus_flan_T5 = PeftModel.from_pretrained(model, '/opt/app-root/src/nexodus-docs-qa/models/nexodus-flan-T5')
99
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
100
+ print("Model sucessfully loaded")
101
+ return nexodus_flan_T5, tokenizer
102
+
103
+ def provide_context(context):
104
+ context = [f"<P> {m.page_content}" for m in context]
105
+ context = " ".join(context)
106
+ return context
107
+
108
+ def get_answer(question, strategy):
109
+ if strategy == 'Generative':
110
+ question = 'question: ' + question
111
+ text2text_generator = pipeline("text2text-generation", model="declare-lab/flan-alpaca-large")
112
+ output = text2text_generator(question, min_length=5, max_length=50)
113
+ answer = output[0]['generated_text']
114
+
115
+ else:
116
+ db = load_db()
117
+ if strategy == 'Finetuned with LoRA':
118
+ model, tokenizer = load_model_tokenizer()
119
+ # get the top 3 most similar sentences in the docs to the inputted question
120
+ top_3 = db.similarity_search(question, k=3)
121
+ # set as context for the question
122
+ context = provide_context(top_3)
123
+ question_context = f"Question: ## {question} ##\n Context: ## {context} ##"
124
+ input_ids = tokenizer(question_context, return_tensors="pt", truncation=True).input_ids.cuda()
125
+ outputs = model.generate(input_ids=input_ids, max_new_tokens=1000, do_sample=True, top_p=1)
126
+ answer = tokenizer.batch_decode(outputs.detach().cpu().numpy(), skip_special_tokens=True)[0]
127
+ return answer
128
+
129
+ else:
130
+ llm = load_model()
131
+ if strategy == 'Extractive':
132
+ output = db.similarity_search(question, k=1)
133
+ answer = output[0].page_content
134
+ return answer
135
+
136
+ elif strategy == 'Abstractive':
137
+ top_3 = db.similarity_search(question, k=3)
138
+ context = provide_context(top_3)
139
+ text2text_generator = pipeline(task='question-answering', tokenizer=llm, model=llm)
140
+ output = text2text_generator(question=question, context=context, temperature=1.5, min_length=5, max_length=50)
141
+ answer = output["answer"]
142
+ return answer
143
+
144
+ return answer
145
+
146
+ if __name__ == "__main__":
147
+ main()
148
+