niro commited on
Commit
62c16a7
Β·
1 Parent(s): 4c23fea
assets/Images/Vanti - Main Logo@4x copy.png ADDED
assets/Images/colleen-logo.png ADDED
chatbot_legger.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from io import BytesIO
4
+ from io import StringIO
5
+ import sys
6
+ import re
7
+ from langchain.agents import create_csv_agent
8
+ from src.modules.history import ChatHistory
9
+ from src.modules.layout import Layout
10
+ from src.modules.utils import Utilities
11
+ from src.modules.sidebar import Sidebar
12
+ import streamlit as st
13
+ from langchain.embeddings.openai import OpenAIEmbeddings
14
+ from langchain.chat_models import ChatOpenAI
15
+ from langchain.chains import ConversationalRetrievalChain
16
+ from langchain.vectorstores import FAISS
17
+
18
+
19
+ # To be able to update the changes made to modules in localhost,
20
+ # you can press the "r" key on the localhost page to refresh and reflect the changes made to the module files.
21
+ def reload_module(module_name):
22
+ import importlib
23
+ import sys
24
+ if module_name in sys.modules:
25
+ importlib.reload(sys.modules[module_name])
26
+ return sys.modules[module_name]
27
+
28
+
29
+ history_module = reload_module('src.modules.history')
30
+ layout_module = reload_module('src.modules.layout')
31
+ utils_module = reload_module('src.modules.utils')
32
+ sidebar_module = reload_module('src.modules.sidebar')
33
+
34
+ ChatHistory = history_module.ChatHistory
35
+ Layout = layout_module.Layout
36
+ Utilities = utils_module.Utilities
37
+ Sidebar = sidebar_module.Sidebar
38
+
39
+
40
+ def init():
41
+ load_dotenv()
42
+ st.set_page_config(layout="wide", page_icon="πŸ’¬", page_title="ChatBot-Legger")
43
+
44
+
45
+ def main():
46
+ init()
47
+ layout, sidebar, utils = Layout(), Sidebar(), Utilities()
48
+ sidebar.show_logo('assets/Images/colleen-logo.png')
49
+
50
+ layout.show_header_txt()
51
+ user_api_key = utils.load_api_key()
52
+
53
+
54
+ if not user_api_key:
55
+ layout.show_api_key_missing()
56
+ else:
57
+ os.environ["OPENAI_API_KEY"] = user_api_key
58
+ uploaded_file = utils.handle_upload_txt()
59
+
60
+ if uploaded_file:
61
+ history = ChatHistory()
62
+ sidebar.show_options()
63
+
64
+ uploaded_file_content = StringIO(uploaded_file.getvalue().decode("utf-8"))
65
+ string_data = uploaded_file_content.read()
66
+
67
+ # st.write(string_data)
68
+
69
+
70
+ try:
71
+ chatbot = utils.setup_chatbot_txt(
72
+ uploaded_file, st.session_state["model"], st.session_state["temperature"]
73
+ )
74
+ st.session_state["chatbot"] = chatbot
75
+
76
+ # agent = create_csv_agent(ChatOpenAI(temperature=0),
77
+ # uploaded_file_content,
78
+ # verbose=True,
79
+ # max_iterations=15)
80
+
81
+ # embeddings = OpenAIEmbeddings()
82
+ # vectors = FAISS.from_documents([uploaded_file], embeddings)
83
+
84
+ # agent = ConversationalRetrievalChain.from_llm(
85
+ # llm=ChatOpenAI(temperature=0.0, model_name='gpt-3.5-turbo', openai_api_key=user_api_key),
86
+ # retriever=vectors.as_retriever())
87
+ # st.session_state['agent'] = agent
88
+ st.session_state['agent'] = chatbot
89
+
90
+ if st.session_state["ready"]:
91
+ response_container, prompt_container = st.container(), st.container()
92
+
93
+ with prompt_container:
94
+ is_ready, user_input = layout.prompt_form()
95
+
96
+ history.initialize(uploaded_file)
97
+ if st.session_state["reset_chat"]:
98
+ history.reset(uploaded_file)
99
+
100
+ if is_ready:
101
+ history.append("user", user_input)
102
+ output = st.session_state["chatbot"].conversational_chat(user_input)
103
+
104
+ history.append("assistant", output)
105
+ # old_stdout = sys.stdout
106
+ # sys.stdout = captured_output = StringIO()
107
+ # agent_answer = chatbot.run(user_input)
108
+ # sys.stdout = old_stdout
109
+ # thoughts = captured_output.getvalue()
110
+ #
111
+ # cleaned_thoughts = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', thoughts)
112
+ # cleaned_thoughts = re.sub(r'\[1m>', '', cleaned_thoughts)
113
+ #
114
+ # resp = cleaned_thoughts.split('Thought:')[-1].split('Final Answer')
115
+ # thought = resp[0]
116
+ # final_answer = resp[1].split('\n')[0].split(': ')[-1]
117
+ # agent_answer_clean = '\n'.join([thought, final_answer])
118
+ # full_answer = '\n'.join([output, agent_answer_clean])
119
+ # history.append("assistant", full_answer)
120
+
121
+ history.generate_messages(response_container)
122
+
123
+ # if st.session_state["show_csv_agent"]:
124
+ # query = st.text_input(
125
+ # label="Use CSV agent for precise information about the structure of your csv file",
126
+ # placeholder="ex : how many rows in my file ?")
127
+ # if query != "":
128
+ # old_stdout = sys.stdout
129
+ # sys.stdout = captured_output = StringIO()
130
+ # agent = create_csv_agent(ChatOpenAI(temperature=0),
131
+ # uploaded_file_content,
132
+ # verbose=True,
133
+ # max_iterations=4)
134
+ #
135
+ #
136
+ # result = agent.run(query)
137
+ #
138
+ # sys.stdout = old_stdout
139
+ # thoughts = captured_output.getvalue()
140
+ #
141
+ # cleaned_thoughts = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', thoughts)
142
+ # cleaned_thoughts = re.sub(r'\[1m>', '', cleaned_thoughts)
143
+ #
144
+ # with st.expander("Afficher les pensΓ©es de l'agent"):
145
+ # st.write(cleaned_thoughts)
146
+ #
147
+ # st.write(result)
148
+
149
+ except Exception as e:
150
+ st.error(f"Error: {str(e)}")
151
+
152
+ sidebar.about()
153
+
154
+
155
+ if __name__ == "__main__":
156
+ main()
pandasai_demo.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import streamlit as st
3
+ import pandas as pd
4
+ from pandasai import PandasAI
5
+ from pandasai.llm.openai import OpenAI
6
+ import matplotlib.pyplot as plt
7
+ import toml
8
+ #
9
+ #
10
+ key = 'sk-Sr1286CInNN1FxVqTOzu' + 'T3BlbkFJi1eo1gRQED5dSj4KXyHn'
11
+ page_title = "Vanti chatBI"
12
+ page_icon = ":money_with_wings:" # emojis: https://www.webfx.com/tools/emoji-cheat-sheet/
13
+
14
+ st.set_page_config(page_title=page_title, page_icon=page_icon, layout="wide")
15
+ primaryColor = toml.load(".streamlit/config.toml")['theme']['primaryColor']
16
+ style_description = f"""
17
+ <style>
18
+ div.stButton > button:first-child {{ border: 2px solid {primaryColor}; border-radius:10px 10px 10px 10px; }}
19
+ div.stButton > button:hover {{ background-color: {primaryColor}; color:#000000;}}
20
+ footer {{ visibility: hidden;}}
21
+ # header {{ visibility: hidden;}}
22
+ <style>
23
+ """
24
+ st.markdown(style_description, unsafe_allow_html=True)
25
+
26
+ st.title("pandas-ai streamlit interface")
27
+
28
+ st.write("A demo interface for [PandasAI](https://github.com/gventuri/pandas-ai)")
29
+ st.write(
30
+ "Looking for an example *.csv-file?, check [here](https://gist.github.com/netj/8836201)."
31
+ )
32
+ with st.sidebar:
33
+ st.image('assets/Images/Vanti - Main Logo@4x copy.png')
34
+ if "openai_key" not in st.session_state:
35
+ with st.form("API key"):
36
+ key = st.text_input("OpenAI Key", value="", type="password")
37
+ if st.form_submit_button("Submit"):
38
+ st.session_state.openai_key = key
39
+ st.session_state.prompt_history = []
40
+ st.session_state.df = None
41
+
42
+ if "openai_key" in st.session_state:
43
+ if st.session_state.df is None:
44
+ uploaded_file = st.file_uploader(
45
+ "Choose a CSV file. This should be in long format (one datapoint per row).",
46
+ type="csv",
47
+ )
48
+ if uploaded_file is not None:
49
+ df = pd.read_csv(uploaded_file)
50
+ st.session_state.df = df
51
+
52
+ with st.form("Question"):
53
+ question = st.text_input("Question", value="", type="default")
54
+ submitted = st.form_submit_button("Submit")
55
+ if submitted:
56
+ with st.spinner():
57
+ llm = OpenAI(api_token=st.session_state.openai_key)
58
+ pandas_ai = PandasAI(llm)
59
+ x = pandas_ai.run(st.session_state.df, prompt=question)
60
+
61
+ fig = plt.gcf()
62
+ if fig.get_axes():
63
+ st.pyplot(fig)
64
+ st.write(x)
65
+ st.session_state.prompt_history.append(question)
66
+
67
+ if st.session_state.df is not None:
68
+ st.subheader("Current dataframe:")
69
+ st.write(st.session_state.df)
70
+
71
+ st.subheader("Prompt history:")
72
+ st.write(st.session_state.prompt_history)
73
+
74
+
75
+ if st.button("Clear"):
76
+ st.session_state.prompt_history = []
77
+ st.session_state.df = None
src/modules/chatbot.py CHANGED
@@ -4,6 +4,48 @@ from langchain.chains import ConversationalRetrievalChain
4
  from langchain.prompts.prompt import PromptTemplate
