pranit144's picture
Update app.py
72b4fe9 verified
from flask import Flask, render_template, request, jsonify
import google.generativeai as genai
from PIL import Image
import io
import fitz
import markdown2
import re
import matplotlib.pyplot as plt
import base64
import json
# Configure the Gemini API
genai.configure(api_key="AIzaSyAP_HLW93ErBBhmwxBilrFak_m8D6LQf04")
app = Flask(__name__)
app.secret_key = "supersecretkey"
def process_file(file):
"""Process file into an appropriate format for Gemini."""
if file.content_type == 'application/pdf':
try:
pdf_bytes = file.read()
pdf_document = fitz.open(stream=pdf_bytes, filetype="pdf")
first_page = pdf_document[0]
pix = first_page.get_pixmap()
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
return img, file.filename
except Exception as e:
raise Exception(f"Error processing PDF {file.filename}: {str(e)}")
else:
try:
image_bytes = file.read()
image = Image.open(io.BytesIO(image_bytes))
return image, file.filename
except Exception as e:
raise Exception(f"Error processing image {file.filename}: {str(e)}")
def format_markdown(text):
"""Improve markdown formatting for the output."""
lines = [line.strip() for line in text.split('\n')]
formatted_lines = []
for i, line in enumerate(lines):
if line.startswith('#'):
if i > 0:
formatted_lines.append('')
formatted_lines.append(line)
formatted_lines.append('')
elif line:
formatted_lines.append(line)
text = '\n'.join(formatted_lines)
text = re.sub(r'(?m)^(\s*)-', r'\1•', text)
text = re.sub(r'\n(•[^\n]+)(?:\n(?!•)|\Z)', r'\n\1\n', text)
return text
def generate_nutrient_chart(labels, data):
"""Generate a bar chart for nutrient levels using provided labels and data, and return it as a base64 encoded PNG."""
fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(labels, data, color=['#FF6384', '#36A2EB', '#FFCE56'], edgecolor=['#FF6384', '#36A2EB', '#FFCE56'],
linewidth=1)
ax.set_ylabel('Nutrient Levels (lbs/100 sq ft)')
ax.set_title('Nutrient Levels')
ax.set_ylim(0, max(data) * 1.5)
buf = io.BytesIO()
plt.savefig(buf, format='png', bbox_inches='tight')
plt.close(fig)
buf.seek(0)
img_data = base64.b64encode(buf.getvalue()).decode('utf-8')
return f"data:image/png;base64,{img_data}"
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
if "files" not in request.files:
return jsonify({"error": "No files uploaded"})
files = request.files.getlist("files")
if not files or files[0].filename == "":
return jsonify({"error": "No files selected"})
try:
processed_files = []
for file in files:
processed_content, filename = process_file(file)
processed_files.append((processed_content, filename))
filenames = [f[1] for f in processed_files]
files_list = "\n".join([f"- {fname}" for fname in filenames])
content_parts = []
for img, _ in processed_files:
content_parts.append(img)
# Updated prompt: we now instruct Gemini to include a section "NUTRIENT_DATA:"
# with a complete JSON object for chart generation.
content_parts.append(
f"""Please analyze all {len(files)} soil reports provided and generate a comprehensive, detailed soil analysis report in markdown format. Use simple, everyday language that farmers and non-technical users can easily understand.
Divide the report into the following clearly labeled sections (each with distinct formatting when rendered):
1. **Overview:**
Provide a detailed snapshot of the soil's overall health in plain language.
2. **Soil Composition:**
Explain the proportions of sand, silt, and clay, and describe how these affect water retention, drainage, and fertility.
3. **Nutrient Levels:**
Present an in-depth analysis of key nutrients (e.g. Nitrogen, Phosphorus, Potassium) and include recommendations.
4. **pH Balance & Moisture Content:**
Describe the soil’s pH level and moisture content, and explain how they influence crop performance.
5. **Recommendations & Actionable Steps:**
Provide clear, practical advice to improve soil quality (such as lime application, fertilizer usage, and adding organic matter) with this aslo provide which crops should we should cultivate with season and weather condition that will help me to improve my soil condition and let me develop more and also which crops should i avoid with this can you also recommend me any home remedies or natural remedies that will help me to improve my soil condition also recommend me what agriculture practices whill help me to maintain my soil condition in terms of the future of 5 to 10 years .
6. **Graphical Representation:**
In addition to the text, generate a bar chart displaying nutrient levels.
Also, please include a section labeled **NUTRIENT_DATA:** containing a JSON object with two keys: "labels" (a list of nutrient names) and "values" (a list of corresponding numerical values). The data may vary based on the analysis.
Reports being analyzed:
{files_list}
Ensure that every section is clearly labeled and formatted so that the output is easy to understand and visually appealing."""
)
model = genai.GenerativeModel("gemini-1.5-flash")
response = model.generate_content(content_parts)
if response and response.text:
summary = response.text.strip()
if summary.lower().startswith("please provide"):
return jsonify({"error": "Could not analyze the documents"})
# Extract nutrient data from the analysis if available
nutrient_data = None
if "NUTRIENT_DATA:" in summary:
try:
parts = summary.split("NUTRIENT_DATA:")
summary = parts[0].strip()
# Assume the nutrient JSON is on the first line after the marker
nutrient_json_str = parts[1].strip().split("\n")[0]
nutrient_data = json.loads(nutrient_json_str)
except Exception as e:
nutrient_data = None
final_output = f"""
# 🌱 Soil Report Analysis
{summary}
---
"""
fixed_output = format_markdown(final_output)
html_output = markdown2.markdown(
fixed_output,
extras=[
'tables',
'fenced-code-blocks',
'break-on-newline',
'cuddled-lists',
'code-friendly'
]
)
# Generate chart image using dynamic data if available
if nutrient_data and 'labels' in nutrient_data and 'values' in nutrient_data:
chart_img = generate_nutrient_chart(nutrient_data['labels'], nutrient_data['values'])
else:
chart_img = generate_nutrient_chart(['Nitrogen', 'Phosphorus', 'Potassium'], [0.15, 0.2, 0.3])
return jsonify({
"summary": fixed_output,
"html_summary": html_output,
"chart_img": chart_img
})
else:
return jsonify({"error": "No analysis could be generated"})
except Exception as e:
return jsonify({"error": f"Error processing files: {str(e)}"})
return render_template("index2.html")
if __name__ == "__main__":
app.run(debug=True, port=1234)