|
|
from flask import Flask, render_template, request, jsonify |
|
|
from google import genai |
|
|
from google.genai import types |
|
|
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 |
|
|
import matplotlib |
|
|
matplotlib.use('Agg') |
|
|
import matplotlib.pyplot as plt |
|
|
from dotenv import load_dotenv |
|
|
import os |
|
|
|
|
|
load_dotenv() |
|
|
gemini_api_key = os.getenv("GEMINI_API_KEY") |
|
|
if not gemini_api_key: |
|
|
raise ValueError("GEMINI_API_KEY not set in environment variables.") |
|
|
genai.configure(api_key=gemini_api_key) |
|
|
|
|
|
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): |
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@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"}) |
|
|
|
|
|
|
|
|
language = request.form.get("language", "English") |
|
|
|
|
|
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) |
|
|
|
|
|
content_parts.append(f""" |
|
|
Please analyze all {len(files)} soil reports and generate a comprehensive soil analysis report in markdown format, entirely in {language}. |
|
|
dont reveal yourself as llm or ai model make the report as proffessional as possible and dont refer like i me sorry and all that in response. |
|
|
Ensure **exactly** five sections, each labeled as an H2 heading in Markdown, like this (in {language}): |
|
|
## Overview Provide a detailed snapshot of the soil's overall health in plain language. |
|
|
## Soil Composition Explain the proportions of sand, silt, and clay, and describe how these affect water retention, drainage, and fertility. |
|
|
## Nutrient Levels Present an in-depth analysis of key nutrients (e.g. Nitrogen, Phosphorus, Potassium) and include recommendations. |
|
|
## pH Balance & Moisture Content Describe the soil’s pH level and moisture content, and explain how they influence crop performance. |
|
|
## 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. |
|
|
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"}) |
|
|
|
|
|
|
|
|
nutrient_data = None |
|
|
if "NUTRIENT_DATA:" in summary: |
|
|
try: |
|
|
parts = summary.split("NUTRIENT_DATA:") |
|
|
summary = parts[0].strip() |
|
|
|
|
|
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' |
|
|
] |
|
|
) |
|
|
|
|
|
return jsonify({ |
|
|
"summary": fixed_output, |
|
|
"html_summary": html_output, |
|
|
}) |
|
|
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("index.html") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
port = int(os.environ.get("PORT", 7860)) |
|
|
app.run(host='0.0.0.0', port=port) |