5
 
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  class Chatbot:
8
  _template = """Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question.
9
  Chat History:
 
4
  from langchain.prompts.prompt import PromptTemplate
5
 
6
 
7
+ class Chatbot_txt:
8
+ _template = """Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question.
9
+ Chat History:
10
+ {chat_history}
11
+ Follow-up entry: {question}
12
+ Standalone question:"""
13
+
14
+ CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(_template)
15
+
16
+ qa_template = """"You are an AI conversational assistant to answer questions based on a context.
17
+ You are given data from a txt file and a question, you must help the user find the information they need.
18
+ Your answers should be friendly, in the same language.
19
+ question: {question}
20
+ =========
21
+ context: {context}
22
+ =======
23
+ """
24
+
25
+ QA_PROMPT = PromptTemplate(template=qa_template, input_variables=["question", "context"])
26
+
27
+ def __init__(self, model_name, temperature, vectors):
28
+ self.model_name = model_name
29
+ self.temperature = temperature
30
+ self.vectors = vectors
31
+
32
+ def conversational_chat(self, query):
33
+ """
34
+ Starts a conversational chat with a model via Langchain
35
+ """
36
+ chain = ConversationalRetrievalChain.from_llm(
37
+ llm=ChatOpenAI(model_name=self.model_name, temperature=self.temperature),
38
+ condense_question_prompt=self.CONDENSE_QUESTION_PROMPT,
39
+ qa_prompt=self.QA_PROMPT,
40
+ retriever=self.vectors.as_retriever(),
41
+ )
42
+ result = chain({"question": query, "chat_history": st.session_state["history"]})
43
+
44
+ st.session_state["history"].append((query, result["answer"]))
45
+
46
+ return result["answer"]
47
+
48
+
49
  class Chatbot:
50
  _template = """Given the following conversation and a follow-up question, rephrase the follow-up question to be a standalone question.
