ainur1 commited on
Commit
d31e8ca
1 Parent(s): 90bbda1
app.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from utils import Bot
3
+
4
+ # Define the initialization function for the bot
5
+ def initialize_bot(openai_api_key, table_descriptions, text_documents):
6
+ global bot
7
+ bot = Bot(openai_api_key=openai_api_key, table_descriptions=table_descriptions, text_documents=text_documents, verbose=True)
8
+
9
+ # Define the function to generate the bot's response
10
+ def generate_response(question):
11
+ response = bot(question)
12
+ return response
13
+
14
+ # Define the interface components
15
+ openai_api_key_input = gr.inputs.Textbox(label="OpenAI API Key")
16
+ table_descriptions_input = gr.inputs.Textbox(label="Table Descriptions")
17
+ text_documents_input = gr.inputs.Textbox(label="Text Documents")
18
+
19
+ submit_button = gr.outputs.Button(label="Submit")
20
+
21
+ question_input = gr.inputs.Textbox(label="Ask a question")
22
+ submit_question_button = gr.outputs.Button(label="Submit")
23
+
24
+ # Define the interface layout
25
+ input_components = [
26
+ openai_api_key_input,
27
+ table_descriptions_input,
28
+ text_documents_input,
29
+ submit_button,
30
+ ]
31
+
32
+ output_components = [
33
+ question_input,
34
+ submit_question_button,
35
+ ]
36
+
37
+ interface = gr.Interface(
38
+ initialize_bot,
39
+ input_components,
40
+ show_input=False,
41
+ outputs=output_components,
42
+ title="Chat with your Bot",
43
+ )
44
+
45
+ # Define the callback function for the submit button
46
+ def submit_callback(openai_api_key, table_descriptions, text_documents):
47
+ initialize_bot(openai_api_key, table_descriptions, text_documents)
48
+
49
+ # Define the callback function for the submit question button
50
+ def submit_question_callback(question):
51
+ response = generate_response(question)
52
+ return response
53
+
54
+ # Add the callbacks to the interface
55
+ interface.launch(inline=False, submit_button=submit_callback, submit_question_button=submit_question_callback)
utils/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .bot import Bot
utils/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (166 Bytes). View file
 
utils/__pycache__/bot.cpython-310.pyc ADDED
Binary file (5.72 kB). View file
 
