AI-Infused Optimization in the Wild: Developing a Companion Planting App

Danielle Heymann
7 min readDec 31, 2023

--

GRDN.AI 3.0 optimizes companion planting with an AI-infused genetic algorithm. In this article, I will break down how I developed the application, demonstrating a unique fusion of cutting-edge LLM agents with classic methodologies in decision sciences.

Overview

Key to a thriving garden, companion planting offers natural pest control, promotes healthy growth, and leads to more nutrients in soil. GRDN.AI applies this concept using an AI-infused genetic algorithm, making companion plant compatibility decisions easier. Built on an initial plant compatibility matrix, the app helps gardeners maximize the health of their plants.

GRDN.AI suggests customized garden bed configurations, taking into account user preferences for plant choices, number of plant beds, and minimum/maximum species desired in each plant bed. The initial plant compatibility matrix guides the two main backend workflows: a mathematical one for the optimization algorithm and an AI-driven one that helps generate starting points for the algorithm and provides additional review along the way. Ultimately, the application provides effective companion planting arrangements, as demonstrated in the demo video below. This is a side project that I have been experimenting and working on.

Demo

Tech Stack

The GRDN.AI application tech stack is comprised of input data and images, AI/ML and mathematical optimization workflows, user input, LLMs, analysis and visualizations, and deployment of the application to cloud based hub.

Deep dive: core features and functions explained

Graph theory

Graph theory is essential to GRDN.AI’s design, enabling smart planting through a network of plant relationships. Here’s a quick breakdown of graph theory fundamentals and how they are represented in the app:

  • Vertices (Nodes): These represent entities in a graph. In GRDN.AI, plant species are the vertices of the graphs
  • Edges: Link vertices, symbolizing plant compatibilities — positive, neutral, or antagonistic
  • Weights on Edges: Numerical indicators of interaction strength, with values 1, 0, or -1 for positive, neutral, or negative companion plant interactions, respectively
  • Adjacency Matrix: A key data matrix mapping out the connections and weights between all plant pairs, guiding the algorithm and the AI agent in discovering the best plant groupings
  • Complete Graph: A network graph setup where each plant is connected to all others, ensuring all relationships are considered
example of building a complete graph in networkx
On the left is the Networkx graph, and on the right is the streamlit-agraph based graph of a sample plant compatibility network. Networkx graphs can easily be transformed to streamlit-agraph structures. (Images by author; plant visualizations on the vertices of the network graph were generated with DALL-E 3)

GRDN.AI uses the Networkx and streamlit-agraph packages to manage and visualize these graph-based data structures.

Running LLMs locally with LlamaIndex and LlamaCPP

LlamaIndex and LlamaCPP allow engineers to run open-source models locally, including Meta AI’s Llama2, Deci’s DeciLM, which are used in GRDN.AI, and many open-source models available on platforms like Hugging Face. Key benefits include privacy and security, as data remains on-premises, and the full computational power of local hardware is harnessed without network latency. This setup allows for experimentation and testing, in addition to establishing the foundation for offline model access and local deployment.

What model files to use and where to find them

Optimized for local execution, GGUF files of Llama-based models are the current preferred model format for LlamaCPP. These can be acquired from Hugging Face, which hosts a diverse array of machine learning models. You can also convert other model formats to the GGUF format via scripts in the llama.cpp repo. Depending on your machine, the appropriate libraries, like CuBLAS for NVIDIA or Metal for M1/M2 MacBooks, can be utilized for optimal performance. The deployed app on my Hugging Face space runs on an NVIDIA T4. However, I use a MacBook M2 max when I run the application locally, which will be demonstrated in this article. You will see signs of the Metal framework in use, and in the code, I have selected to offload some of the model layers to the GPU (indicated by model_kwargs={ “n_gpu_layers”: 1 }).

The model files leveraged in GRDN.AI can be found here:

The code snippet is adopted from the Llama Index LlamaCPP documentation
Output from sample LlamaCPP code; model response is highlighted in lime green. Metal framework use is evident. (Image by author)

Genetic algorithm

The genetic algorithm that I’ve implemented in GRDN.AI utilizes several key steps fundamental to genetic algorithms, which include initializing a population, selection, crossover, mutation, and finally, evaluating the fitness of each individual within the population. The fitness function rewards positive interactions and penalizes negative interactions and constraint violation, which is a strategy to optimize the overall plant compatibility within each garden bed.

