danidanidani commited on
Commit
08ec439
1 Parent(s): ff9b6c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +350 -144
app.py CHANGED
@@ -5,7 +5,8 @@ import os
5
  import time
6
  import math
7
  import streamlit as st
8
- #from streamlit_chat import message
 
9
  from streamlit_extras.colored_header import colored_header
10
  from streamlit_extras.add_vertical_space import add_vertical_space
11
  from PIL import Image
@@ -18,45 +19,51 @@ from src.frontend.visualizations import *
18
 
19
  # import compatibilities matrix
20
  # make plant_compatibility.csv into a matrix. it currently has indexes as rows and columns for plant names and then compatibility values as the values
21
- st.session_state.raw_plant_compatibility = pd.read_csv('src/data/plant_compatibility.csv', index_col=0)
 
 
22
  # fill NaN values with 0
23
- st.session_state.raw_plant_compatibility = st.session_state.raw_plant_compatibility.fillna(0)
 
 
24
  # get list of plants
25
  st.session_state.plant_list = st.session_state.raw_plant_compatibility.index.tolist()
26
 
27
  # set version
28
- st.session_state.demo_lite = True
 
 
29
 
30
  # setup keys and api info
31
  # OPENAI_API_KEY = st.secrets["OPENAI_API_KEY"]
32
  # os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
33
 
34
 
35
-
36
- #chat = ChatOpenAI()
37
 
38
 
39
  # UI page config
40
  st.set_page_config(
41
- #page_title="GRDN.AI",
42
  page_icon="🌱",
43
  layout="wide",
44
  initial_sidebar_state="expanded",
45
  )
46
 
 
47
  # Function to display chat message with an icon
48
  def chat_message(message, is_user=False):
49
  if is_user:
50
- icon = Image.open("src/assets/cool.png")
51
  side = "left"
52
  else:
53
- icon = Image.open("src/assets/bot.png")
54
  side = "right"
55
-
56
  chat_container = st.container()
57
 
58
  with chat_container:
59
- col1, col2, col3, col4= st.columns([1,7,7,1])
60
 
61
  with col1:
62
  if is_user == True:
@@ -64,21 +71,32 @@ def chat_message(message, is_user=False):
64
 
65
  with col2:
66
  if is_user == True:
67
- st.markdown(f'<div style="text-align: {side};">{message}</div>', unsafe_allow_html=True)
 
 
 
68
  with col3:
69
  if is_user == False:
70
- st.markdown(f'<div style="text-align: {side};">{message}</div>', unsafe_allow_html=True)
 
 
 
71
  with col4:
72
  if is_user == False:
73
  st.image(icon, width=50)
74
 
75
 
76
-
77
-
78
- st.image ("src/assets/logo_title_transparent.png", caption=None, use_column_width=None, clamp=False, channels='RGB', output_format='auto')
 
 
 
 
 
79
 
80
  st.write("AI and optimization powered companion gardening")
81
- colored_header(label='', description='', color_name='green-30')
82
 
83
  # Sidebar
84
  # st.sidebar.title("Navigation")
@@ -90,6 +108,7 @@ with st.sidebar:
90
  # Sidebar
91
  st.sidebar.title("Navigation")
92
 
 
93
  # Define the page options
94
  pages = ["Garden Optimization", "About"]
95
 
@@ -99,7 +118,9 @@ page = st.sidebar.selectbox("Select a page:", pages)
99
 
100
  if page == "Garden Optimization":
101
  st.sidebar.subheader("Companion Gardening")
102
- st.write("GRDN is a companion gardening app that helps you plan your garden and maximize your harvest. It uses optimization algorithms and AI to predict the best plants to grow together and optimization algorithms to optimize how you build your garden.")
 
 
103
  st.write("This app is currently in beta. Please report any bugs.")
104
  companion_planting_info = """
105
  Key Benefits
@@ -112,15 +133,44 @@ if page == "Garden Optimization":
112
  """
113
 
114
  st.sidebar.markdown(companion_planting_info)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  # Set the initial value of user_name
116
- if 'user_name' not in st.session_state:
117
- st.session_state.user_name = ''
118
  # add in some vertical space
119
  add_vertical_space(3)
120
  # Display the welcome message
121
- st.title('Let\'s get started! Decide on your garden parameters')
122
-
123
-
124
  # add in some vertical space
125
  add_vertical_space(2)
126
 
@@ -129,14 +179,20 @@ if page == "Garden Optimization":
129
 
130
  with container1:
131
  # Modify the user_name variable based on user input
132
- if st.session_state['user_name'] == '':
133
- col1, col2, col3= st.columns([1,2,1])
134
  with col1:
135
- st.session_state['user_name_input'] = st.text_input('Enter your name', st.session_state.user_name)
136
- if 'user_name_input' in st.session_state:
 
 
137
  st.session_state.user_name = st.session_state.user_name_input
138
- if st.session_state.user_name != '':
139
- st.write('Hello ' + st.session_state['user_name'] + '! Let\'s optimize your garden. 🌱')
 
 
 
 
140
 
141
  # # add in some vertical space
142
  add_vertical_space(2)