51
  Chat History:
src/modules/embedder.py CHANGED
@@ -4,8 +4,66 @@ import tempfile
4
  from langchain.document_loaders.csv_loader import CSVLoader
5
  from langchain.vectorstores import FAISS
6
  from langchain.embeddings.openai import OpenAIEmbeddings
 
 
7
 
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  class Embedder:
10
  def __init__(self):
11
  self.PATH = "embeddings"
 
4
  from langchain.document_loaders.csv_loader import CSVLoader
5
  from langchain.vectorstores import FAISS
6
  from langchain.embeddings.openai import OpenAIEmbeddings
7
+ from langchain.document_loaders import TextLoader
8
+ from langchain.text_splitter import CharacterTextSplitter
9
 
10
 
11
+ class Embedder_txt:
12
+ def __init__(self):
13
+ self.PATH = "embeddings"
14
+ self.createEmbeddingsDir()
15
+
16
+ def createEmbeddingsDir(self):
17
+ """
18
+ Creates a directory to store the embeddings vectors
19
+ """
20
+ if not os.path.exists(self.PATH):
21
+ os.mkdir(self.PATH)
22
+
23
+ def storeDocEmbeds(self, file, filename):
24
+ """
25
+ Stores document embeddings using Langchain and FAISS
26
+ """
27
+ # Write the uploaded file to a temporary file
28
+ with tempfile.NamedTemporaryFile(mode="wb", delete=False) as tmp_file:
29
+ tmp_file.write(file)
30
+ tmp_file_path = tmp_file.name
31
+
32
+ # Load the data from the file using Langchain
33
+ # loader = CSVLoader(file_path=tmp_file_path, encoding="utf-8")
34
+ documents = []
35
+ loader = TextLoader(file_path=tmp_file_path)
36
+ documents.extend(loader.load())
37
+ text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
38
+ data = loader.load_and_split()
39
+ texts = text_splitter.split_documents(documents)
40
+
41
+ # Create an embeddings object using Langchain
42
+ embeddings = OpenAIEmbeddings()
43
+
44
+ # Store the embeddings vectors using FAISS
45
+ vectors = FAISS.from_documents(texts, embeddings)
46
+ os.remove(tmp_file_path)
47
+
48
+ # Save the vectors to a pickle file
49
+ with open(f"{self.PATH}/{filename}.pkl", "wb") as f:
50
+ pickle.dump(vectors, f)
51
+
52
+ def getDocEmbeds(self, file, filename):
53
+ """
54
+ Retrieves document embeddings
55
+ """
56
+ # Check if embeddings vectors have already been stored in a pickle file
57
+ if not os.path.isfile(f"{self.PATH}/{filename}.pkl"):
58
+ # If not, store the vectors using the storeDocEmbeds function
59
+ self.storeDocEmbeds(file, filename)
60
+
61
+ # Load the vectors from the pickle file
62
+ with open(f"{self.PATH}/{filename}.pkl", "rb") as f:
63
+ vectors = pickle.load(f)
64
+
65
+ return vectors
66
+
67
  class Embedder:
68
  def __init__(self):
69
  self.PATH = "embeddings"
src/modules/layout.py CHANGED
@@ -3,6 +3,18 @@ import streamlit as st
3
 
4
  class Layout:
5
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  def show_header(self):
7
  """
8
  Displays the header of the app
 
3
 
4
  class Layout:
5
 
6
+ def show_header_txt(self):
7
+ """
8
+ Displays the header of the app
9
+ """
10
+ # st.image('assets/Images/colleen-logo.png', width=400)
11
+ st.markdown(
12
+ """
13
+ <h1 style='text-align: center;'>LedgerGPT by Colleen.AI, Talk with your ledger data! πŸ’¬</h1>
14
+ """,
15
+ unsafe_allow_html=True,
16
+ )
17
+
18
  def show_header(self):
19
  """
20
  Displays the header of the app
src/modules/sidebar.py CHANGED
@@ -8,6 +8,10 @@ class Sidebar:
8
  TEMPERATURE_DEFAULT_VALUE = 0.0
9
  TEMPERATURE_STEP = 0.01
10
 
 
 
 
 
11
  @staticmethod
12
  def about():
13
  about = st.sidebar.expander("About πŸ€–")
 
8
  TEMPERATURE_DEFAULT_VALUE = 0.0
9
  TEMPERATURE_STEP = 0.01
10
 
11
+ @staticmethod
12
+ def show_logo(path):
13
+ st.sidebar.image(path)
14
+
15
  @staticmethod
16
  def about():
17
  about = st.sidebar.expander("About πŸ€–")
src/modules/utils.py CHANGED
@@ -1,9 +1,11 @@
1
  import os
2
  import pandas as pd
3
  import streamlit as st
 
4
 
5
- from src.modules.chatbot import Chatbot
6
- from src.modules.embedder import Embedder
 
7
 
8
 
9
  class Utilities:
@@ -24,6 +26,29 @@ class Utilities:
24
  st.sidebar.success("API key loaded", icon="πŸš€")