utils/bot.py ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import langchain
2
+ from langchain.agents import create_csv_agent
3
+ from langchain.schema import HumanMessage
4
+ from langchain.chat_models import ChatOpenAI
5
+ from langchain.embeddings import OpenAIEmbeddings
6
+ from langchain.vectorstores import Chroma
7
+ from typing import List, Dict
8
+ from langchain.agents import AgentType
9
+ from langchain.chains.conversation.memory import ConversationBufferWindowMemory
10
+
11
+
12
+ class Bot:
13
+
14
+ def __init__(
15
+ self,
16
+ openai_api_key: str,
17
+ table_descriptions: List[Dict[str, any]],
18
+ text_documents: List[langchain.schema.Document],
19
+ verbose: bool = False
20
+ ):
21
+ self.verbose = verbose
22
+ self.table_descriptions = table_descriptions
23
+
24
+ self.llm = ChatOpenAI(
25
+ openai_api_key=openai_api_key,
26
+ temperature=0,
27
+ model_name="gpt-3.5-turbo"
28
+ )
29
+
30
+ embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
31
+ vector_store = Chroma.from_documents(text_documents, embeddings)
32
+ self.text_retriever = langchain.chains.RetrievalQAWithSourcesChain.from_chain_type(
33
+ llm=self.llm,
34
+ chain_type='stuff',
35
+ retriever=vector_store.as_retriever()
36
+ )
37
+ self.text_search_tool = langchain.agents.Tool(
38
+ func=self._text_search,
39
+ description="Use this tool when searching for text information",
40
+ name="search text information"
41
+ )
42
+
43
+ def __call__(
44
+ self,
45
+ question: str
46
+ ):
47
+ self.tools = []
48
+ self.tools.append(self.text_search_tool)
49
+ table = self._define_appropriate_table(question)
50
+ if table != "None of the tables":
51
+ number = int(table[table.find('№')+1:])
52
+ table_description = [x for x in self.table_descriptions if x['number'] == number][0]
53
+ table_path = table_description['path']
54
+
55
+ self.csv_agent = create_csv_agent(
56
+ llm=self.llm,
57
+ path=table_path,
58
+ verbose=self.verbose
59
+ )
60
+
61
+ self._init_tabular_search_tool(table_description)
62
+ self.tools.append(self.tabular_search_tool)
63
+
64
+ self._init_chatbot()
65
+ print(table)
66
+ response = self.agent(question)
67
+ return response
68
+
69
+ def _init_chatbot(self):
70
+
71
+ conversational_memory = ConversationBufferWindowMemory(
72
+ memory_key='chat_history',
73
+ k=5,
74
+ return_messages=True
75
+ )
76
+
77
+ self.agent = langchain.agents.initialize_agent(
78
+ agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
79
+ tools=self.tools,
80
+ llm=self.llm,
81
+ verbose=self.verbose,
82
+ max_iterations=5,
83
+ early_stopping_method='generate',
84
+ memory=conversational_memory
85
+ )
86
+ sys_msg = (
87
+ "You are an expert summarizer and deliverer of information. "
88
+ "Yet, the reason you are so intelligent is that you make complex "
89
+ "information incredibly simple to understand. It's actually rather incredible."
90
+ "When users ask information you refer to the relevant tools."
91
+ "if one of the tools helped you with only a part of the necessary information, you must "
92
+ "try to find the missing information using another tool"
93
+ "if you can't find the information using the provided tools, you MUST "
94
+ "say 'I don't know'. Don't try to make up an answer."
95
+ )
96
+ prompt = self.agent.agent.create_prompt(
97
+ system_message=sys_msg,
98
+ tools=self.tools
99
+ )
100
+ self.agent.agent.llm_chain.prompt = prompt
101
+
102
+ def _text_search(
103
+ self,
104
+ query: str
105
+ ) -> str:
106
+ query = self.text_retriever.prep_inputs(query)
107
+ res = self.text_retriever(query)['answer']
108
+ return res
109
+
110
+ def _tabular_search(
111
+ self,
112
+ query: str
113
+ ) -> str:
114
+ res = self.csv_agent.run(query)
115
+ return res
116
+
117
+ def _init_tabular_search_tool(
118
+ self,
119
+ table_description: Dict[str, any]
120
+ ) -> None:
121
+
122
+ columns = table_description["columns"]
123
+ columns = '"' + '", "'.join(columns) + '"'
124
+ tittle = table_description["tittle"]
125
+
126
+ description = f"""
127
+ Use this tool when searching for tabular information.
128
+ With this tool you could get access to table.
129
+ This table tittle is "{tittle}" and the names of the columns in this table: {columns}
130
+ """
131
+
132
+ self.tabular_search_tool = langchain.agents.Tool(
133
+ func=self._tabular_search,
134
+ description=description,
135
+ name="search tabular information"
136
+ )
137
+
138
+ def _define_appropriate_table(
139
+ self,
140
+ question: str
141
+ ) -> str:
142
+ ''' Определяет по описаниям таблиц в какой из них может содержаться ответ на во��рос.
143
+ Возвращает номер таблицы по шаблону "Table №1" или "None of the tables" '''
144
+
145
+ message = 'I have list of table descriptions: \n'
146
+ k = 0
147
+ for description in self.table_descriptions:
148
+ k += 1
149
+ number = description["number"]
150
+ columns = description["columns"]
151
+ columns = '"' + '", "'.join(columns) + '"'
152
+ tittle = description["tittle"]
153
+ str_description = f""" {k}) description for Table №{number}:
154
+ a) table consist of columns with names: {columns};
155
+ b) table tittle: {tittle}.\n"""
156
+ message += str_description
157
+
158
+ question = f""" How do you think, which table can help answer the question: "{question}" .
159
+ Your answer MUST be specific,
160
+ for example if you think that Table №2 can help answer the question, you MUST just write "Table №2".
161
+ If you think that none of the tables can help answer the question just write "None of the tables"
162
+ Don't include to answer information about your thinking.
163
+ """
164
+ message += question
165
+
166
+ res = self.llm([HumanMessage(content=message)])
167
+ return res.content[:-1]
168
+