@@ -145,174 +201,286 @@ if page == "Garden Optimization":
145
  print("____________________")
146
  print("start of session")
147
 
148
- col1a, col2a= st.columns([1,2])
149
  enable_max_species = False
150
  enable_min_species = False
151
 
152
-
153
  # make a form to get the plant list from the user
154
  with col1a:
155
- with st.form(key = "plant_list_form"):
156
- input_plants_raw = st.multiselect('plants', st.session_state.plant_list)
157
- submit_button = st.form_submit_button(label='Submit Plant List')
 
 
158
  if submit_button:
159
- st.session_state['input_plants_raw'] = input_plants_raw
160
  st.session_state.submitted_plant_list = True
161
 
162
  # add in some vertical space
163
  add_vertical_space(1)
164
 
165
  with col2a:
166
- col1, col2, col3= st.columns([1,1,1])
167
- if 'input_plants_raw' in st.session_state:
168
  print("BP1")
169
  # first question is what plants would you like to plant
170
  plants_response = st.session_state.input_plants_raw
171
 
172
  # Initialize session state variables if they don't exist
173
- if 'n_plant_beds' not in st.session_state:
174
- st.session_state['n_plant_beds'] = 1
175
 
176
- if 'min_species' not in st.session_state:
177
- st.session_state['min_species'] = 1
178
 
179
- if 'max_species' not in st.session_state:
180
- st.session_state['max_species'] = 2
181
 
182
  # Number of plant beds input
183
  with col1:
184
- n_plant_beds = st.number_input('Number of plant beds \n', min_value=1, max_value=20, value=st.session_state.n_plant_beds, step=1)
 
 
 
 
 
 
185
  st.session_state.n_plant_beds = n_plant_beds
186
  with col2:
187
  # Minimum species per plant bed input
188
- min_species = st.number_input('Minimum number of species per plant bed',
189
- min_value=1,
190
- max_value=len(st.session_state.input_plants_raw),
191
- value=st.session_state.min_species,
192
- step=1)
 
 
193
  st.session_state.min_species = min_species
194
 
195
  # Maximum species per plant bed input
196
  # It will be enabled only if min_species is set
197
  enable_max_species = st.session_state.min_species > 0
198
  with col3:
199
- max_species = st.number_input('Maximum number of species per plant bed',
200
- min_value=st.session_state.min_species,
201
- max_value=len(st.session_state.input_plants_raw),
202
- value=max(st.session_state.min_species, st.session_state.max_species),
203
- step=1,
204
- disabled=not enable_max_species)
 
 
 
 
 
205
  if enable_max_species:
206
  st.session_state.max_species = max_species
207
 
208
  # extract the compatibility matrix from the user's input
209
- if 'extracted_mat' not in st.session_state:
210
  valid = False
211
- if 'submitted_plant_list' in st.session_state and st.session_state.submitted_plant_list:
 
 
 
212
  # check if the user's input is valid
213
  # min species per bed must be less than or equal to max species per bed
214
- if (st.session_state.min_species <= st.session_state.max_species
215
- ) and (
216
- # max species per bed must be less than or equal to the number of plants
217
- st.session_state.max_species <= len(st.session_state.input_plants_raw)
218
- ) and (
219
- # max species per bed must be greater than or equal to the min species per bed
220
- st.session_state.max_species >= st.session_state.min_species
221
- ) and (
222
- # min species per bed must be less than or equal to the number of plants
223
- st.session_state.min_species <= len(st.session_state.input_plants_raw)
224
- ) and (
225
- # number of plant beds multiplied by min species per bed must be less than or equal to the number of plants
226
- len(st.session_state.input_plants_raw) >= st.session_state.n_plant_beds * st.session_state.min_species
227
- ) and (
228
- # number of plant beds multiplied by max species per bed must be greater than or equal to the number of plants
229
- len(st.session_state.input_plants_raw) <= st.session_state.n_plant_beds * st.session_state.max_species
230
- ):
231
- valid = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  else:
233
  # add a warning message
234
- st.warning('Please enter valid parameters. The minimum number of species per plant bed must be less than or equal to the maximum number of species per plant bed. The maximum number of species per plant bed must be less than or equal to the number of plants. The maximum number of species per plant bed must be greater than or equal to the minimum number of species per plant bed. The minimum number of species per plant bed must be less than or equal to the number of plants. The number of plant beds multiplied by the minimum number of species per plant bed must be less than or equal to the number of plants. The number of plant beds multiplied by the maximum number of species per plant bed must be greater than or equal to the number of plants.')
 
 
235
 
236
  if valid:
237
  # add in some vertical space
238
  add_vertical_space(2)
239
- if st.button('Generate Companion Plant Compatibility Matrix'):
240
- with st.spinner('generating companion plant compatibility matrix...'):
241
- st.session_state['generating_mat'] = True
 
 
 
 
242
  # now get compatibility matrix for companion planting
243
  time.sleep(1)
244
- extracted_mat, full_mat, plant_index_mapping= get_compatibility_matrix_2(st.session_state.input_plants_raw)
 
 
 
 
 
 
245
  print(extracted_mat)
246
  st.session_state.extracted_mat = extracted_mat
