Hung Bui commited on
Commit
4915495
·
0 Parent(s):

Duplicate from hbui/RegBotBeta2.3

Browse files
.gitattributes ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ *.tflite filter=lfs diff=lfs merge=lfs -text
29
+ *.tgz filter=lfs diff=lfs merge=lfs -text
30
+ *.wasm filter=lfs diff=lfs merge=lfs -text
31
+ *.xz filter=lfs diff=lfs merge=lfs -text
32
+ *.zip filter=lfs diff=lfs merge=lfs -text
33
+ *.zst filter=lfs diff=lfs merge=lfs -text
34
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ .*pdf filter=lfs diff=lfs merge=lfs -text
36
+ assets/pdf/calregs.pdf filter=lfs diff=lfs merge=lfs -text
37
+ assets/pdf/CADWReg.pdf filter=lfs diff=lfs merge=lfs -text
38
+ vectorStores/bloom-560m/vector_store.json filter=lfs diff=lfs merge=lfs -text
39
+ vectorStores/langOpen/index.faiss filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ venv
2
+ data/__pycache__
3
+ models/__pycache__
4
+ .env
5
+ __pycache__
6
+ vectorStores
7
+ .vscode
Dockerfile ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /docker
4
+
5
+ ADD . /docker
6
+
7
+ COPY requirements.txt requirements.txt
8
+ RUN pip install --upgrade pip
9
+ RUN pip install --no-cache-dir -r requirements.txt
10
+
11
+ COPY . .
12
+
13
+ # Set up a new user named "user" with user ID 1000
14
+ RUN useradd -m -u 1000 user
15
+
16
+ # Switch to the "user" user
17
+ USER user
18
+
19
+ # Set home to the user's home directory
20
+ ENV HOME=/home/user \
21
+ PATH=/home/user/.local/bin:$PATH
22
+
23
+ # Set the working directory to the user's home directory
24
+ WORKDIR $HOME/app
25
+
26
+ # Set the working directory to the user's home directory
27
+ COPY --chown=user . $HOME/app
28
+
29
+ EXPOSE 8501
30
+
31
+ HEALTHCHECK CMD --fail http://localhost:8501/_stcore/health
32
+
33
+ ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
34
+ # CMD [ "streamlit" , "run", "app.py"]
35
+ # CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: RegBotBeta
3
+ emoji: 😻
4
+ colorFrom: green
5
+ colorTo: red
6
+ sdk: docker
7
+ app_file: app.py
8
+ app_port: 8501
9
+ pinned: false
10
+ duplicated_from: hbui/RegBotBeta2.3
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # https://docs.streamlit.io/knowledge-base/tutorials/build-conversational-apps
2
+
3
+ import os
4
+
5
+ import openai
6
+ import requests
7
+ import streamlit as st
8
+
9
+ from utils.util import *
10
+
11
+ st.set_page_config(page_title="RegBotBeta", page_icon="📜🤖")
12
+
13
+ st.title("Welcome to RegBotBeta2.0")
14
+ st.header("Powered by `LlamaIndex🦙`, `Langchain🦜🔗 ` and `OpenAI API`")
15
+
16
+ #api_key = st.text_input("Enter your OpenAI API key here:", type="password")
17
+ api_key = os.environ['OPENAI_API_KEY']
18
+
19
+ if api_key:
20
+ resp = validate(api_key)
21
+ if "error" in resp.json():
22
+ st.info("Invalid Token! Try again.")
23
+ else:
24
+ #st.info("Success")
25
+ os.environ["OPENAI_API_KEY"] = api_key
26
+ openai.api_key = api_key
27
+
28
+ if "openai_api_key" not in st.session_state:
29
+ st.session_state.openai_api_key = ""
30
+
31
+ st.session_state.openai_api_key = api_key
assets/pdf/CADWReg.pdf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9a80bdec9f2f6c15ca5d9181723b711bb7428fa48babaf87bab3f3b690055f54
3
+ size 3724564
assets/prompts/__init__.py ADDED
File without changes
assets/prompts/custom_prompts.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ text_qa_template_str = (
2
+ "Assistant Message: I'm here to assist you with information about California water regulations."
3
+ "Feel free to ask questions based on the context below, and I'll do my best to provide accurate answers.\n\n"
4
+ "Context: {context_str}\n\n"
5
+ "Your Question: {query_str}\n\n"
6
+ "Answer: \n\n"
7
+ "If the question is pertinent, I'll provide you with the chapter, article, and section of the information"
8
+ "from the PDF document 'Title 17 and 22, California Code of Regulations'. Additionally, I'll strive to include"
9
+ "the corresponding page number for your reference.\n\n"
10
+ "Please note that my knowledge is up to date as of September 2021."
11
+ )
12
+
13
+ refine_template_str = (
14
+ "The original question is as follows: {query_str}\n"
15
+ "We have provided an existing answer: {existing_answer}\n"
16
+ "We have the opportunity to refine the existing answer "
17
+ "(only if needed) with some more context below.\n"
18
+ "------------\n"
19
+ "{context_msg}\n"
20
+ "------------\n"
21
+ "Using both the new context and your own knowledege, update or repeat the existing answer.\n"
22
+ )
assets/regItems.json ADDED
The diff for this file is too large to render. See raw diff
 