High-level overview of the key components of the genetic algorithm:

  1. Population initialization: At the start of the algorithm, the initial population of plant groupings are generated, incorporating both random groupings and those suggested by the LLM agent. This helps us make sure that we have a diverse starting point. The breakdown is determined by the seed population rate. GRDN.AI’s integration of an AI agent to provide initial seed groupings based on the compatibility matrix is a novel approach. It leverages the AI’s power to start the algorithm off with some potentially favorable solutions, which could lead to faster convergence on optimal garden bed configurations.
  2. Fitness calculation: Each grouping is evaluated based on a fitness function, which considers both the constraints and the compatibility matrix to score the grouping based on the positive and negative interactions between the plants.
  3. Selection: The algorithm selects the fittest groupings to be parents of the next generation. There are a variety of different selection methods that can be used. In GRDN.AI, this is achieved using a method called tournament selection, where groupings are randomly selected to compete, and the fittest from each group is selected. They then pass on their genes to the next generation.
  4. Crossover: The selected groupings are paired, and crossover is performed to produce offspring. This mimics biological reproduction to combine traits from each of the parents.
  5. Mutation: Avoiding local optima and preventing early convergence is important with the genetic algorithm. To maintain diversity in the population and avoid these issues, mutations are introduced at a set rate. This randomly changes parts of the offspring groupings and can also help avoid converging at local optima.
  6. Replacement: The new generation of groupings replaces the members of population who are less fit, and further iterations continue for a set number of generations that the user has indicated in the algorithm parameters or until a termination condition is met.
  7. Result: We end up with an optimized solution of the configuration of plant bed groupings found over all generations. This solution maximizes positive interactions and minimizes negative ones within the plant beds, while keeping the gardener’s constraints intact.

The fitness function: a more in-depth technical illustration

Although it is one function of many, the fitness function is a core piece of logic as it is designed to reward beneficial plant pairings and penalize any deviations from garden bed constraints or incomplete use of plant varieties. It is the scorekeeper in finding the ideal garden configuration and is refined through the generation iterations of the genetic algorithm in order to converge at a strong solution. Technical details are provided to show how this is developed and represented, both programmatically and theoretically.

Code snippet for GRDN.AI’s fitness function

Mathematical formulation of GRDN.AI’s fitness function

(Image by author)

Future Directions

I will be adding more to GRDN.AI, including more plant options, another optimization algorithm option that I developed with a mixed integer programming model based on correlation clustering, enhanced user experience, and better flow of the application. Feel free to send suggestions!

Something of interest that I’ve been thinking about it the role of AI within classical methodologies in decision sciences. This app shows just one example. So, I will conclude by sharing ideas for additional introduction of generative AI within well known methods:

Predictive modeling:

  • Data enrichment: integrate language-based insights extracted from unstructured data sources
  • Anomaly detection: identify unusual patterns or anomalies in text data; highlight potential issues or trends
  • Time series analysis: help interpret and predict patterns in time series data, especially where textual commentary or notes are involved

Prescriptive modeling:

  • Recommender systems: add another workflow for recommendations or decision-making support by analyzing complex scenarios described in text
  • Optimization: suggest constraint generation or objective function formulation based on user described challenge

Descriptive modeling:

  • Data summarization and interpretation: summarize large amounts of unstructured text into reports, and generate underlying themes, patterns, or questions to focus on in the data analysis
  • Community detection and topic modeling: help cluster data, categorizing documents into meaningful groups based on their content; generate the topic for each community

I hope that you found this walkthrough useful, and I look forward to writing more about these topics as I experiment and test out new ideas.

App repo: https://github.com/4dh/GRDN/

Gallery of GRDN.AI in action

The initial selection of plants and plant bed parameters, companion plant compatibility graph and matrix. This is followed by user selection of genetic algorithm parameters, which will influence how the algorithm will run (iterations, crossover rate, population size, etc.). Generally, the default settings are sufficient, but this extra flexibility lets the user experiment with the parameters. (Images by author; plant visualizations on the vertices of the network graph were generated with DALL-E 3)
The results: garden plant bed configurations based on user provided constraints. This is accompanied with plant care tips specific to the plants chosen. (Images by author; plant visualizations on the vertices of the network graph were generated with DALL-E 3)

--

--

Danielle Heymann

Data Scientist with specialties including: AI, ML, NLP, CV, computer programming, optimization, graph analytics, and rapidly learning new concepts and skills.