247
  st.session_state.full_mat = full_mat
248
- st.session_state.plant_index_mapping = plant_index_mapping
 
 
249
  # add in some vertical space
250
  add_vertical_space(4)
251
 
252
  # display the companion plant compatibility matrix
253
- if 'extracted_mat' in st.session_state:
254
  # add a title for the next section- companion plant compatibility matrix based on user input
255
- st.title('Your companion plant compatibility matrix')
256
  # make a container for this section
257
  container2 = st.container(border=True)
258
  with container2:
259
- col1, col2 = st.columns([8,4])
260
  # display the companion plant compatibility matrix
261
  with col2:
262
  st.write("Here is your companion plant compatibility matrix:")
263
  with st.expander("Show ugly compatibility matrix of 1's 0's and -1's"):
264
  st.write(st.session_state.extracted_mat)
265
  with col1:
266
- st.write("Here is a network visualization of your companion plant compatibility matrix. It is color coded to show which plants are companions (green), antagonists (violetred), or neutral (grey).")
267
- plot_compatibility_with_agraph(st.session_state.input_plants_raw, st.session_state.full_mat)
268
- st.session_state['got_mat'] = True
269
-
270
- if 'got_mat' in st.session_state:
 
 
 
 
271
  # add in some vertical space
272
- add_vertical_space(4)
273
  # make a container for this section
274
  container3 = st.container(border=True)
275
- with container3:
276
- st.title('Optimizing companion planting with the genetic algorithm and AI')
277
- st.write("Now that we have your companion plant compatibility matrix, we can use optimization to maximize your harvest. We will use a genetic algorithm to determine the best way to plant your garden. The genetic algorithm will determine the best way to plant your garden by maximizing the number of companion plants and minimizing the number of antagonists.")
278
- st.write("Set the parameters for the genetic algorithm. Here is more info for your reference:")
279
- with st.form(key = "genetic_algorithm_form"):
280
- col1, col2= st.columns([1,1])
 
 
 
 
 
 
281
  with col2:
282
- with st.expander("Show more information about the genetic algorithm parameters"):
 
 
283
  st.subheader("Plant Optimization Heuristic Performance")
284
- st.write("The genetic algorithm parameters impact the performance of the plant optimization heuristic in the following ways:")
285
- st.markdown("- **Population Size**: A larger population size allows for a more diverse exploration of the solution space. However, it also increases computational complexity.")
286
- st.markdown("- **Number of Generations**: Increasing the number of generations provides more opportunities for the algorithm to converge towards an optimal solution.")
287
- st.markdown("- **Tournament Size**: A larger tournament size promotes stronger selection pressure and can lead to faster convergence, but it may also increase the risk of premature convergence.")
288
- st.markdown("- **Crossover Rate**: A higher crossover rate increases the exploration capability by creating diverse offspring, potentially improving the algorithm's ability to escape local optima.")
289
- st.markdown("- **Mutation Rate**: Mutation introduces random changes in individuals, helping to maintain diversity in the population and preventing premature convergence.")
 
 
 
 
 
 
 
 
 
 
 
 
290
  # seed population rate
291
- st.markdown("- **Seed Population Rate**: The seed population rate is the percentage of the population that is generated based on the LLM's interpretation of compatibility. The remaining percentage of the population is generated randomly. A higher seed population rate increases the likelihood that the genetic algorithm will converge towards a solution that is compatible.")
 
 
292
  # Run the Genetic Algorithm
293
  with col1:
294
  st.subheader("Genetic Algorithm Parameters")
295
- st.write("These parameters control the behavior of the genetic algorithm.")
 
 
296
 
297
  # Genetic Algorithm parameters
298
- st.session_state.population_size = st.slider("Population Size", min_value=100, max_value=1000, value=500,
299
- help="The number of individuals in each generation of the genetic algorithm.")
300
- st.session_state.num_generations = st.slider("Number of Generations", min_value=100, max_value=1000, value=250,
301
- help="The total number of generations to evolve through.")
302
- st.session_state.tournament_size = st.slider("Tournament Size", min_value=5, max_value=20, value=10,
303
- help="The number of individuals competing in each tournament selection round.")
304
- st.session_state.crossover_rate = st.slider("Crossover Rate", min_value=0.1, max_value=1.0, step=0.1, value=0.8,
305
- help="The probability of two individuals undergoing crossover to create offspring.")
306
- st.session_state.mutation_rate = st.slider("Mutation Rate", min_value=0.01, max_value=0.9, step=0.01, value=0.3,
307
- help="The probability of an individual undergoing mutation.")
308
- st.session_state.seed_population_rate = st.slider("Seed Population Rate", min_value=0.0, max_value=.02, step=0.001, value=0.08,
309
- help="The percentage of the population that is generated based on the LLM's interpretation of compatibility. The remaining percentage of the population is generated randomly.")
310
-
311
- #
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  # Run the genetic algorithm
313
- if st.form_submit_button(label='Run Genetic Algorithm'):
314
- with st.spinner('running genetic algorithm... this may take a minute'):
315
- grouping = genetic_algorithm_plants()
 
 
 
 
316
  st.session_state.grouping = grouping
317
 