assets/updated_calregs.txt ADDED
The diff for this file is too large to render. See raw diff
 
models/langOpen.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import openai
4
+ from dotenv import load_dotenv
5
+ from langchain.chains import LLMChain
6
+ from langchain.chat_models import ChatOpenAI
7
+ from langchain.document_loaders import PyPDFLoader
8
+ from langchain.embeddings.openai import OpenAIEmbeddings
9
+ from langchain.prompts import PromptTemplate
10
+ from langchain.vectorstores import FAISS
11
+
12
+ loader = PyPDFLoader("./assets/pdf/CADWReg.pdf")
13
+ pages = loader.load_and_split()
14
+
15
+ load_dotenv()
16
+
17
+ prompt_template = """Answer the question using the given context to the best of your ability.
18
+ If you don't know, answer I don't know.
19
+ Context: {context}
20
+ Topic: {topic}"""
21
+
22
+ PROMPT = PromptTemplate(template=prompt_template, input_variables=["context", "topic"])
23
+
24
+
25
+ class LangOpen:
26
+ def __init__(self, model_name: str) -> None:
27
+ self.index = self.initialize_index("langOpen")
28
+ self.llm = ChatOpenAI(temperature=0.3, model=model_name)
29
+ self.chain = LLMChain(llm=self.llm, prompt=PROMPT)
30
+
31
+ def initialize_index(self, index_name):
32
+ path = f"./vectorStores/{index_name}"
33
+ embeddings = OpenAIEmbeddings()
34
+
35
+ if os.path.exists(path=path):
36
+ return FAISS.load_local(folder_path=path, embeddings=embeddings)
37
+ else:
38
+ faiss = FAISS.from_documents(pages, embeddings)
39
+ faiss.save_local(path)
40
+ return faiss
41
+
42
+ def get_response(self, query_str):
43
+ print("query_str: ", query_str)
44
+ print("model_name: ", self.llm.model_name)
45
+ docs = self.index.similarity_search(query_str, k=4)
46
+ inputs = [{"context": doc.page_content, "topic": query_str} for doc in docs]
47
+ result = self.chain.apply(inputs)[0]["text"]
48
+ return result
models/llamaCustom.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ from json import dumps, loads
4
+ from typing import Any, List, Mapping, Optional
5
+
6
+ import numpy as np
7
+ import openai
8
+ import pandas as pd
9
+ import streamlit as st
10
+ from dotenv import load_dotenv
11
+ from huggingface_hub import HfFileSystem
12
+ from langchain.llms.base import LLM
13
+ from llama_index import (
14
+ Document,
15
+ GPTVectorStoreIndex,
16
+ LLMPredictor,
17
+ PromptHelper,
18
+ ServiceContext,
19
+ SimpleDirectoryReader,
20
+ StorageContext,
21
+ load_index_from_storage,
22
+ )
23
+ from llama_index.llms import CompletionResponse, CustomLLM, LLMMetadata
24
+ from llama_index.prompts import Prompt
25
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
26
+
27
+ from assets.prompts import custom_prompts
28
+
29
+ load_dotenv()
30
+ # openai.api_key = os.getenv("OPENAI_API_KEY")
31
+ fs = HfFileSystem()
32
+
33
+ # define prompt helper
34
+ # set maximum input size
35
+ CONTEXT_WINDOW = 2048
36
+ # set number of output tokens
37
+ NUM_OUTPUT = 525
38
+ # set maximum chunk overlap
39
+ CHUNK_OVERLAP_RATION = 0.2
40
+
41
+ text_qa_template = Prompt(custom_prompts.text_qa_template_str)
42
+
43
+ refine_template = Prompt(custom_prompts.refine_template_str)
44
+
45
+
46
+ @st.cache_resource
47
+ def load_model(model_name: str):
48
+ # llm_model_name = "bigscience/bloom-560m"
49
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
50
+ model = AutoModelForCausalLM.from_pretrained(model_name, config="T5Config")
51
+
52
+ pipe = pipeline(
53
+ task="text-generation",
54
+ model=model,
55
+ tokenizer=tokenizer,
56
+ # device=0, # GPU device number
57
+ # max_length=512,
58
+ do_sample=True,
59
+ top_p=0.95,
60
+ top_k=50,
61
+ temperature=0.7,
62
+ )
63
+
64
+ return pipe
65
+
66
+
67
+ class OurLLM(CustomLLM):
68
+ def __init__(self, model_name: str, model_pipeline):
69
+ self.model_name = model_name
70
+ self.pipeline = model_pipeline
71
+
72
+ @property
73
+ def metadata(self) -> LLMMetadata:
74
+ """Get LLM metadata."""
75
+ return LLMMetadata(
76
+ context_window=CONTEXT_WINDOW,
77
+ num_output=NUM_OUTPUT,
78
+ model_name=self.model_name,
79
+ )
80
+
81
+ def complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:
82
+ prompt_length = len(prompt)
83
+ response = self.pipeline(prompt, max_new_tokens=NUM_OUTPUT)[0]["generated_text"]
84
+
85
+ # only return newly generated tokens
86
+ text = response[prompt_length:]
87
+ return CompletionResponse(text=text)
88
+
89
+ def stream_complete(self, prompt: str, **kwargs: Any) -> CompletionResponse:
90
+ raise NotImplementedError()
91
+
92
+
93
+ class LlamaCustom:
94
+ def __init__(self, model_name: str) -> None:
95
+ self.vector_index = self.initialize_index(model_name=model_name)
96
+
97
+ def initialize_index(self, model_name: str):
98
+ index_name = model_name.split("/")[-1]
99
+
100
+ file_path = f"./vectorStores/{index_name}"
101
+
102
+ if os.path.exists(path=file_path):
103
+ # rebuild storage context
104
+ storage_context = StorageContext.from_defaults(persist_dir=file_path)
105
+
106
+ # local load index access
107
+ index = load_index_from_storage(storage_context)
108
+
109
+ # huggingface repo load access
110
+ # with fs.open(file_path, "r") as file:
111
+ # index = pickle.loads(file.readlines())
112
+ return index
113
+ else:
114
+ prompt_helper = PromptHelper(
115
+ context_window=CONTEXT_WINDOW,
116
+ num_output=NUM_OUTPUT,
117
+ chunk_overlap_ratio=CHUNK_OVERLAP_RATION,
118
+ )
119
+
120
+ # define llm
121
+ pipe = load_model(model_name=model_name)
122
+ llm = OurLLM(model_name=model_name, model_pipeline=pipe)
123
+
124
+ llm_predictor = LLMPredictor(llm=llm)
125
+ service_context = ServiceContext.from_defaults(
126
+ llm_predictor=llm_predictor, prompt_helper=prompt_helper
127
+ )
128
+
129
+ # documents = prepare_data(r"./assets/regItems.json")
130
+ documents = SimpleDirectoryReader(input_dir="./assets/pdf").load_data()
131
+
132
+ index = GPTVectorStoreIndex.from_documents(
133
+ documents, service_context=service_context
134
+ )
135
+
136
+ # local write access
137
+ index.storage_context.persist(file_path)
138
+
139
+ # huggingface repo write access
140
+ # with fs.open(file_path, "w") as file:
141
+ # file.write(pickle.dumps(index))
142
+ return index
143
+
144
+ def get_response(self, query_str):
145
+ print("query_str: ", query_str)
146
+ # query_engine = self.vector_index.as_query_engine()
147
+ query_engine = self.vector_index.as_query_engine(
148
+ text_qa_template=text_qa_template, refine_template=refine_template
149
+ )
150
+ response = query_engine.query(query_str)
151
+ print("metadata: ", response.metadata)
152
+ return str(response)
pages/langchain_demo.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import openai
4
+ import streamlit as st
5
+
6
+ from models.langOpen import LangOpen
7
+ from utils.chatbox import chatbox
8
+
9
+ st.set_page_config(page_title="Langchain", page_icon="")
10
+
11
+ st.subheader("Langchain with OpenAI Demo")
12
+
13
+ if "messages" not in st.session_state:
14
+ st.session_state.messages = []
15
+
16
+ if "openai_api_key" not in st.session_state:
17
+ st.info("Enter your openai key to access the chatbot.")
18
+ else:
19
+ option = st.selectbox(
20
+ label="Select your model:", options=("gpt-3.5-turbo", "gpt-4")
21
+ )
22
+
23
+ with st.spinner(f"Initializing {option} ..."):
24
+ langOpen = LangOpen(model_name=option)
25
+
26
+ chatbox("lang_open", langOpen)
pages/llama_custom_demo.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import openai
4
+ import streamlit as st
5
+
6
+ from models.llamaCustom import LlamaCustom
7
+ from utils.chatbox import chatbox
8
+
9
+ st.set_page_config(page_title="Llama", page_icon="🦙")
10
+
11
+ st.subheader("Llama Index with Custom LLM Demo")
12
+
13
+ if "messages" not in st.session_state:
14
+ st.session_state.messages = []
15
+
16
+ if "openai_api_key" not in st.session_state:
17
+ st.info("Enter your openai key to access the chatbot.")
18
+ else:
19
+ option = st.selectbox(
20
+ label="Select your model:", options=("bigscience/bloom-560m",)
21
+ )
22
+
23
+ # with st.spinner("Initializing vector index"):
24
+ model = LlamaCustom(model_name=option)
25
+
26
+ chatbox("llama_custom", model)
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ llama_index
2
+ torch
3
+ transformers
4
+ panda
5
+ numpy
6
+ langchain
7
+ openai
8
+ faiss-cpu
9
+ python-dotenv
10
+ streamlit>=1.24.0
11
+ huggingface_hub
12
+ xformers
13
+ pypdf
utils/__init__.py ADDED
File without changes
utils/chatbox.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+
3
+ import streamlit as st
4
+
5
+ def display_chat_history(model_name: str):
6
+ for message in st.session_state[model_name]:
7
+ with st.chat_message(message["role"]):
8
+ st.markdown(message["content"])
9
+
10
+ def chat_input(model_name: str):
11
+ if prompt := st.chat_input("Say something"):
12
+ # Display user message in chat message container
13
+ st.chat_message("user").markdown(prompt)
14
+
15
+ # Add user message to chat history
16
+ st.session_state[model_name].append({"role": "user", "content": prompt})
17
+
18
+ return prompt
19
+
20
+ def display_bot_msg(model_name: str, bot_response: str):
21
+ # Display assistant response in chat message container
22
+ with st.chat_message("assistant"):
23
+ message_placeholder = st.empty()
24
+ full_response = ""
25
+
26
+ # simulate the chatbot "thinking" before responding
27
+ # (or stream its response)
28
+ for chunk in bot_response.split():
29
+ full_response += chunk + " "
30
+ time.sleep(0.05)
31
+
32
+ # add a blinking cursor to simulate typing
33
+ message_placeholder.markdown(full_response + "▌")
34
+
35
+ message_placeholder.markdown(full_response)
36
+ # st.markdown(response)
37
+
38
+ # Add assistant response to chat history
39
+ st.session_state[model_name].append(
40
+ {"model_name": model_name, "role": "assistant", "content": full_response}
41
+ )
42
+
43
+ def chatbox(model_name: str, model: None):
44
+ # Display chat messages from history on app rerun
45
+ for message in st.session_state.messages:
46
+ if (message["model_name"] == model_name):
47
+ with st.chat_message(message["role"]):
48
+ st.markdown(message["content"])
49
+
50
+ if prompt := st.chat_input("Say something"):
51
+ # Display user message in chat message container
52
+ st.chat_message("user").markdown(prompt)
53
+
54
+ # Add user message to chat history
55
+ st.session_state.messages.append({"model_name": model_name, "role": "user", "content": prompt})
56
+
57
+ with st.spinner("Processing your query..."):
58
+ bot_response = model.get_response(prompt)
59
+
60
+ print("bot: ", bot_response)
61
+
62
+ # Display assistant response in chat message container
63
+ with st.chat_message("assistant"):
64
+ message_placeholder = st.empty()
65
+ full_response = ""
66
+
67
+ # simulate the chatbot "thinking" before responding
68
+ # (or stream its response)
69
+ for chunk in bot_response.split():
70
+ full_response += chunk + " "
71
+ time.sleep(0.05)
72
+
73
+ # add a blinking cursor to simulate typing
74
+ message_placeholder.markdown(full_response + "▌")
75
+
76
+ message_placeholder.markdown(full_response)
77
+ # st.markdown(response)
78
+
79
+ # Add assistant response to chat history
80
+ st.session_state.messages.append(
81
+ {"model_name": model_name, "role": "assistant", "content": full_response}
82
+ )
83
+
84
+ # Scroll to the bottom of the chat container
85
+ # st.markdown(
86
+ # """
87
+ # <script>
88
+ # const chatContainer = document.getElementsByClassName("css-1n76uvr")[0];
89
+ # chatContainer.scrollTop = chatContainer.scrollHeight;
90
+ # </script>
91
+ # """,
92
+ # unsafe_allow_html=True,
93
+ # )
utils/util.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+
4
+ def validate(token: str):
5
+ api_endpoint = "https://api.openai.com/v1/chat/completions"
6
+ api_key = token
7
+
8
+ headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
9
+
10
+ messages = [{"role": "user", "content": "Say this is a test!"}]
11
+
12
+ data = {"model": "gpt-3.5-turbo", "messages": messages}
13
+
14
+ response = requests.post(api_endpoint, json=data, headers=headers)
15
+ return response