Page cover image

Geological Survey Investigation Report Generation

This page demonstrates how to build a report generation app. The app allows users to upload their data and to use Action Table to compile essential information to generate the report.

Project setup

Before we start building, we are going to set up our Action Table. This is simple as clicking “New Action Table” in JamAIBase and then creating a “schema” inside the database.

Create a project

  1. Click “New Action Table”.

  2. Enter your project details.

  3. Click “Create” to complete the Action Table setup.

  4. Update the settings of the output column. Define the prompt message.

  5. Add additional columns if necessary.

Create Action Table for the report generation app.

Building the app

Step 1: Set Up Your Environment

First, ensure you have Python installed on your system. Then, install Streamlit and other necessary libraries using pip:

pip install streamlit pandas requests

Step 2: Initialize Your Streamlit App

Create a new Python file for your app, for example, borehole_analysis.py.

Step 3: Import Required Libraries

Start by importing the necessary libraries in your Python script:

import pandas as pd
import streamlit as st
import requests
from requests.auth import HTTPBasicAuth
import json

Step 4: Design the Sidebar for File Upload

Create a sidebar for user inputs. Add a file uploader in the sidebar to allow users to upload their Excel data.

st.sidebar.title("Upload Borehole Data")
uploaded_file = st.sidebar.file_uploader("Choose a file", type=['xlsx', 'xls'])

Step 5: Load and Display the Data

Once the file is uploaded, read and display the data using pandas.

if uploaded_file is not None:
    data = pd.read_excel(uploaded_file)
    st.write(data)

Step 6: Define Helper Functions for API Calls

Implement functions to interact with the database through API calls:

Function to Add a Row to the Database

def add_row(table_id, input_text):
    url = "https://app.jamaibase.com/api/v1/gen_tables/action/rows/add"
    payload = {
        "data": {"data": input_text},
        "stream": True,
        "table_id": table_id,
    }
    headers = {"accept": "application/json", "content-type": "application/json"}
    response = requests.post(
        url,
        json=payload,
        headers=headers,
        auth=HTTPBasicAuth("username", "password"),
        verify=False,
    )

Function to Retrieve Rows from the Database

def get_row(table_id):
    url = f"https://app.jamaibase.com/api/v1/gen_tables/action/{table_id}/rows?limit=100"
    headers = {"accept": "application/json"}
    response = requests.get(
        url, headers=headers, auth=HTTPBasicAuth("username", "password")
    )
    return response

Note that the latest row added to the database is always returned at the top of the list from the API.

Function to Get the Latest Row from the Database

def get_latest_row(table_id):
    response = get_row(table_id)
    json_object = json.loads(response.text) 
    last_row = json_object["items"][0]
    return last_row

Step 7: Add Button to Trigger API Calls

Add a button in Streamlit to trigger the API calls:

button_clicked = st.button("Run analysis")
if button_clicked:
    add_row('YourTableID', st.session_state["input_text"])
    st.session_state["lastest_row"] = get_latest_row('YourTableID')
    # Remaining code to process data goes here

Step 8: Prepare the Report Template

Display the static content of the report at appropriate sections:

st.markdown("### Drilling Sampling and On-site Testing")
st.markdown(
    """
    According to the on-site drilling work at this base, the approach is based on the site area, planning data, and analysis design requirements.
    """
)
...
st.markdown(
    """
    During the drilling process, a standard penetration test is conducted every 2.0 meters in the soil layer,
    which not only provides the N-value but also allows for the collection of split-spoon soil samples to supply the laboratory soil tests needed.
    """
)

Display Action Table outputs dynamically to allow users to update the outputs:

def stream_data(input_text):
    for word in input_text.split(" "):
        yield "**" + word + "** "
        time.sleep(0.1)

def stream_text_sections(button_clicked, stream_text, placeholder_key):
    text_area_placeholder = st.empty()
    if not button_clicked:
        st.session_state[placeholder_key] = text_area_placeholder.text_area(
            placeholder_key,
            value="",
            height=100,
        )
    else:
        if st.session_state[placeholder_key] != "":
            st.session_state[placeholder_key] = text_area_placeholder.text_area(
                placeholder_key,
                value=st.session_state[
                    placeholder_key
                ],
                height=100,
            )
            return
        response = stream_data(stream_text)
        full_response = ""
        for res in response:
            full_response += res
            text_area_placeholder.markdown(full_response, unsafe_allow_html=True)
        st.session_state[placeholder_key] = text_area_placeholder.text_area(
            placeholder_key,
            value=full_response.replace("**", ""), 
            height=100,
        )

# Add the functions at appropriate sections to display the outputs:
stream_text_sections(st.session_state["button_clicked"], result, key)

Step 9: Add Interactivity

Powered by JamAI, users are capable to easily generate as many outputs as possible. Add interactive elements, such as buttons or sliders, to allow users to customize the analysis. For example, add a radio to select the most appropriate descriptiopn for the report:

keys = ["Result_A1", "Result_A2", "Result_A3"]
results = [rA1, rA2, rA3]
for key, result in zip(keys, results):
    stream_text_sections(st.session_state["button_clicked"], result, key)

......

options = keys + ["None"]
selected_option = st.radio(
    "Choose the appropriate description:", options, index=0
)
if selected_option == "None":
    user_text = st.text_area(
        "User input", placeholder="Please provide your input."
    )
    st.session_state["result_A"] = user_text
elif selected_option in ["Result_A1", "Result_A2", "Result_A3"]:
    st.session_state["result_A"] = selected_option
    st.write(st.session_state.result_A)

Step 9: Add Button to download report

Add a button in Streamlit to download the report generated.

if st.session_state["button_clicked"]:
    st.download_button(
        label="Download File",
        data=gen_doc(
            text_1=text_1,
            text_2=text_2,
            html_table_1=html_table_1,
        ),
        file_name="report.docx",
        mime="text/plain",
    )

Step 10: Run Your Streamlit App

Save your script and run it using the Streamlit command in your terminal:

streamlit run borehole_analysis.py

Step 11: Start Your App

Interact with the application by uploading data and using the button to trigger API calls. Verify that data is added and retrieved as expected.

Sample video demonstrating the streamlit app for Borehole Analysis Report Generation app

Last updated

Was this helpful?