Spaces:
Sleeping
Sleeping
coulibaly-b
commited on
Commit
•
240310d
1
Parent(s):
d605c1e
login page
Browse files- AI_generator.py +202 -0
- LPO_AI.egg-info/PKG-INFO +3 -0
- LPO_AI.egg-info/SOURCES.txt +6 -0
- LPO_AI.egg-info/dependency_links.txt +1 -0
- LPO_AI.egg-info/top_level.txt +1 -0
- __pycache__/AI_generator.cpython-312.pyc +0 -0
- __pycache__/dashboard.cpython-312.pyc +0 -0
- app.py +71 -198
- dashboard.py +181 -0
- pages/dashboard.py +0 -177
- setup.py +3 -0
AI_generator.py
ADDED
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from langchain_community.llms import HuggingFaceHub
|
2 |
+
from langchain.chains import SequentialChain
|
3 |
+
from langchain.prompts import ChatPromptTemplate
|
4 |
+
from langchain.chains import LLMChain
|
5 |
+
from dotenv import load_dotenv
|
6 |
+
import streamlit as st
|
7 |
+
import plotly.express as px
|
8 |
+
import plotly.graph_objects as go
|
9 |
+
import os
|
10 |
+
import hashlib
|
11 |
+
|
12 |
+
load_dotenv()
|
13 |
+
|
14 |
+
|
15 |
+
HUGGINGFACE_HUB_API_TOKEN = os.getenv("HUGGINGFACE_HUB_API_TOKEN")
|
16 |
+
|
17 |
+
|
18 |
+
SCHEMA_STR = """ Table Name: sensitive_areas
|
19 |
+
|
20 |
+
!important : data_path = data/biodiv_sports.db
|
21 |
+
|
22 |
+
Columns:
|
23 |
+
|
24 |
+
1. `id` (INTEGER): Unique identifier for the sensitive area and record.
|
25 |
+
2. `name` (TEXT): Name of the sensitive area.
|
26 |
+
3. `description` (TEXT): Description of the sensitive area.
|
27 |
+
4. `practices` (INTEGER): Sporting activities related to the sensitive area.
|
28 |
+
5. `structure` (TEXT): Name or acronym of the organization that provided the data for this sensitive area.
|
29 |
+
6. `species_id` (INTEGER): Identifier for the species associated with the sensitive area, or NULL if it is a regulatory zone.
|
30 |
+
7. `update_datetime` (TIMESTAMP): Date and time when the sensitive area was last updated.
|
31 |
+
8. `create_datetime` (TIMESTAMP): Date and time when the sensitive area was created.
|
32 |
+
9. `region` (TEXT): Region where the sensitive area is located.
|
33 |
+
10. `departement` (TEXT): Department where the sensitive area is located.
|
34 |
+
11. `pays` (TEXT): Country where the sensitive area is located.
|
35 |
+
12. `months` (TEXT): Month during which the species is present in the sensitive area.
|
36 |
+
|
37 |
+
Other information:
|
38 |
+
- category='spece' if species_id else'regulatory zone'
|
39 |
+
category is not a column name.
|
40 |
+
|
41 |
+
- Each id represents a single record.
|
42 |
+
"""
|
43 |
+
|
44 |
+
|
45 |
+
class SqlToPlotlyStreamlit:
|
46 |
+
@staticmethod
|
47 |
+
def chat_prompt_template() -> list:
|
48 |
+
first_prompt = ChatPromptTemplate.from_template(
|
49 |
+
"""Generate the optimal SQL query considering the following table schema and the user's question.
|
50 |
+
!IMPORTANT: Generate exactly one query and ensure that the query can be used directly without further \
|
51 |
+
modification with sqlite3. Ensure that the columns used in the generated query match the table schema."""
|
52 |
+
"!Important: if there are aggregations arroundi the result to 2 decimal places always"
|
53 |
+
"""Table schema:\n{schema}\nQuestion: {question}"""
|
54 |
+
)
|
55 |
+
|
56 |
+
second_prompt = ChatPromptTemplate.from_template(
|
57 |
+
"Convert the provided SQL query {query} into a Python best graph code snippet. Use the plotly library otherwise seaborn with error handling for visualization."
|
58 |
+
"!IMPORTANT : Provide detailed instructions about loading necessary libraries very important, setting up credentials,"
|
59 |
+
"and configuring parameters needed for connecting to the database, creating the figure, and showing the plot."
|
60 |
+
"the graph will part of an streamlit app so import streamlit, pandas and all librairie that will be use."
|
61 |
+
"Follow the following step:"
|
62 |
+
"1 - import all neccessary librairies"
|
63 |
+
"2 - settting up database connection with sqlite.connect"
|
64 |
+
"3 - Use pandas read_sql_query to retrieve data from database"
|
65 |
+
"4 - close database connection"
|
66 |
+
"5 - try Plotly to build the graph if error use seaborn"
|
67 |
+
"6 - Use distinct color in the graph"
|
68 |
+
"7 - Display the dataframe in table format"
|
69 |
+
"8 - Never use statment if __name__ == '__main__' "
|
70 |
+
)
|
71 |
+
|
72 |
+
third_prompt = ChatPromptTemplate.from_template(
|
73 |
+
"""Return a JSON object containing the original {question}, extracted SQL query {query}, and extracted corresponding Python code {python_graph} snippet separated by two newlines ('\n')."""
|
74 |
+
)
|
75 |
+
|
76 |
+
fourth_prompt = ChatPromptTemplate.from_template(
|
77 |
+
"""Generate another type of graphic for the {query} different from {python_graph}."""
|
78 |
+
)
|
79 |
+
|
80 |
+
return [first_prompt, second_prompt, third_prompt, fourth_prompt]
|
81 |
+
|
82 |
+
@staticmethod
|
83 |
+
def generate_anwers() -> list:
|
84 |
+
first_prompt, second_prompt, third_prompt, fourth_prompt = (
|
85 |
+
SqlToPlotlyStreamlit.chat_prompt_template()
|
86 |
+
)
|
87 |
+
|
88 |
+
chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key="query")
|
89 |
+
chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key="python_graph")
|
90 |
+
chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key="json")
|
91 |
+
chain_four = LLMChain(
|
92 |
+
llm=llm, prompt=fourth_prompt, output_key="reformulated_query"
|
93 |
+
)
|
94 |
+
|
95 |
+
return [chain_one, chain_two, chain_three, chain_four]
|
96 |
+
|
97 |
+
@staticmethod
|
98 |
+
def format_python_code_string(code_str: str) -> str:
|
99 |
+
import re
|
100 |
+
|
101 |
+
# Supprimer les espaces inutiles
|
102 |
+
code_str = re.sub(r"^\s+", "", code_str, flags=re.MULTILINE)
|
103 |
+
code_str = re.sub(r"\s+", " ", code_str)
|
104 |
+
code_str = re.sub(r"\s+$", "", code_str, flags=re.MULTILINE)
|
105 |
+
|
106 |
+
# Ajouter des espaces avant et après les opérateurs
|
107 |
+
code_str = re.sub(r"(\+|\-|\*|\/|\=|\(|\))", r" \1 ", code_str)
|
108 |
+
code_str = re.sub(r"(\w+)\s*(\w+)", r"\1 \2", code_str)
|
109 |
+
|
110 |
+
# Ajouter des espaces après les virgules
|
111 |
+
code_str = re.sub(r",\s*", ", ", code_str)
|
112 |
+
|
113 |
+
# Ajouter des espaces après les deux-points
|
114 |
+
code_str = re.sub(r":\s*", ": ", code_str)
|
115 |
+
|
116 |
+
# Ajouter des espaces avant les crochets et accolades
|
117 |
+
code_str = re.sub(r"(\w+)\s*(\{|\[)", r"\1 \2", code_str)
|
118 |
+
code_str = re.sub(r"(\}|\])", r" \1", code_str)
|
119 |
+
|
120 |
+
# Aligner les indentations
|
121 |
+
lines = code_str.split("\n")
|
122 |
+
indentation_levels = []
|
123 |
+
for line in lines:
|
124 |
+
indentation_level = len(line) - len(line.lstrip())
|
125 |
+
indentation_levels.append(indentation_level)
|
126 |
+
max_indentation_level = max(indentation_levels)
|
127 |
+
indentation_spaces = " " * max_indentation_level
|
128 |
+
code_str = "\n".join(indentation_spaces + line.lstrip() for line in lines)
|
129 |
+
|
130 |
+
# Ajouter des espaces entre les mots-clés et les identifiants
|
131 |
+
code_str = re.sub(r"(\b(and|or|not|is|in)\b)\s*(\w+)", r"\1 \3", code_str)
|
132 |
+
|
133 |
+
return code_str
|
134 |
+
|
135 |
+
@staticmethod
|
136 |
+
def code_execution(code_str):
|
137 |
+
|
138 |
+
code_str = SqlToPlotlyStreamlit.format_python_code_string(code_str)
|
139 |
+
# Exécuter le code dans un environnement isolé
|
140 |
+
namespace = {}
|
141 |
+
exec(code_str, namespace)
|
142 |
+
|
143 |
+
# Récupérer la figure du namespace
|
144 |
+
fig = namespace.get("fig")
|
145 |
+
|
146 |
+
if isinstance(fig, go.Figure):
|
147 |
+
|
148 |
+
st.plotly_chart(fig)
|
149 |
+
|
150 |
+
def __init__(self, schema: str, question: str):
|
151 |
+
self.schema = schema
|
152 |
+
self.question = question
|
153 |
+
self.llm = HuggingFaceHub(
|
154 |
+
repo_id="mistralai/MixTraL-8x7B-Instruct-v0.1",
|
155 |
+
model_kwargs={
|
156 |
+
"temperature": 0.001,
|
157 |
+
"max_length": 5000,
|
158 |
+
"max_new_tokens": 1024,
|
159 |
+
},
|
160 |
+
huggingfacehub_api_token=HUGGINGFACE_HUB_API_TOKEN,
|
161 |
+
)
|
162 |
+
|
163 |
+
def execute_overall_flow(self):
|
164 |
+
error_occurred = False
|
165 |
+
|
166 |
+
try:
|
167 |
+
overall_chain = SequentialChain(
|
168 |
+
chains=list(SqlToPlotlyStreamlit.generate_anwers()),
|
169 |
+
input_variables=["schema", "question"],
|
170 |
+
output_variables=["query", "python_graph", "json"],
|
171 |
+
verbose=True,
|
172 |
+
)
|
173 |
+
result = overall_chain({"schema": self.schema, "question": self.question})
|
174 |
+
self.generated_python_code = (
|
175 |
+
result["json"].split("```python")[-1].split("```")[0].replace("```", "")
|
176 |
+
)
|
177 |
+
# self.code_execution(self.generated_python_code)
|
178 |
+
|
179 |
+
except Exception as e:
|
180 |
+
error_message = f"\nAttempt: An exception occurred while executing the generated code:{e}"
|
181 |
+
st.write(error_message)
|
182 |
+
error_occurred = True
|
183 |
+
|
184 |
+
if not error_occurred:
|
185 |
+
# st.write("## Generated Query")
|
186 |
+
# st.code(result["json"].split("```sql")[-1].split("```")[0].replace("```", ""))
|
187 |
+
st.write("## Generated Python")
|
188 |
+
st.code(self.generated_python_code)
|
189 |
+
|
190 |
+
|
191 |
+
def main():
|
192 |
+
st.set_page_config(layout="wide")
|
193 |
+
st.title("SQL Query Visualizer")
|
194 |
+
|
195 |
+
schema = SCHEMA_STR
|
196 |
+
question = st.text_input(
|
197 |
+
"Enter Question:", "what is the total of zones for each category ?"
|
198 |
+
)
|
199 |
+
if st.button("Run"):
|
200 |
+
obj = SqlToPlotlyStreamlit(schema, question)
|
201 |
+
obj.execute_overall_flow()
|
202 |
+
exec(obj.generated_python_code)
|
LPO_AI.egg-info/PKG-INFO
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: LPO_AI
|
3 |
+
Version: 0.0.0
|
LPO_AI.egg-info/SOURCES.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
README.md
|
2 |
+
setup.py
|
3 |
+
LPO_AI.egg-info/PKG-INFO
|
4 |
+
LPO_AI.egg-info/SOURCES.txt
|
5 |
+
LPO_AI.egg-info/dependency_links.txt
|
6 |
+
LPO_AI.egg-info/top_level.txt
|
LPO_AI.egg-info/dependency_links.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
LPO_AI.egg-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
__pycache__/AI_generator.cpython-312.pyc
ADDED
Binary file (9.79 kB). View file
|
|
__pycache__/dashboard.cpython-312.pyc
ADDED
Binary file (4.69 kB). View file
|
|
app.py
CHANGED
@@ -1,209 +1,82 @@
|
|
1 |
-
from langchain_community.llms import HuggingFaceHub
|
2 |
-
from langchain.chains import SequentialChain
|
3 |
-
from langchain.prompts import ChatPromptTemplate
|
4 |
-
from langchain.chains import LLMChain
|
5 |
-
from dotenv import load_dotenv
|
6 |
import streamlit as st
|
7 |
-
import
|
8 |
-
import
|
9 |
-
|
|
|
10 |
import os
|
|
|
11 |
|
12 |
load_dotenv()
|
13 |
-
HUGGINGFACE_HUB_API_TOKEN = os.getenv("HUGGINGFACE_HUB_API_TOKEN")
|
14 |
-
|
15 |
-
llm = HuggingFaceHub(
|
16 |
-
repo_id="mistralai/MixTraL-8x7B-Instruct-v0.1",
|
17 |
-
model_kwargs={
|
18 |
-
"temperature": 0.001,
|
19 |
-
"max_length": 5000,
|
20 |
-
"max_new_tokens": 1024,
|
21 |
-
},
|
22 |
-
huggingfacehub_api_token=HUGGINGFACE_HUB_API_TOKEN,
|
23 |
-
)
|
24 |
-
|
25 |
-
SCHEMA_STR = """ Table Name: sensitive_areas
|
26 |
-
|
27 |
-
!important : data_path = data/biodiv_sports.db
|
28 |
-
|
29 |
-
Columns:
|
30 |
-
|
31 |
-
1. `id` (INTEGER): Unique identifier for the sensitive area.
|
32 |
-
2. `name` (TEXT): Name of the sensitive area.
|
33 |
-
3. `description` (TEXT): Description of the sensitive area.
|
34 |
-
4. `practices` (INTEGER): Sporting activities related to the sensitive area.
|
35 |
-
5. `structure` (TEXT): Name or acronym of the organization that provided the data for this sensitive area.
|
36 |
-
6. `species_id` (INTEGER): Identifier for the species associated with the sensitive area, or NULL if it is a regulatory zone.
|
37 |
-
7. `update_datetime` (TIMESTAMP): Date and time when the sensitive area was last updated.
|
38 |
-
8. `create_datetime` (TIMESTAMP): Date and time when the sensitive area was created.
|
39 |
-
9. `region` (TEXT): Region where the sensitive area is located.
|
40 |
-
10. `departement` (TEXT): Department where the sensitive area is located.
|
41 |
-
11. `pays` (TEXT): Country where the sensitive area is located.
|
42 |
-
12. `months` (TEXT): Month during which the species is present in the sensitive area.
|
43 |
-
|
44 |
-
Other information: category='spece' if species_id else'regulatory zone'
|
45 |
-
category is not a column name."""
|
46 |
-
|
47 |
-
|
48 |
-
class SqlToPlotlyStreamlit:
|
49 |
-
@staticmethod
|
50 |
-
def chat_prompt_template() -> list:
|
51 |
-
first_prompt = ChatPromptTemplate.from_template(
|
52 |
-
"""Generate the optimal SQL query considering the following table schema and the user's question.
|
53 |
-
!IMPORTANT: Generate exactly one query and ensure that the query can be used directly without further \
|
54 |
-
modification with sqlite3. Ensure that the columns used in the generated query match the table schema."""
|
55 |
-
"!Important: if there are aggregations arroundi the result to 2 decimal places always"
|
56 |
-
"""Table schema:\n{schema}\nQuestion: {question}"""
|
57 |
-
)
|
58 |
-
|
59 |
-
second_prompt = ChatPromptTemplate.from_template(
|
60 |
-
"Convert the provided SQL query {query} into a Python best graph code snippet. Use the plotly library otherwise seaborn with error handling for visualization."
|
61 |
-
"!IMPORTANT : Provide detailed instructions about loading necessary libraries very important, setting up credentials,"
|
62 |
-
"and configuring parameters needed for connecting to the database, creating the figure, and showing the plot."
|
63 |
-
"the graph will part of an streamlit app so import streamlit, pandas and all librairie that will be use."
|
64 |
-
"Follow the following step:"
|
65 |
-
"1 - import all neccessary librairies"
|
66 |
-
"2 - settting up database connection with sqlite.connect"
|
67 |
-
"3 - Use pandas read_sql_query to retrieve data from database"
|
68 |
-
"4 - close database connection"
|
69 |
-
"5 - try Plotly to build the graph if error use seaborn"
|
70 |
-
"6 - Use distinct color in the graph"
|
71 |
-
"7 - Display the dataframe in table format"
|
72 |
-
"8 - Never use statment if __name__ == '__main__' "
|
73 |
-
)
|
74 |
-
|
75 |
-
third_prompt = ChatPromptTemplate.from_template(
|
76 |
-
"""Return a JSON object containing the original {question}, extracted SQL query {query}, and extracted corresponding Python code {python_graph} snippet separated by two newlines ('\n')."""
|
77 |
-
)
|
78 |
|
79 |
-
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
)
|
|
|
|
|
|
|
|
|
82 |
|
83 |
-
return [first_prompt, second_prompt, third_prompt, fourth_prompt]
|
84 |
-
|
85 |
-
@staticmethod
|
86 |
-
def generate_anwers() -> list:
|
87 |
-
first_prompt, second_prompt, third_prompt, fourth_prompt = (
|
88 |
-
SqlToPlotlyStreamlit.chat_prompt_template()
|
89 |
-
)
|
90 |
-
|
91 |
-
chain_one = LLMChain(llm=llm, prompt=first_prompt, output_key="query")
|
92 |
-
chain_two = LLMChain(llm=llm, prompt=second_prompt, output_key="python_graph")
|
93 |
-
chain_three = LLMChain(llm=llm, prompt=third_prompt, output_key="json")
|
94 |
-
chain_four = LLMChain(
|
95 |
-
llm=llm, prompt=fourth_prompt, output_key="reformulated_query"
|
96 |
-
)
|
97 |
-
|
98 |
-
return [chain_one, chain_two, chain_three, chain_four]
|
99 |
-
|
100 |
-
@staticmethod
|
101 |
-
def format_python_code_string(code_str: str) -> str:
|
102 |
-
import re
|
103 |
-
|
104 |
-
# Supprimer les espaces inutiles
|
105 |
-
code_str = re.sub(r"^\s+", "", code_str, flags=re.MULTILINE)
|
106 |
-
code_str = re.sub(r"\s+", " ", code_str)
|
107 |
-
code_str = re.sub(r"\s+$", "", code_str, flags=re.MULTILINE)
|
108 |
-
|
109 |
-
# Ajouter des espaces avant et après les opérateurs
|
110 |
-
code_str = re.sub(r"(\+|\-|\*|\/|\=|\(|\))", r" \1 ", code_str)
|
111 |
-
code_str = re.sub(r"(\w+)\s*(\w+)", r"\1 \2", code_str)
|
112 |
-
|
113 |
-
# Ajouter des espaces après les virgules
|
114 |
-
code_str = re.sub(r",\s*", ", ", code_str)
|
115 |
-
|
116 |
-
# Ajouter des espaces après les deux-points
|
117 |
-
code_str = re.sub(r":\s*", ": ", code_str)
|
118 |
-
|
119 |
-
# Ajouter des espaces avant les crochets et accolades
|
120 |
-
code_str = re.sub(r"(\w+)\s*(\{|\[)", r"\1 \2", code_str)
|
121 |
-
code_str = re.sub(r"(\}|\])", r" \1", code_str)
|
122 |
-
|
123 |
-
# Aligner les indentations
|
124 |
-
lines = code_str.split("\n")
|
125 |
-
indentation_levels = []
|
126 |
-
for line in lines:
|
127 |
-
indentation_level = len(line) - len(line.lstrip())
|
128 |
-
indentation_levels.append(indentation_level)
|
129 |
-
max_indentation_level = max(indentation_levels)
|
130 |
-
indentation_spaces = " " * max_indentation_level
|
131 |
-
code_str = "\n".join(indentation_spaces + line.lstrip() for line in lines)
|
132 |
-
|
133 |
-
# Ajouter des espaces entre les mots-clés et les identifiants
|
134 |
-
code_str = re.sub(r"(\b(and|or|not|is|in)\b)\s*(\w+)", r"\1 \3", code_str)
|
135 |
-
|
136 |
-
return code_str
|
137 |
-
|
138 |
-
@staticmethod
|
139 |
-
def code_execution(code_str):
|
140 |
-
|
141 |
-
code_str = SqlToPlotlyStreamlit.format_python_code_string(code_str)
|
142 |
-
# Exécuter le code dans un environnement isolé
|
143 |
-
namespace = {}
|
144 |
-
exec(code_str, namespace)
|
145 |
-
|
146 |
-
# Récupérer la figure du namespace
|
147 |
-
fig = namespace.get("fig")
|
148 |
-
|
149 |
-
if isinstance(fig, go.Figure):
|
150 |
-
|
151 |
-
st.plotly_chart(fig)
|
152 |
-
|
153 |
-
def __init__(self, schema: str, question: str):
|
154 |
-
self.schema = schema
|
155 |
-
self.question = question
|
156 |
-
self.llm = HuggingFaceHub(
|
157 |
-
repo_id="mistralai/MixTraL-8x7B-Instruct-v0.1",
|
158 |
-
model_kwargs={
|
159 |
-
"temperature": 0.001,
|
160 |
-
"max_length": 5000,
|
161 |
-
"max_new_tokens": 1024,
|
162 |
-
},
|
163 |
-
huggingfacehub_api_token=HUGGINGFACE_HUB_API_TOKEN,
|
164 |
-
)
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
chains=list(SqlToPlotlyStreamlit.generate_anwers()),
|
172 |
-
input_variables=["schema", "question"],
|
173 |
-
output_variables=["query", "python_graph", "json"],
|
174 |
-
verbose=True,
|
175 |
-
)
|
176 |
-
result = overall_chain({"schema": self.schema, "question": self.question})
|
177 |
-
self.generated_python_code = (
|
178 |
-
result["json"].split("```python")[-1].split("```")[0].replace("```", "")
|
179 |
-
)
|
180 |
-
# self.code_execution(self.generated_python_code)
|
181 |
-
|
182 |
-
except Exception as e:
|
183 |
-
error_message = f"\nAttempt: An exception occurred while executing the generated code:{e}"
|
184 |
-
st.write(error_message)
|
185 |
-
error_occurred = True
|
186 |
-
|
187 |
-
if not error_occurred:
|
188 |
-
# st.write("## Generated Query")
|
189 |
-
# st.code(result["json"].split("```sql")[-1].split("```")[0].replace("```", ""))
|
190 |
-
st.write("## Generated Python")
|
191 |
-
st.code(self.generated_python_code)
|
192 |
-
|
193 |
-
|
194 |
-
def main():
|
195 |
-
st.set_page_config(layout="wide")
|
196 |
-
st.title("SQL Query Visualizer")
|
197 |
-
|
198 |
-
schema = SCHEMA_STR
|
199 |
-
question = st.text_input(
|
200 |
-
"Enter Question:", "what is the total of zones for each category ?"
|
201 |
-
)
|
202 |
-
if st.button("Run"):
|
203 |
-
obj = SqlToPlotlyStreamlit(schema, question)
|
204 |
-
obj.execute_overall_flow()
|
205 |
-
exec(obj.generated_python_code)
|
206 |
|
207 |
|
|
|
208 |
if __name__ == "__main__":
|
209 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
+
import hashlib
|
3 |
+
from AI_generator import SCHEMA_STR, SqlToPlotlyStreamlit
|
4 |
+
from dashboard import dashboard
|
5 |
+
from dotenv import load_dotenv
|
6 |
import os
|
7 |
+
import hashlib
|
8 |
|
9 |
load_dotenv()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
+
username = os.getenv("USERNAME")
|
12 |
+
password = os.getenv("PASSWORD")
|
13 |
+
|
14 |
+
|
15 |
+
st.sidebar.markdown("""
|
16 |
+
<footer style="position: fixed; bottom: 0; text-align: center; background-color: #002b36; border-top: 1px solid #ddd;">
|
17 |
+
© 2023 LPO. All rights reserved.
|
18 |
+
</footer>
|
19 |
+
""", unsafe_allow_html=True)
|
20 |
+
|
21 |
+
|
22 |
+
# Create an authentication function
|
23 |
+
def authenticate(username, password):
|
24 |
+
|
25 |
+
users = {
|
26 |
+
username: hashlib.sha256(password.encode()).hexdigest()
|
27 |
+
}
|
28 |
+
hashed_password = hashlib.sha256(password.encode()).hexdigest()
|
29 |
+
if username in users and users[username] == hashed_password:
|
30 |
+
return True
|
31 |
+
return False
|
32 |
+
|
33 |
+
|
34 |
+
# Create a login form
|
35 |
+
@st.cache_resource()
|
36 |
+
def login_cache():
|
37 |
+
return {"authenticated": False}
|
38 |
+
|
39 |
+
|
40 |
+
def login():
|
41 |
+
st.title("Login")
|
42 |
+
form = st.form("login_form")
|
43 |
+
username = form.text_input("Username")
|
44 |
+
password = form.text_input("Password", type="password")
|
45 |
+
if form.form_submit_button("Login"):
|
46 |
+
if authenticate(username, password):
|
47 |
+
login_cache()["authenticated"] = True
|
48 |
+
st.experimental_rerun()
|
49 |
+
else:
|
50 |
+
st.error("Invalid username or password")
|
51 |
+
|
52 |
+
|
53 |
+
# Protect your app content
|
54 |
+
def home():
|
55 |
+
if not login_cache()["authenticated"]:
|
56 |
+
login()
|
57 |
+
else:
|
58 |
+
# Your app content here
|
59 |
+
st.title("SQL Query Visualizer")
|
60 |
+
schema = SCHEMA_STR
|
61 |
+
question = st.text_input(
|
62 |
+
"Enter Question:", "what is the total of zones for each category?"
|
63 |
)
|
64 |
+
if st.button("Run"):
|
65 |
+
obj = SqlToPlotlyStreamlit(schema, question)
|
66 |
+
obj.execute_overall_flow()
|
67 |
+
exec(obj.generated_python_code)
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
|
70 |
+
def page2():
|
71 |
+
if not login_cache()["authenticated"]:
|
72 |
+
login()
|
73 |
+
else:
|
74 |
+
dashboard()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
|
77 |
+
# Run the app
|
78 |
if __name__ == "__main__":
|
79 |
+
pages = {"AI Generator": home, "Analytic Dashboard": page2}
|
80 |
+
st.sidebar.markdown("<h2> Select a page </h2>", unsafe_allow_html=True)
|
81 |
+
page = st.sidebar.selectbox("", list(pages.keys()))
|
82 |
+
pages[page]()
|
dashboard.py
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import streamlit as st
|
3 |
+
import sqlite3
|
4 |
+
import plotly.express as px
|
5 |
+
|
6 |
+
# Database connection
|
7 |
+
conn = sqlite3.connect("data/biodiv_sports.db")
|
8 |
+
|
9 |
+
# Queries
|
10 |
+
query_zone_catg_prop = """
|
11 |
+
SELECT
|
12 |
+
CASE
|
13 |
+
WHEN species_id IS NOT NULL THEN 'Espèces'
|
14 |
+
ELSE 'Réglementaire'
|
15 |
+
END AS zone_category,
|
16 |
+
ROUND(COUNT(DISTINCT id)*1.0/(
|
17 |
+
SELECT
|
18 |
+
COUNT(DISTINCT id)
|
19 |
+
FROM
|
20 |
+
sensitive_areas
|
21 |
+
), 2) AS proportion
|
22 |
+
FROM
|
23 |
+
sensitive_areas
|
24 |
+
GROUP BY
|
25 |
+
zone_category;
|
26 |
+
"""
|
27 |
+
|
28 |
+
query_mon_wise_prop = """
|
29 |
+
SELECT
|
30 |
+
months,
|
31 |
+
species_id,
|
32 |
+
ROUND(COUNT(DISTINCT id)*1.0/(
|
33 |
+
SELECT
|
34 |
+
COUNT(DISTINCT id)
|
35 |
+
FROM
|
36 |
+
sensitive_areas
|
37 |
+
), 2) AS proportion
|
38 |
+
FROM
|
39 |
+
sensitive_areas
|
40 |
+
GROUP BY
|
41 |
+
months
|
42 |
+
ORDER BY
|
43 |
+
months;
|
44 |
+
"""
|
45 |
+
|
46 |
+
query_practice_mon_wise = """
|
47 |
+
SELECT
|
48 |
+
practices,
|
49 |
+
months,
|
50 |
+
species_id,
|
51 |
+
COUNT(DISTINCT id) AS nombre_zone
|
52 |
+
FROM
|
53 |
+
sensitive_areas
|
54 |
+
GROUP BY
|
55 |
+
1,
|
56 |
+
2,
|
57 |
+
3;
|
58 |
+
"""
|
59 |
+
|
60 |
+
query_zone_per_species = """
|
61 |
+
SELECT
|
62 |
+
name,
|
63 |
+
COUNT(DISTINCT id)/12.0 AS number_of_zones
|
64 |
+
FROM
|
65 |
+
sensitive_areas
|
66 |
+
WHERE
|
67 |
+
species_id IS NOT NULL
|
68 |
+
GROUP BY
|
69 |
+
1;
|
70 |
+
"""
|
71 |
+
|
72 |
+
|
73 |
+
def dashboard():
|
74 |
+
conn = sqlite3.connect("data/biodiv_sports.db")
|
75 |
+
|
76 |
+
# Read query results into Pandas DataFrames
|
77 |
+
df_zone_catg_prop = pd.read_sql_query(query_zone_catg_prop, conn)
|
78 |
+
df_mon_wise_prop = pd.read_sql_query(query_mon_wise_prop, conn)
|
79 |
+
df_practice_mon_wise = pd.read_sql_query(query_practice_mon_wise, conn)
|
80 |
+
df_zone_per_species = pd.read_sql_query(query_zone_per_species, conn)
|
81 |
+
|
82 |
+
# Map month names to their corresponding numbers
|
83 |
+
MONTHS = [
|
84 |
+
"janvier",
|
85 |
+
"fevrier",
|
86 |
+
"mars",
|
87 |
+
"avril",
|
88 |
+
"mai",
|
89 |
+
"juin",
|
90 |
+
"juillet",
|
91 |
+
"août",
|
92 |
+
"septembre",
|
93 |
+
"octobre",
|
94 |
+
"novembre",
|
95 |
+
"decembre",
|
96 |
+
]
|
97 |
+
MONTH_MAPPING = {k: v + 1 for v, k in enumerate(MONTHS)}
|
98 |
+
|
99 |
+
# Add a numeric_months column based on MONTH_MAPPING
|
100 |
+
df_practice_mon_wise["numeric_months"] = df_practice_mon_wise["months"].map(
|
101 |
+
MONTH_MAPPING
|
102 |
+
)
|
103 |
+
df_mon_wise_prop["numeric_months"] = df_mon_wise_prop["months"].map(MONTH_MAPPING)
|
104 |
+
|
105 |
+
# Sort by numeric_months and reset index before dropping it
|
106 |
+
df_practice_mon_wise = df_practice_mon_wise.sort_values(
|
107 |
+
["numeric_months", "species_id"]
|
108 |
+
).reset_index(drop=True)
|
109 |
+
df_practice_mon_wise.drop("numeric_months", axis=1, inplace=True)
|
110 |
+
|
111 |
+
df_mon_wise_prop = df_mon_wise_prop.sort_values(
|
112 |
+
["numeric_months", "proportion"]
|
113 |
+
).reset_index(drop=True)
|
114 |
+
df_mon_wise_prop.drop("numeric_months", axis=1, inplace=True)
|
115 |
+
|
116 |
+
st.markdown(
|
117 |
+
"""<h1 style='text-align: center'>Visualization of Biodiv-Sport
|
118 |
+
Database</h1>""",
|
119 |
+
unsafe_allow_html=True,
|
120 |
+
)
|
121 |
+
|
122 |
+
# Charts
|
123 |
+
fig_pie = px.pie(df_zone_catg_prop, values="proportion", names="zone_category")
|
124 |
+
fig_pie.update_layout(
|
125 |
+
paper_bgcolor="#002b36",
|
126 |
+
plot_bgcolor="#586e75",
|
127 |
+
font_color="#fafafa",
|
128 |
+
title={"text": "<b>Proportions of Zone Categories</b>", "x": 0.0, "y": 1},
|
129 |
+
)
|
130 |
+
|
131 |
+
fig_bar = px.bar(df_zone_per_species, x="name", y="number_of_zones")
|
132 |
+
fig_bar.update_layout(
|
133 |
+
paper_bgcolor="#002b36",
|
134 |
+
plot_bgcolor="#586e75",
|
135 |
+
font_color="#fafafa",
|
136 |
+
title={"text": "<b>Total Number of Zones Per Species</b>", "x": 0.0, "y": 1},
|
137 |
+
)
|
138 |
+
|
139 |
+
fig_line = px.line(df_mon_wise_prop, x="months", y="proportion", color="species_id")
|
140 |
+
fig_line.update_layout(
|
141 |
+
paper_bgcolor="#002b36",
|
142 |
+
plot_bgcolor="#586e75",
|
143 |
+
font_color="#fafafa",
|
144 |
+
title={
|
145 |
+
"text": "<b>Monthly Proportion Distribution Across Year</b>",
|
146 |
+
"x": 0.0,
|
147 |
+
"y": 1,
|
148 |
+
},
|
149 |
+
)
|
150 |
+
|
151 |
+
fig_heatmap = px.density_heatmap(
|
152 |
+
df_practice_mon_wise,
|
153 |
+
x="months",
|
154 |
+
y="practices",
|
155 |
+
z="nombre_zone",
|
156 |
+
color_continuous_scale="OrRd",
|
157 |
+
nbinsx=12, # Set the number of bins in the x direction (months)
|
158 |
+
nbinsy=10,
|
159 |
+
)
|
160 |
+
fig_heatmap.update_layout(
|
161 |
+
xaxis={
|
162 |
+
"tickmode": "array",
|
163 |
+
"tickvals": list(MONTH_MAPPING.keys()),
|
164 |
+
},
|
165 |
+
paper_bgcolor="#002b36",
|
166 |
+
plot_bgcolor="#586e75",
|
167 |
+
font_color="#fafafa",
|
168 |
+
title={
|
169 |
+
"text": "Number of Zones According to Activity Practiced and By Month",
|
170 |
+
"x": 0.0,
|
171 |
+
"y": 1.0,
|
172 |
+
},
|
173 |
+
)
|
174 |
+
|
175 |
+
st.plotly_chart(fig_pie)
|
176 |
+
|
177 |
+
st.plotly_chart(fig_bar)
|
178 |
+
|
179 |
+
st.plotly_chart(fig_line)
|
180 |
+
|
181 |
+
st.plotly_chart(fig_heatmap)
|
pages/dashboard.py
DELETED
@@ -1,177 +0,0 @@
|
|
1 |
-
import pandas as pd
|
2 |
-
import streamlit as st
|
3 |
-
import sqlite3
|
4 |
-
import plotly.express as px
|
5 |
-
|
6 |
-
# Database connection
|
7 |
-
conn = sqlite3.connect("data/biodiv_sports.db")
|
8 |
-
|
9 |
-
# Queries
|
10 |
-
query_zone_catg_prop = """
|
11 |
-
SELECT
|
12 |
-
CASE
|
13 |
-
WHEN species_id IS NOT NULL THEN 'Espèces'
|
14 |
-
ELSE 'Réglementaire'
|
15 |
-
END AS zone_category,
|
16 |
-
ROUND(COUNT(DISTINCT id)*1.0/(
|
17 |
-
SELECT
|
18 |
-
COUNT(DISTINCT id)
|
19 |
-
FROM
|
20 |
-
sensitive_areas
|
21 |
-
), 2) AS proportion
|
22 |
-
FROM
|
23 |
-
sensitive_areas
|
24 |
-
GROUP BY
|
25 |
-
zone_category;
|
26 |
-
"""
|
27 |
-
|
28 |
-
query_mon_wise_prop = """
|
29 |
-
SELECT
|
30 |
-
months,
|
31 |
-
species_id,
|
32 |
-
ROUND(COUNT(DISTINCT id)*1.0/(
|
33 |
-
SELECT
|
34 |
-
COUNT(DISTINCT id)
|
35 |
-
FROM
|
36 |
-
sensitive_areas
|
37 |
-
), 2) AS proportion
|
38 |
-
FROM
|
39 |
-
sensitive_areas
|
40 |
-
GROUP BY
|
41 |
-
months
|
42 |
-
ORDER BY
|
43 |
-
months;
|
44 |
-
"""
|
45 |
-
|
46 |
-
query_practice_mon_wise = """
|
47 |
-
SELECT
|
48 |
-
practices,
|
49 |
-
months,
|
50 |
-
species_id,
|
51 |
-
COUNT(DISTINCT id) AS nombre_zone
|
52 |
-
FROM
|
53 |
-
sensitive_areas
|
54 |
-
GROUP BY
|
55 |
-
1,
|
56 |
-
2,
|
57 |
-
3;
|
58 |
-
"""
|
59 |
-
|
60 |
-
query_zone_per_species = """
|
61 |
-
SELECT
|
62 |
-
name,
|
63 |
-
COUNT(DISTINCT id) AS number_of_zones
|
64 |
-
FROM
|
65 |
-
sensitive_areas
|
66 |
-
WHERE
|
67 |
-
species_id IS NOT NULL
|
68 |
-
GROUP BY
|
69 |
-
1;
|
70 |
-
"""
|
71 |
-
|
72 |
-
# Read query results into Pandas DataFrames
|
73 |
-
df_zone_catg_prop = pd.read_sql_query(query_zone_catg_prop, conn)
|
74 |
-
df_mon_wise_prop = pd.read_sql_query(query_mon_wise_prop, conn)
|
75 |
-
df_practice_mon_wise = pd.read_sql_query(query_practice_mon_wise, conn)
|
76 |
-
df_zone_per_species = pd.read_sql_query(query_zone_per_species, conn)
|
77 |
-
|
78 |
-
# Map month names to their corresponding numbers
|
79 |
-
MONTHS = ['janvier', 'fevrier', 'mars', 'avril', 'mai', 'juin',
|
80 |
-
'juillet', 'août', 'septembre', 'octobre', 'novembre', 'decembre']
|
81 |
-
MONTH_MAPPING = {k: v+1 for v, k in enumerate(MONTHS)}
|
82 |
-
|
83 |
-
# Add a numeric_months column based on MONTH_MAPPING
|
84 |
-
df_practice_mon_wise['numeric_months'] = df_practice_mon_wise['months'].map(
|
85 |
-
MONTH_MAPPING
|
86 |
-
)
|
87 |
-
df_mon_wise_prop['numeric_months'] = df_mon_wise_prop['months'].map(
|
88 |
-
MONTH_MAPPING
|
89 |
-
)
|
90 |
-
|
91 |
-
# Sort by numeric_months and reset index before dropping it
|
92 |
-
df_practice_mon_wise = df_practice_mon_wise.sort_values(['numeric_months',
|
93 |
-
'species_id']
|
94 |
-
).reset_index(
|
95 |
-
drop=True
|
96 |
-
)
|
97 |
-
df_practice_mon_wise.drop('numeric_months', axis=1, inplace=True)
|
98 |
-
|
99 |
-
df_mon_wise_prop = df_mon_wise_prop.sort_values(['numeric_months',
|
100 |
-
'proportion']
|
101 |
-
).reset_index(
|
102 |
-
drop=True
|
103 |
-
)
|
104 |
-
df_mon_wise_prop.drop('numeric_months', axis=1, inplace=True)
|
105 |
-
|
106 |
-
|
107 |
-
st.markdown("""<h1 style='text-align: center'>Visualization of Biodiv-Sport
|
108 |
-
Database</h1>""", unsafe_allow_html=True)
|
109 |
-
|
110 |
-
# Charts
|
111 |
-
fig_pie = px.pie(df_zone_catg_prop, values="proportion", names="zone_category")
|
112 |
-
fig_pie.update_layout(
|
113 |
-
paper_bgcolor="#002b36",
|
114 |
-
plot_bgcolor="#586e75",
|
115 |
-
font_color="#fafafa",
|
116 |
-
title={
|
117 |
-
"text": "<b>Proportions of Zone Categories</b>",
|
118 |
-
"x": 0.,
|
119 |
-
"y": 1
|
120 |
-
})
|
121 |
-
|
122 |
-
fig_bar = px.bar(df_zone_per_species, x="name", y="number_of_zones")
|
123 |
-
fig_bar.update_layout(
|
124 |
-
paper_bgcolor="#002b36",
|
125 |
-
plot_bgcolor="#586e75",
|
126 |
-
font_color="#fafafa",
|
127 |
-
title={
|
128 |
-
"text": "<b>Total Number of Zones Per Species</b>",
|
129 |
-
"x": 0.,
|
130 |
-
"y": 1
|
131 |
-
})
|
132 |
-
|
133 |
-
fig_line = px.line(df_mon_wise_prop, x="months",
|
134 |
-
y="proportion",
|
135 |
-
color="species_id")
|
136 |
-
fig_line.update_layout(
|
137 |
-
paper_bgcolor="#002b36",
|
138 |
-
plot_bgcolor="#586e75",
|
139 |
-
font_color="#fafafa",
|
140 |
-
title={
|
141 |
-
"text": "<b>Monthly Proportion Distribution Across Year</b>",
|
142 |
-
"x": 0.,
|
143 |
-
"y": 1
|
144 |
-
})
|
145 |
-
|
146 |
-
|
147 |
-
fig_heatmap = px.density_heatmap(df_practice_mon_wise,
|
148 |
-
x="months",
|
149 |
-
y="practices",
|
150 |
-
z="nombre_zone",
|
151 |
-
color_continuous_scale="OrRd",
|
152 |
-
nbinsx=12, # Set the number of bins in the x direction (months)
|
153 |
-
nbinsy=10
|
154 |
-
)
|
155 |
-
fig_heatmap.update_layout(
|
156 |
-
xaxis={
|
157 |
-
"tickmode": "array",
|
158 |
-
"tickvals": list(MONTH_MAPPING.keys()),
|
159 |
-
},
|
160 |
-
paper_bgcolor="#002b36",
|
161 |
-
plot_bgcolor="#586e75",
|
162 |
-
font_color="#fafafa",
|
163 |
-
title={
|
164 |
-
"text": "Number of Zones According to Activity Practiced and By Month",
|
165 |
-
"x": 0.,
|
166 |
-
"y": 1.0
|
167 |
-
}
|
168 |
-
)
|
169 |
-
|
170 |
-
st.plotly_chart(fig_pie)
|
171 |
-
|
172 |
-
st.plotly_chart(fig_bar)
|
173 |
-
|
174 |
-
|
175 |
-
st.plotly_chart(fig_line)
|
176 |
-
|
177 |
-
st.plotly_chart(fig_heatmap)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setup.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from setuptools import setup, find_packages
|
2 |
+
|
3 |
+
setup(name="LPO_AI", packages=find_packages())
|