318
  # visualize the groupings
@@ -323,44 +491,77 @@ if page == "Garden Optimization":
323
  st.header("Here are the optimized groupings of plants for your garden")
324
  container4 = st.container(border=True)
325
  with container4:
326
- if 'grouping' in st.session_state:
327
  visualize_groupings()
328
- if 'best_fitness' in st.session_state:
329
  # embed score.png
330
- col1b, col2b = st.columns([2,11])
331
  with col1b:
332
- st.image("src/assets/score.png", caption=None, width = 160, use_column_width=None, clamp=False, channels='RGB', output_format='auto')
 
 
 
 
 
 
 
 
333
  with col2b:
334
- #st.write("\n")
335
  st.header("| " + str(st.session_state.best_fitness))
336
- st.write("The genetic algorithm converged towards a solution with a fitness score of " + str(st.session_state.best_fitness) + ".")
 
 
 
 
337
  # Add vertical space
338
  add_vertical_space(4)
339
  # show plant care tips
340
  st.header("Plant care tips")
341
- with st.spinner('generating plant care tips...'):
342
- st.write("Here are some plant care tips for your plants. Good luck!")
 
 
343
  if st.session_state.demo_lite:
344
- st.session_state.plant_care_tips = "Plant care tips are not available in this lite demo version but will be available in the future! Only the local version of this app has full functionality at this time."
345
  else:
346
- #if 'plant_care_tips' not in st.session_state:
347
- st.session_state.plant_care_tips = get_plant_care_tips(st.session_state.input_plants_raw)
 
 
 
 
348
  styled_text = f'<div style="background-color: #2d5a59; color: white; padding: 10px; border-radius: 5px;">{st.session_state.plant_care_tips}</div>'
349
  st.write(styled_text, unsafe_allow_html=True)
350
 
351
 
 
 
 
 
 
 
 
 
 
352
 
 
353
 
 
354
 
 
 
 
 
 
 
 
 
355
 
356
- if page == "About":
357
- st.sidebar.subheader("About")
358
- st.sidebar.write("GRDN is a companion gardening app that helps you plan your garden and maximize your harvest. It uses AI to predict the best plants to grow together and optimization algorithms to optimize how you build your garden.")
359
- st.sidebar.write("Companion gardening is the practice of planting different plants together to maximize their growth. Companion gardening can help to increase the yield of your garden, improve the health of your plants, and reduce the need for pesticides.")
360
- st.write("This app is currently in beta. Please report any bugs to the team.")
361
 
362
- col1, col2= st.columns([1,1])
363
- with col1:
364
  st.subheader("Contact Information")
365
  st.write("Author: Danielle Heymann")
366
  st.write("Email: dheymann314@gmail.com")
@@ -368,7 +569,8 @@ if page == "About":
368
  with col2:
369
  st.subheader("Software, data, and libraries used")
370
  st.write("Libraries and Software")
371
- st.markdown("""
 
372
  - Python
373
  - streamlit
374
  - openai
@@ -380,12 +582,16 @@ if page == "About":
380
  - streamlit_chat
381
  - github copilot
382
  - Llama2
 
383
  - HuggingFace
384
  - LlamaIndex
385
  - chatGPT
386
  - GPT family of models
387
  - DALL·E 3 (in preprocessing script for image generation)
388
- """)
389
- st.write("Data sources in addition to what LLMs were trained on: \n https://waldenlabs.com/the-ultimate-companion-planting-guide-chart/ ")
 
 
 
390
 
391
- #st.write("avatars from: https://www.flaticon.com/free-icons/bot")
 
5
  import time
6
  import math
7
  import streamlit as st
8
+
9
+ # from streamlit_chat import message
10
  from streamlit_extras.colored_header import colored_header
11
  from streamlit_extras.add_vertical_space import add_vertical_space
12
  from PIL import Image
 
19
 
20
  # import compatibilities matrix
21
  # make plant_compatibility.csv into a matrix. it currently has indexes as rows and columns for plant names and then compatibility values as the values
22
+ st.session_state.raw_plant_compatibility = pd.read_csv(
23
+ "src/data/plant_compatibility.csv", index_col=0
24
+ )
25
  # fill NaN values with 0
26
+ st.session_state.raw_plant_compatibility = (
27
+ st.session_state.raw_plant_compatibility.fillna(0)
28
+ )
29
  # get list of plants
30
  st.session_state.plant_list = st.session_state.raw_plant_compatibility.index.tolist()
31
 
32
  # set version
33
+ st.session_state.demo_lite = False
34
+ # set default model
35
+ st.session_state.model = "Llama2-7b_CPP"
36
 
37
  # setup keys and api info
38
  # OPENAI_API_KEY = st.secrets["OPENAI_API_KEY"]
39
  # os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
40
 
41
 
42
+ # chat = ChatOpenAI()
 
43
 
44
 
45
  # UI page config
46
  st.set_page_config(
47
+ # page_title="GRDN.AI",
48
  page_icon="🌱",
49
  layout="wide",
50
  initial_sidebar_state="expanded",
51
  )
52
 
53
+
54
  # Function to display chat message with an icon
55
  def chat_message(message, is_user=False):
