import streamlit as st import numpy as np import pandas as pd import requests import json import os from io import StringIO from sklearn.ensemble import RandomForestClassifier, GradientBoostingRegressor from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import PolynomialFeatures, StandardScaler from sklearn.pipeline import Pipeline from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, mean_squared_error ############################################################################### # Embedded minimal "real US small-farm" data (10 rows each). ############################################################################### PEST_DATA_CSV = """temperature,humidity,leaf_wetness,pest_outbreak 29,63,44,1 25,53,32,0 32,70,59,1 21,46,18,0 34,78,66,1 19,41,15,0 28,61,42,1 26,54,35,0 31,71,57,1 24,51,29,0 """ DISEASE_DATA_CSV = """soil_ph,rainfall,planting_density,disease_present 5.9,52,105,1 6.3,68,95,0 6.0,42,90,0 5.4,63,120,1 7.1,78,145,0 5.2,58,110,1 6.7,72,135,0 6.1,47,85,0 5.5,66,115,1 6.8,88,155,0 """ YIELD_DATA_CSV = """soil_fertility,temperature,irrigation_freq,fertilizer_score,crop_yield 64,25,3,42,56 48,21,2,36,47 78,31,4,62,73 52,27,2,46,59 68,29,3,52,66 44,19,1,32,39 82,33,4,74,82 57,24,2,40,51 72,30,3,56,69 88,34,5,82,88 """ ############################################################################### # Load data and train models without printing anything in the UI. ############################################################################### def load_data_from_string(csv_str): return pd.read_csv(StringIO(csv_str)) @st.cache_data def load_pest_data(): df = load_data_from_string(PEST_DATA_CSV) df.dropna(inplace=True) return df @st.cache_data def load_disease_data(): df = load_data_from_string(DISEASE_DATA_CSV) df.dropna(inplace=True) return df @st.cache_data def load_yield_data(): df = load_data_from_string(YIELD_DATA_CSV) df.dropna(inplace=True) return df @st.cache_data def train_pest_model(df): X = df[["temperature", "humidity", "leaf_wetness"]] y = df["pest_outbreak"] pipeline = Pipeline([ ("scaler", StandardScaler()), ("rf", RandomForestClassifier(n_estimators=50, random_state=42)) ]) pipeline.fit(X, y) return pipeline @st.cache_data def train_disease_model(df): X = df[["soil_ph", "rainfall", "planting_density"]] y = df["disease_present"] pipeline = Pipeline([ ("poly", PolynomialFeatures(degree=2, include_bias=False)), ("scaler", StandardScaler()), ("lr", LogisticRegression(random_state=42, max_iter=1000)) ]) pipeline.fit(X, y) return pipeline @st.cache_data def train_yield_model(df): X = df[["soil_fertility", "temperature", "irrigation_freq", "fertilizer_score"]] y = df["crop_yield"] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) pipeline = Pipeline([ ("scaler", StandardScaler()), ("gbr", GradientBoostingRegressor(n_estimators=50, learning_rate=0.1, random_state=42)) ]) pipeline.fit(X_train, y_train) return pipeline ############################################################################### # Define the OpenAI API Key using session state ############################################################################### if 'openai_api_key' not in st.session_state: st.session_state['openai_api_key'] = '' def call_gpt(prompt_text): api_key = st.session_state.get('openai_api_key', '') if not api_key: return "ERROR: No OpenAI API key provided. Please enter it to get GPT advice." endpoint = "https://api.openai.com/v1/chat/completions" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {api_key}" } data = { "model": "gpt-4o", # Using "o1-preview" as specified "messages": [ {"role": "system", "content": "You are a professional farm AI assistant."}, {"role": "user", "content": prompt_text} ], "max_tokens": 400, "temperature": 0.7 } try: resp = requests.post(endpoint, headers=headers, json=data) resp.raise_for_status() # Raise an error for bad status codes result = resp.json() if "choices" in result and len(result["choices"]) > 0: return result["choices"][0]["message"]["content"].strip() else: return "No valid response from GPT." except Exception as e: return f"Error calling GPT: {e}" ############################################################################### # Streamlit app with a title, sliders, labels, multi-crop selection box, # a button, minimal local predictions, and GPT response displayed. ############################################################################### def main(): st.title("Ai Farm Agent") # Load & train behind the scenes: pest_df = load_pest_data() disease_df = load_disease_data() yield_df = load_yield_data() pest_model = train_pest_model(pest_df) disease_model = train_disease_model(disease_df) yield_model = train_yield_model(yield_df) crop_options = [ "Corn", "Soybeans", "Wheat", "Cotton", "Alfalfa", "Sorghum", "Rice", "Peanuts" ] with st.form("farm_form"): selected_crop = st.selectbox("Select your crop", crop_options) soil_moisture = st.slider("Soil Moisture (%)", 0.0, 100.0, 25.0) soil_ph = st.slider("Soil pH", 0.0, 14.0, 6.0) temperature = st.slider("Temperature (°C)", 0.0, 50.0, 28.0) humidity = st.slider("Humidity (%)", 0.0, 100.0, 60.0) crop_health = st.slider("Crop Health (0-100)", 0.0, 100.0, 80.0) leaf_wetness = st.slider("Leaf Wetness (0-100)", 0.0, 100.0, 40.0) rainfall = st.number_input("Rainfall (mm)", 0.0, 500.0, 50.0, 5.0) planting_density = st.number_input("Planting Density (#/acre)", 10.0, 500.0, 100.0, 10.0) irrigation_freq = st.number_input("Irrigation Frequency (times/week)", 0.0, 14.0, 3.0) fertilizer_score = st.slider("Fertilizer Score (0-100)", 0.0, 100.0, 50.0) # Capture the API key from the user and set it in session state st.session_state['openai_api_key'] = st.text_input("OpenAI API Key", type="password") submitted = st.form_submit_button("Analyze") if submitted: # ------------------------- # Minimal local predictions # ------------------------- # 1) Check irrigation need irrigation_needed = (soil_moisture < 30) # 2) Pest outbreak X_pest = np.array([[temperature, humidity, leaf_wetness]]) pest_flag = (pest_model.predict(X_pest)[0] == 1) # 3) Disease presence X_dis = np.array([[soil_ph, rainfall, planting_density]]) disease_flag = (disease_model.predict(X_dis)[0] == 1) # 4) Yield prediction # We'll treat "crop_health" as "soil_fertility" in place of a separate input X_yield = np.array([[crop_health, temperature, irrigation_freq, fertilizer_score]]) predicted_yield = yield_model.predict(X_yield)[0] # Show minimal local results st.write(f"**Irrigation Needed:** {irrigation_needed}") st.write(f"**Pest Outbreak Likely?** {pest_flag}") st.write(f"**Disease Present?** {disease_flag}") st.write(f"**Predicted Yield (t/ha):** {predicted_yield:.2f}") # ------------------------- # GPT call # ------------------------- prompt_text = ( f"Crop: {selected_crop}. " f"Inputs: soil moisture={soil_moisture}%, soil pH={soil_ph}, temperature={temperature}°C, " f"humidity={humidity}%, crop health={crop_health}/100, leaf wetness={leaf_wetness}, " f"rainfall={rainfall} mm, planting density={planting_density} plants/acre, " f"irrigation frequency={irrigation_freq} times/week, fertilizer score={fertilizer_score}/100." f"\n\nLocal Analysis Results:\n" f"- Irrigation Needed: {irrigation_needed}\n" f"- Pest Outbreak Likely? {pest_flag}\n" f"- Disease Present? {disease_flag}\n" f"- Predicted Yield: {predicted_yield:.2f} t/ha\n\n" f"You are an agricultral agent. Your task is to help farmers create detailed, clear, comprehensive, and actionable plans for optimal results. Do this using the data provided. Take deep breaths, this is a tough one." ) response = call_gpt(prompt_text) # Show GPT response or a fallback message if response.strip() == "": st.write("No GPT response. Check your API key or model access.") else: st.write("**GPT Advice:**") st.write(response) if __name__ == "__main__": main()