Spaces:
Running
Running
File size: 8,000 Bytes
b8fe962 72b4fe9 b8fe962 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
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)
|