56
  if is_user:
57
+ icon = Image.open("src/assets/cool.png")
58
  side = "left"
59
  else:
60
+ icon = Image.open("src/assets/bot.png")
61
  side = "right"
62
+
63
  chat_container = st.container()
64
 
65
  with chat_container:
66
+ col1, col2, col3, col4 = st.columns([1, 7, 7, 1])
67
 
68
  with col1:
69
  if is_user == True:
 
71
 
72
  with col2:
73
  if is_user == True:
74
+ st.markdown(
75
+ f'<div style="text-align: {side};">{message}</div>',
76
+ unsafe_allow_html=True,
77
+ )
78
  with col3:
79
  if is_user == False:
80
+ st.markdown(
81
+ f'<div style="text-align: {side};">{message}</div>',
82
+ unsafe_allow_html=True,
83
+ )
84
  with col4:
85
  if is_user == False:
86
  st.image(icon, width=50)
87
 
88
 
89
+ st.image(
90
+ "src/assets/logo_title_transparent.png",
91
+ caption=None,
92
+ use_column_width=None,
93
+ clamp=False,
94
+ channels="RGB",
95
+ output_format="auto",
96
+ )
97
 
98
  st.write("AI and optimization powered companion gardening")
99
+ colored_header(label="", description="", color_name="green-30")
100
 
101
  # Sidebar
102
  # st.sidebar.title("Navigation")
 
108
  # Sidebar
109
  st.sidebar.title("Navigation")
110
 
111
+
112
  # Define the page options
113
  pages = ["Garden Optimization", "About"]
114
 
 
118
 
119
  if page == "Garden Optimization":
120
  st.sidebar.subheader("Companion Gardening")
121
+ st.write(
122
+ "GRDN is a companion gardening app that helps you plan your garden and maximize your harvest. It uses optimization and AI to predict the best plants to grow together and optimization algorithms to optimize how you build your garden."
123
+ )
124
  st.write("This app is currently in beta. Please report any bugs.")
125
  companion_planting_info = """
126
  Key Benefits
 
133
  """
134
 
135
  st.sidebar.markdown(companion_planting_info)
136
+ # dropdown with advanced algorithm options- LLM agent base model and optimization algorithm type (constrained genetic algorithm or constrained community detection mixed integer programming model)
137
+ # with st.sidebar.expander("Advanced Options: LLM, optimization algorithm"):
138
+ # select LLM agent base model
139
+
140
+ st.sidebar.write("\n\n\n")
141
+ st.sidebar.write("\n\n\n")
142
+
143
+ st.sidebar.subheader("LLM agent base model")
144
+ # radio buttons for LLM used throughout the app ('openai', 'Llama2-7b_CPP', 'deci-7b-CPP')
145
+ st.session_state.model = st.sidebar.radio(
146
+ "Select an open-source LLM :",
147
+ (
148
+ #'openai-gpt35turbo',
149
+ "Llama2-7b_CPP",
150
+ "deci-7b_CPP",
151
+ "lite_demo (no LLM)",
152
+ ),
153
+ )
154
+ # # radio buttons for optimization algorithm used throughout the app ('constrained_genetic_algorithm', 'constrained_community_detection_mip')
155
+ # st.session_state.optimization_algo = st.radio("Select an optimization algorithm :", (
156
+ # 'constrained_genetic_algorithm',
157
+ # 'constrained_community_detection_mip'))
158
+
159
+ # override model if lite demo is selected
160
+ if (
161
+ st.session_state.model == "lite_demo (no LLM)"
162
+ or st.session_state.model == "deci-7b_CPP"
163
+ ):
164
+ st.session_state.demo_lite = True
165
+
166
  # Set the initial value of user_name
167
+ if "user_name" not in st.session_state:
168
+ st.session_state.user_name = ""
169
  # add in some vertical space
170
  add_vertical_space(3)
171
  # Display the welcome message
172
+ st.title("Let's get started! Decide on your garden parameters")
173
+
 
174
  # add in some vertical space
175
  add_vertical_space(2)
176
 
 
179
 
180
  with container1:
181
  # Modify the user_name variable based on user input
182
+ if st.session_state["user_name"] == "":
183
+ col1, col2, col3 = st.columns([1, 2, 1])
184
  with col1:
185
+ st.session_state["user_name_input"] = st.text_input(
186
+ "Enter your name", st.session_state.user_name
187
+ )
188
+ if "user_name_input" in st.session_state:
189
  st.session_state.user_name = st.session_state.user_name_input
190
+ if st.session_state.user_name != "":
191
+ st.write(
192
+ "Hello "
193
+ + st.session_state["user_name"]
194
+ + "! Let's optimize your garden. "
195
+ )
196
 
197
  # # add in some vertical space
198
  add_vertical_space(2)
 
201
  print("____________________")
202
  print("start of session")
203
 
204
+ col1a, col2a = st.columns([1, 2])
205
  enable_max_species = False
206
  enable_min_species = False
207
 
 
208
  # make a form to get the plant list from the user
209
  with col1a:
210
+ with st.form(key="plant_list_form"):
211
+ input_plants_raw = st.multiselect(
212
+ "plants", st.session_state.plant_list
213
+ )
214
+ submit_button = st.form_submit_button(label="Submit Plant List")
215
  if submit_button:
216
+ st.session_state["input_plants_raw"] = input_plants_raw
217
  st.session_state.submitted_plant_list = True
218
 
219
  # add in some vertical space
220
  add_vertical_space(1)
221
 
222
  with col2a:
223
+ col1, col2, col3 = st.columns([1, 1, 1])
224
+ if "input_plants_raw" in st.session_state:
225
  print("BP1")
226
  # first question is what plants would you like to plant
227
  plants_response = st.session_state.input_plants_raw
228
 
229
  # Initialize session state variables if they don't exist
230
+ if "n_plant_beds" not in st.session_state:
231
+ st.session_state["n_plant_beds"] = 1
232
 
233
+ if "min_species" not in st.session_state:
234
+ st.session_state["min_species"] = 1
235
 
236
+ if "max_species" not in st.session_state:
237
+ st.session_state["max_species"] = 2
238
 
239
  # Number of plant beds input
240
  with col1:
241
+ n_plant_beds = st.number_input(
242
+ "Number of plant beds \n",
243
+ min_value=1,
244
+ max_value=20,
245
+ value=st.session_state.n_plant_beds,
246
+ step=1,
247
+ )
248
  st.session_state.n_plant_beds = n_plant_beds
249
  with col2:
250
  # Minimum species per plant bed input
251
+ min_species = st.number_input(
252
+ "Minimum number of species per plant bed",
253
+ min_value=1,
254
+ max_value=len(st.session_state.input_plants_raw),
255
+ value=st.session_state.min_species,
256
+ step=1,
257
+ )
258
  st.session_state.min_species = min_species
259
 
260
  # Maximum species per plant bed input
261
  # It will be enabled only if min_species is set
262
  enable_max_species = st.session_state.min_species > 0
263
  with col3:
264
+ max_species = st.number_input(
265
+ "Maximum number of species per plant bed",
266
+ min_value=st.session_state.min_species,
267
+ max_value=len(st.session_state.input_plants_raw),
268
+ value=max(
269
+ st.session_state.min_species,
270
+ st.session_state.max_species,
271
+ ),
272
+ step=1,
273
+ disabled=not enable_max_species,
274
+ )
275
  if enable_max_species:
276
  st.session_state.max_species = max_species
277
 
278
  # extract the compatibility matrix from the user's input
279
+ if "extracted_mat" not in st.session_state:
280
  valid = False
281
+ if (
282
+ "submitted_plant_list" in st.session_state
283
+ and st.session_state.submitted_plant_list
284
+ ):
285
  # check if the user's input is valid
286
  # min species per bed must be less than or equal to max species per bed
287
+ if (
288
+ (
289
+ st.session_state.min_species
290
+ <= st.session_state.max_species
291
+ )
292
+ and (
293
+ # max species per bed must be less than or equal to the number of plants
294
+ st.session_state.max_species
295
+ <= len(st.session_state.input_plants_raw)
296
+ )
297
+ and (
298
+ # max species per bed must be greater than or equal to the min species per bed
299
+ st.session_state.max_species
300
+ >= st.session_state.min_species
301
+ )
302
+ and (
303
+ # min species per bed must be less than or equal to the number of plants
304
+ st.session_state.min_species
305
+ <= len(st.session_state.input_plants_raw)
306
+ )
307
+ and (
308
+ # number of plant beds multiplied by min species per bed must be less than or equal to the number of plants
309
+ len(st.session_state.input_plants_raw)
310
+ >= st.session_state.n_plant_beds
311
+ * st.session_state.min_species
312
+ )
313
+ and (
314
+ # number of plant beds multiplied by max species per bed must be greater than or equal to the number of plants
315
+ len(st.session_state.input_plants_raw)
316
+ <= st.session_state.n_plant_beds
317
+ * st.session_state.max_species
318
+ )
319
+ ):
320
+ valid = True
321
  else:
322
  # add a warning message
323
+ st.warning(
324
+ "Please enter valid parameters. The minimum number of species per plant bed must be less than or equal to the maximum number of species per plant bed. The maximum number of species per plant bed must be less than or equal to the number of plants. The maximum number of species per plant bed must be greater than or equal to the minimum number of species per plant bed. The minimum number of species per plant bed must be less than or equal to the number of plants. The number of plant beds multiplied by the minimum number of species per plant bed must be less than or equal to the number of plants. The number of plant beds multiplied by the maximum number of species per plant bed must be greater than or equal to the number of plants."
325
+ )
326
 
327
  if valid:
328
  # add in some vertical space
329
  add_vertical_space(2)
330
+ if st.button(
331
+ "Generate Companion Plant Compatibility Matrix"
332
+ ):
333
+ with st.spinner(
334
+ "generating companion plant compatibility matrix..."
335
+ ):
336
+ st.session_state["generating_mat"] = True
337
  # now get compatibility matrix for companion planting
338
  time.sleep(1)
339
+ (
340
+ extracted_mat,
341
+ full_mat,
342
+ plant_index_mapping,
343
+ ) = get_compatibility_matrix_2(
344
+ st.session_state.input_plants_raw
345
+ )
346
  print(extracted_mat)