25
  return user_api_key
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  @staticmethod
28
  def handle_upload():
29
  """
@@ -31,14 +56,12 @@ class Utilities:
31
  """
32
  uploaded_file = st.sidebar.file_uploader("upload", type="csv", label_visibility="collapsed")
33
  if uploaded_file is not None:
34
-
35
 
36
  def show_user_file(uploaded_file):
37
  file_container = st.expander("Your CSV file :")
38
  shows = pd.read_csv(uploaded_file)
39
  uploaded_file.seek(0)
40
  file_container.write(shows)
41
-
42
 
43
  show_user_file(uploaded_file)
44
  else:
@@ -49,12 +72,27 @@ class Utilities:
49
  st.session_state["reset_chat"] = True
50
  return uploaded_file
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  @staticmethod
53
  def setup_chatbot(uploaded_file, model, temperature):
54
  """
55
  Sets up the chatbot with the uploaded file, model, and temperature
56
  """
57
- embeds = Embedder()
58
  with st.spinner("Processing..."):
59
  uploaded_file.seek(0)
60
  file = uploaded_file.read()
 
1
  import os
2
  import pandas as pd
3
  import streamlit as st
4
+ from io import StringIO
5
 
6
+
7
+ from src.modules.chatbot import Chatbot_txt, Chatbot
8
+ from src.modules.embedder import Embedder_txt, Embedder
9
 
10
 
11
  class Utilities:
 
26
  st.sidebar.success("API key loaded", icon="πŸš€")
27
  return user_api_key
28
 
29
+ @staticmethod
30
+ def handle_upload_txt():
31
+ """
32
+ Handles the file upload and displays the uploaded file
33
+ """
34
+ uploaded_file = st.sidebar.file_uploader("upload", type="txt", label_visibility="collapsed")
35
+ if uploaded_file is not None:
36
+
37
+ def show_user_file(uploaded_file):
38
+ file_container = st.expander("Your TXT file :")
39
+ uploaded_file_content = StringIO(uploaded_file.getvalue().decode("utf-8"))
40
+ string_data = uploaded_file_content.read()
41
+ file_container.write(string_data)
42
+
43
+ show_user_file(uploaded_file)
44
+ else:
45
+ st.sidebar.info(
46
+ "πŸ‘† Upload your TXT file to get started, "
47
+ # "sample for try : [fishfry-locations.csv](https://drive.google.com/file/d/1TpP3thVnTcDO1_lGSh99EKH2iF3GDE7_/view?usp=sharing)"
48
+ )
49
+ st.session_state["reset_chat"] = True
50
+ return uploaded_file
51
+
52
  @staticmethod
53
  def handle_upload():
54
  """
 
56
  """
57
  uploaded_file = st.sidebar.file_uploader("upload", type="csv", label_visibility="collapsed")
58
  if uploaded_file is not None:
 
59
 
60
  def show_user_file(uploaded_file):
61
  file_container = st.expander("Your CSV file :")
62
  shows = pd.read_csv(uploaded_file)
63
  uploaded_file.seek(0)
64
  file_container.write(shows)
 
65
 
66
  show_user_file(uploaded_file)
67
  else:
 
72
  st.session_state["reset_chat"] = True
73
  return uploaded_file
74
 
75
+ @staticmethod
76
+ def setup_chatbot_txt(uploaded_file, model, temperature):
77
+ """
78
+ Sets up the chatbot with the uploaded file, model, and temperature
79
+ """
80
+ embeds = Embedder_txt()
81
+ with st.spinner("Processing..."):
82
+ uploaded_file.seek(0)
83
+ file = uploaded_file.read()
84
+ vectors = embeds.getDocEmbeds(file, uploaded_file.name)
85
+ chatbot = Chatbot(model, temperature, vectors)
86
+ st.session_state["ready"] = True
87
+ return chatbot
88
+
89
+
90
  @staticmethod
91
  def setup_chatbot(uploaded_file, model, temperature):
92
  """
93
  Sets up the chatbot with the uploaded file, model, and temperature
94
  """
95
+ embeds = Embedder_txt()
96
  with st.spinner("Processing..."):
97
  uploaded_file.seek(0)
98
  file = uploaded_file.read()