347
  st.session_state.extracted_mat = extracted_mat
348
  st.session_state.full_mat = full_mat
349
+ st.session_state.plant_index_mapping = (
350
+ plant_index_mapping
351
+ )
352
  # add in some vertical space
353
  add_vertical_space(4)
354
 
355
  # display the companion plant compatibility matrix
356
+ if "extracted_mat" in st.session_state:
357
  # add a title for the next section- companion plant compatibility matrix based on user input
358
+ st.title("Your companion plant compatibility matrix")
359
  # make a container for this section
360
  container2 = st.container(border=True)
361
  with container2:
362
+ col1, col2 = st.columns([8, 4])
363
  # display the companion plant compatibility matrix
364
  with col2:
365
  st.write("Here is your companion plant compatibility matrix:")
366
  with st.expander("Show ugly compatibility matrix of 1's 0's and -1's"):
367
  st.write(st.session_state.extracted_mat)
368
  with col1:
369
+ st.write(
370
+ "Here is a network visualization of your companion plant compatibility matrix. It is color coded to show which plants are companions (green), antagonists (violetred), or neutral (grey)."
371
+ )
372
+ plot_compatibility_with_agraph(
373
+ st.session_state.input_plants_raw, st.session_state.full_mat
374
+ )
375
+ st.session_state["got_mat"] = True
376
+
377
+ if "got_mat" in st.session_state:
378
  # add in some vertical space
379
+ add_vertical_space(4)
380
  # make a container for this section
381
  container3 = st.container(border=True)
382
+ with container3:
383
+ st.title(
384
+ "Optimizing companion planting with the genetic algorithm and AI"
385
+ )
386
+ st.write(
387
+ "Now that we have your companion plant compatibility matrix, we can use optimization to maximize your harvest. We will use a genetic algorithm to determine the best way to plant your garden. The genetic algorithm will determine the best way to plant your garden by maximizing the number of companion plants and minimizing the number of antagonists."
388
+ )
389
+ st.write(
390
+ "Set the parameters for the genetic algorithm. Here is more info for your reference:"
391
+ )
392
+ with st.form(key="genetic_algorithm_form"):
393
+ col1, col2 = st.columns([1, 1])
394
  with col2:
395
+ with st.expander(
396
+ "Show more information about the genetic algorithm parameters"
397
+ ):
398
  st.subheader("Plant Optimization Heuristic Performance")
399
+ st.write(
400
+ "The genetic algorithm parameters impact the performance of the plant optimization heuristic in the following ways:"
401
+ )
402
+ st.markdown(
403
+ "- **Population Size**: A larger population size allows for a more diverse exploration of the solution space. However, it also increases computational complexity."
404
+ )
405
+ st.markdown(
406
+ "- **Number of Generations**: Increasing the number of generations provides more opportunities for the algorithm to converge towards an optimal solution."
407
+ )
408
+ st.markdown(
409
+ "- **Tournament Size**: A larger tournament size promotes stronger selection pressure and can lead to faster convergence, but it may also increase the risk of premature convergence."
410
+ )
411
+ st.markdown(
412
+ "- **Crossover Rate**: A higher crossover rate increases the exploration capability by creating diverse offspring, potentially improving the algorithm's ability to escape local optima."
413
+ )
414
+ st.markdown(
415
+ "- **Mutation Rate**: Mutation introduces random changes in individuals, helping to maintain diversity in the population and preventing premature convergence."
416
+ )
417
  # seed population rate
418
+ st.markdown(
419
+ "- **Seed Population Rate**: The seed population rate is the percentage of the population that is generated based on the LLM's interpretation of compatibility. The remaining percentage of the population is generated randomly. A higher seed population rate increases the likelihood that the genetic algorithm will converge towards a solution that is compatible."
420
+ )
421
  # Run the Genetic Algorithm
422
  with col1:
423
  st.subheader("Genetic Algorithm Parameters")
424
+ st.write(
425
+ "These parameters control the behavior of the genetic algorithm."
426
+ )
427
 
428
  # Genetic Algorithm parameters
429
+ st.session_state.population_size = st.slider(
430
+ "Population Size",
431
+ min_value=100,
432
+ max_value=1000,
433
+ value=500,
434
+ help="The number of individuals in each generation of the genetic algorithm.",
435
+ )
436
+ st.session_state.num_generations = st.slider(
437
+ "Number of Generations",
438
+ min_value=100,
439
+ max_value=1000,
440
+ value=450,
441
+ help="The total number of generations to evolve through.",
442
+ )
443
+ st.session_state.tournament_size = st.slider(
444
+ "Tournament Size",
445
+ min_value=5,
446
+ max_value=20,
447
+ value=10,
448
+ help="The number of individuals competing in each tournament selection round.",
449
+ )
450
+ st.session_state.crossover_rate = st.slider(
451
+ "Crossover Rate",
452
+ min_value=0.1,
453
+ max_value=1.0,
454
+ step=0.1,
455
+ value=0.8,
456
+ help="The probability of two individuals undergoing crossover to create offspring.",
457
+ )
458
+ st.session_state.mutation_rate = st.slider(
459
+ "Mutation Rate",
460
+ min_value=0.01,
461
+ max_value=0.9,
462
+ step=0.01,
463
+ value=0.3,
464
+ help="The probability of an individual undergoing mutation.",
465
+ )
466
+ st.session_state.seed_population_rate = st.slider(
467
+ "Seed Population Rate",
468
+ min_value=0.0,
469
+ max_value=0.02,
470
+ step=0.001,
471
+ value=0.08,
472
+ help="The percentage of the population that is generated based on the LLM's interpretation of compatibility. The remaining percentage of the population is generated randomly.",
473
+ )
474
+
475
+ #
476
  # Run the genetic algorithm
477
+ if st.form_submit_button(label="Run Genetic Algorithm"):
478
+ with st.spinner(
479
+ "running genetic algorithm... this may take a minute"
480
+ ):
481
+ grouping = genetic_algorithm_plants(
482
+ st.session_state.model, st.session_state.demo_lite
483
+ )
484
  st.session_state.grouping = grouping
485
 
486
  # visualize the groupings
 
491
  st.header("Here are the optimized groupings of plants for your garden")
492
  container4 = st.container(border=True)
493
  with container4:
494
+ if "grouping" in st.session_state:
495
  visualize_groupings()
496
+ if "best_fitness" in st.session_state:
497
  # embed score.png
498
+ col1b, col2b = st.columns([2, 11])
499
  with col1b:
500
+ st.image(
501
+ "src/assets/score.png",
502
+ caption=None,
503
+ width=160,
504
+ use_column_width=None,
505
+ clamp=False,
506
+ channels="RGB",
507
+ output_format="auto",
508
+ )
509
  with col2b:
510
+ # st.write("\n")
511
  st.header("| " + str(st.session_state.best_fitness))
512
+ st.write(
513
+ "The genetic algorithm converged towards a solution with a fitness score of "
514
+ + str(st.session_state.best_fitness)
515
+ + "."
516
+ )
517
  # Add vertical space
518
  add_vertical_space(4)
519
  # show plant care tips
520
  st.header("Plant care tips")
521
+ with st.spinner("generating plant care tips..."):
522
+ st.write(
523
+ "Here are some plant care tips for your plants. Good luck!"
524
+ )
525
  if st.session_state.demo_lite:
526
+ st.session_state.plant_care_tips = "Plant care tips are not available in this LLM or lite demo version but will be available in the future! Select the Llama 2 LLM for full functionality."
527
  else:
528
+ # if 'plant_care_tips' not in st.session_state:
529
+ st.session_state.plant_care_tips = get_plant_care_tips(
530
+ st.session_state.input_plants_raw,
531
+ st.session_state.model,
532
+ st.session_state.demo_lite,
533
+ )
534
  styled_text = f'<div style="background-color: #2d5a59; color: white; padding: 10px; border-radius: 5px;">{st.session_state.plant_care_tips}</div>'
535
  st.write(styled_text, unsafe_allow_html=True)
536
 
537
 
538
+ if page == "About":
539
+ st.sidebar.subheader("About")
540
+ st.sidebar.write(
541
+ "GRDN is a companion gardening app that helps you plan your garden and maximize your harvest. It uses AI to predict the best plants to grow together and optimization algorithms to optimize how you build your garden."
542
+ )
543
+ st.sidebar.write(
544
+ "Companion gardening is the practice of planting different plants together to maximize their growth. Companion gardening can help to increase the yield of your garden, improve the health of your plants, and reduce the need for pesticides."
545
+ )
546
+ st.write("This app is currently in beta. Please report any bugs to the team.")
547
 
548
+ add_vertical_space(1)
549
 
550
+ st.subheader("Tech Stack Diagram")
551
 
552
+ st.image(
553
+ "src/assets/GRDN_AI_techstack_.png",
554
+ caption=None,
555
+ use_column_width=None,
556
+ clamp=False,
557
+ channels="RGB",
558
+ output_format="auto",
559
+ )
560
 
561
+ add_vertical_space(4)
 
 
 
 
562
 
563
+ col1, col2 = st.columns([1, 1])
564
+ with col1:
565
  st.subheader("Contact Information")
566
  st.write("Author: Danielle Heymann")
567
  st.write("Email: dheymann314@gmail.com")
 
569
  with col2:
570
  st.subheader("Software, data, and libraries used")
571
  st.write("Libraries and Software")
572
+ st.markdown(
573
+ """
574
  - Python
575
  - streamlit
576
  - openai
 
582
  - streamlit_chat
583
  - github copilot
584
  - Llama2
585
+ - Deci AI
586
  - HuggingFace
587
  - LlamaIndex
588
  - chatGPT
589
  - GPT family of models
590
  - DALL·E 3 (in preprocessing script for image generation)
591
+ """
592
+ )
593
+ st.write(
594
+ "Data sources in addition to what LLMs were trained on: \n https://waldenlabs.com/the-ultimate-companion-planting-guide-chart/ "
595
+ )
596
 
597
+ # st.write("avatars from: https://www.flaticon.com/free-icons/bot")