Update app.py
Browse files
app.py
CHANGED
|
@@ -1,155 +1,156 @@
|
|
| 1 |
-
from flask import Flask, render_template, request, jsonify
|
| 2 |
-
import google.generativeai as genai
|
| 3 |
-
from PIL import Image
|
| 4 |
-
import io
|
| 5 |
-
import fitz
|
| 6 |
-
import markdown2
|
| 7 |
-
import re
|
| 8 |
-
import matplotlib.pyplot as plt
|
| 9 |
-
import base64
|
| 10 |
-
import json
|
| 11 |
-
import matplotlib
|
| 12 |
-
matplotlib.use('Agg')
|
| 13 |
-
import matplotlib.pyplot as plt
|
| 14 |
-
from dotenv import load_dotenv
|
| 15 |
-
import os
|
| 16 |
-
|
| 17 |
-
load_dotenv() # This will load variables from a .env file in your project directory
|
| 18 |
-
gemini_api_key = os.getenv("GEMINI_API_KEY")
|
| 19 |
-
if not gemini_api_key:
|
| 20 |
-
raise ValueError("GEMINI_API_KEY not set in environment variables.")
|
| 21 |
-
genai.configure(api_key=gemini_api_key)
|
| 22 |
-
|
| 23 |
-
app = Flask(__name__)
|
| 24 |
-
app.secret_key = "supersecretkey"
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
def process_file(file):
|
| 28 |
-
"""Process file into an appropriate format for Gemini."""
|
| 29 |
-
if file.content_type == 'application/pdf':
|
| 30 |
-
try:
|
| 31 |
-
pdf_bytes = file.read()
|
| 32 |
-
pdf_document = fitz.open(stream=pdf_bytes, filetype="pdf")
|
| 33 |
-
first_page = pdf_document[0]
|
| 34 |
-
pix = first_page.get_pixmap()
|
| 35 |
-
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
|
| 36 |
-
return img, file.filename
|
| 37 |
-
except Exception as e:
|
| 38 |
-
raise Exception(f"Error processing PDF {file.filename}: {str(e)}")
|
| 39 |
-
else:
|
| 40 |
-
try:
|
| 41 |
-
image_bytes = file.read()
|
| 42 |
-
image = Image.open(io.BytesIO(image_bytes))
|
| 43 |
-
return image, file.filename
|
| 44 |
-
except Exception as e:
|
| 45 |
-
raise Exception(f"Error processing image {file.filename}: {str(e)}")
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
def format_markdown(text):
|
| 49 |
-
lines = [line.strip() for line in text.split('\n')]
|
| 50 |
-
formatted_lines = []
|
| 51 |
-
for i, line in enumerate(lines):
|
| 52 |
-
if line.startswith('#'):
|
| 53 |
-
if i > 0:
|
| 54 |
-
formatted_lines.append('')
|
| 55 |
-
formatted_lines.append(line)
|
| 56 |
-
formatted_lines.append('')
|
| 57 |
-
elif line:
|
| 58 |
-
formatted_lines.append(line)
|
| 59 |
-
text = '\n'.join(formatted_lines)
|
| 60 |
-
text = re.sub(r'(?m)^(\s*)-', r'\1•', text)
|
| 61 |
-
text = re.sub(r'\n(•[^\n]+)(?:\n(?!•)|\Z)', r'\n\1\n', text)
|
| 62 |
-
return text
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
@app.route("/", methods=["GET", "POST"])
|
| 68 |
-
def index():
|
| 69 |
-
if request.method == "POST":
|
| 70 |
-
if "files" not in request.files:
|
| 71 |
-
return jsonify({"error": "No files uploaded"})
|
| 72 |
-
files = request.files.getlist("files")
|
| 73 |
-
if not files or files[0].filename == "":
|
| 74 |
-
return jsonify({"error": "No files selected"})
|
| 75 |
-
|
| 76 |
-
# Retrieve the selected language from the form
|
| 77 |
-
language = request.form.get("language", "English")
|
| 78 |
-
|
| 79 |
-
try:
|
| 80 |
-
processed_files = []
|
| 81 |
-
for file in files:
|
| 82 |
-
processed_content, filename = process_file(file)
|
| 83 |
-
processed_files.append((processed_content, filename))
|
| 84 |
-
filenames = [f[1] for f in processed_files]
|
| 85 |
-
files_list = "\n".join([f"- {fname}" for fname in filenames])
|
| 86 |
-
content_parts = []
|
| 87 |
-
for img, _ in processed_files:
|
| 88 |
-
content_parts.append(img)
|
| 89 |
-
# Updated prompt: include the language instruction and refined content details
|
| 90 |
-
content_parts.append(f"""
|
| 91 |
-
Please analyze all {len(files)} soil reports and generate a comprehensive soil analysis report in markdown format, entirely in {language}.
|
| 92 |
-
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.
|
| 93 |
-
Ensure **exactly** five sections, each labeled as an H2 heading in Markdown, like this (in {language}):
|
| 94 |
-
## Overview Provide a detailed snapshot of the soil's overall health in plain language.
|
| 95 |
-
## Soil Composition Explain the proportions of sand, silt, and clay, and describe how these affect water retention, drainage, and fertility.
|
| 96 |
-
## Nutrient Levels Present an in-depth analysis of key nutrients (e.g. Nitrogen, Phosphorus, Potassium) and include recommendations.
|
| 97 |
-
## pH Balance & Moisture Content Describe the soil’s pH level and moisture content, and explain how they influence crop performance.
|
| 98 |
-
## 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.
|
| 99 |
-
Reports being analyzed:
|
| 100 |
-
{files_list}
|
| 101 |
-
|
| 102 |
-
Ensure that every section is clearly labeled and formatted so that the output is easy to understand and visually appealing."""
|
| 103 |
-
)
|
| 104 |
-
|
| 105 |
-
model = genai.GenerativeModel("gemini-1.5-flash")
|
| 106 |
-
response = model.generate_content(content_parts)
|
| 107 |
-
|
| 108 |
-
if response and response.text:
|
| 109 |
-
summary = response.text.strip()
|
| 110 |
-
if summary.lower().startswith("please provide"):
|
| 111 |
-
return jsonify({"error": "Could not analyze the documents"})
|
| 112 |
-
|
| 113 |
-
# Extract nutrient data from the analysis if available
|
| 114 |
-
nutrient_data = None
|
| 115 |
-
if "NUTRIENT_DATA:" in summary:
|
| 116 |
-
try:
|
| 117 |
-
parts = summary.split("NUTRIENT_DATA:")
|
| 118 |
-
summary = parts[0].strip()
|
| 119 |
-
# Assume the nutrient JSON is on the first line after the marker
|
| 120 |
-
nutrient_json_str = parts[1].strip().split("\n")[0]
|
| 121 |
-
nutrient_data = json.loads(nutrient_json_str)
|
| 122 |
-
except Exception as e:
|
| 123 |
-
nutrient_data = None
|
| 124 |
-
|
| 125 |
-
final_output = f"""
|
| 126 |
-
# 🌱 Soil Report Analysis
|
| 127 |
-
|
| 128 |
-
{summary}
|
| 129 |
-
|
| 130 |
-
---
|
| 131 |
-
"""
|
| 132 |
-
fixed_output = format_markdown(final_output)
|
| 133 |
-
html_output = markdown2.markdown(
|
| 134 |
-
fixed_output,
|
| 135 |
-
extras=[
|
| 136 |
-
'tables',
|
| 137 |
-
'fenced-code-blocks',
|
| 138 |
-
'break-on-newline',
|
| 139 |
-
'cuddled-lists',
|
| 140 |
-
'code-friendly'
|
| 141 |
-
]
|
| 142 |
-
)
|
| 143 |
-
|
| 144 |
-
return jsonify({
|
| 145 |
-
"summary": fixed_output,
|
| 146 |
-
"html_summary": html_output,
|
| 147 |
-
})
|
| 148 |
-
else:
|
| 149 |
-
return jsonify({"error": "No analysis could be generated"})
|
| 150 |
-
except Exception as e:
|
| 151 |
-
return jsonify({"error": f"Error processing files: {str(e)}"})
|
| 152 |
-
return render_template("index.html")
|
| 153 |
-
|
| 154 |
-
if __name__ == "__main__":
|
| 155 |
-
|
|
|
|
|
|
| 1 |
+
from flask import Flask, render_template, request, jsonify
|
| 2 |
+
import google.generativeai as genai
|
| 3 |
+
from PIL import Image
|
| 4 |
+
import io
|
| 5 |
+
import fitz
|
| 6 |
+
import markdown2
|
| 7 |
+
import re
|
| 8 |
+
import matplotlib.pyplot as plt
|
| 9 |
+
import base64
|
| 10 |
+
import json
|
| 11 |
+
import matplotlib
|
| 12 |
+
matplotlib.use('Agg')
|
| 13 |
+
import matplotlib.pyplot as plt
|
| 14 |
+
from dotenv import load_dotenv
|
| 15 |
+
import os
|
| 16 |
+
|
| 17 |
+
load_dotenv() # This will load variables from a .env file in your project directory
|
| 18 |
+
gemini_api_key = os.getenv("GEMINI_API_KEY")
|
| 19 |
+
if not gemini_api_key:
|
| 20 |
+
raise ValueError("GEMINI_API_KEY not set in environment variables.")
|
| 21 |
+
genai.configure(api_key=gemini_api_key)
|
| 22 |
+
|
| 23 |
+
app = Flask(__name__)
|
| 24 |
+
app.secret_key = "supersecretkey"
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def process_file(file):
|
| 28 |
+
"""Process file into an appropriate format for Gemini."""
|
| 29 |
+
if file.content_type == 'application/pdf':
|
| 30 |
+
try:
|
| 31 |
+
pdf_bytes = file.read()
|
| 32 |
+
pdf_document = fitz.open(stream=pdf_bytes, filetype="pdf")
|
| 33 |
+
first_page = pdf_document[0]
|
| 34 |
+
pix = first_page.get_pixmap()
|
| 35 |
+
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
|
| 36 |
+
return img, file.filename
|
| 37 |
+
except Exception as e:
|
| 38 |
+
raise Exception(f"Error processing PDF {file.filename}: {str(e)}")
|
| 39 |
+
else:
|
| 40 |
+
try:
|
| 41 |
+
image_bytes = file.read()
|
| 42 |
+
image = Image.open(io.BytesIO(image_bytes))
|
| 43 |
+
return image, file.filename
|
| 44 |
+
except Exception as e:
|
| 45 |
+
raise Exception(f"Error processing image {file.filename}: {str(e)}")
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def format_markdown(text):
|
| 49 |
+
lines = [line.strip() for line in text.split('\n')]
|
| 50 |
+
formatted_lines = []
|
| 51 |
+
for i, line in enumerate(lines):
|
| 52 |
+
if line.startswith('#'):
|
| 53 |
+
if i > 0:
|
| 54 |
+
formatted_lines.append('')
|
| 55 |
+
formatted_lines.append(line)
|
| 56 |
+
formatted_lines.append('')
|
| 57 |
+
elif line:
|
| 58 |
+
formatted_lines.append(line)
|
| 59 |
+
text = '\n'.join(formatted_lines)
|
| 60 |
+
text = re.sub(r'(?m)^(\s*)-', r'\1•', text)
|
| 61 |
+
text = re.sub(r'\n(•[^\n]+)(?:\n(?!•)|\Z)', r'\n\1\n', text)
|
| 62 |
+
return text
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
@app.route("/", methods=["GET", "POST"])
|
| 68 |
+
def index():
|
| 69 |
+
if request.method == "POST":
|
| 70 |
+
if "files" not in request.files:
|
| 71 |
+
return jsonify({"error": "No files uploaded"})
|
| 72 |
+
files = request.files.getlist("files")
|
| 73 |
+
if not files or files[0].filename == "":
|
| 74 |
+
return jsonify({"error": "No files selected"})
|
| 75 |
+
|
| 76 |
+
# Retrieve the selected language from the form
|
| 77 |
+
language = request.form.get("language", "English")
|
| 78 |
+
|
| 79 |
+
try:
|
| 80 |
+
processed_files = []
|
| 81 |
+
for file in files:
|
| 82 |
+
processed_content, filename = process_file(file)
|
| 83 |
+
processed_files.append((processed_content, filename))
|
| 84 |
+
filenames = [f[1] for f in processed_files]
|
| 85 |
+
files_list = "\n".join([f"- {fname}" for fname in filenames])
|
| 86 |
+
content_parts = []
|
| 87 |
+
for img, _ in processed_files:
|
| 88 |
+
content_parts.append(img)
|
| 89 |
+
# Updated prompt: include the language instruction and refined content details
|
| 90 |
+
content_parts.append(f"""
|
| 91 |
+
Please analyze all {len(files)} soil reports and generate a comprehensive soil analysis report in markdown format, entirely in {language}.
|
| 92 |
+
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.
|
| 93 |
+
Ensure **exactly** five sections, each labeled as an H2 heading in Markdown, like this (in {language}):
|
| 94 |
+
## Overview Provide a detailed snapshot of the soil's overall health in plain language.
|
| 95 |
+
## Soil Composition Explain the proportions of sand, silt, and clay, and describe how these affect water retention, drainage, and fertility.
|
| 96 |
+
## Nutrient Levels Present an in-depth analysis of key nutrients (e.g. Nitrogen, Phosphorus, Potassium) and include recommendations.
|
| 97 |
+
## pH Balance & Moisture Content Describe the soil’s pH level and moisture content, and explain how they influence crop performance.
|
| 98 |
+
## 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.
|
| 99 |
+
Reports being analyzed:
|
| 100 |
+
{files_list}
|
| 101 |
+
|
| 102 |
+
Ensure that every section is clearly labeled and formatted so that the output is easy to understand and visually appealing."""
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
model = genai.GenerativeModel("gemini-1.5-flash")
|
| 106 |
+
response = model.generate_content(content_parts)
|
| 107 |
+
|
| 108 |
+
if response and response.text:
|
| 109 |
+
summary = response.text.strip()
|
| 110 |
+
if summary.lower().startswith("please provide"):
|
| 111 |
+
return jsonify({"error": "Could not analyze the documents"})
|
| 112 |
+
|
| 113 |
+
# Extract nutrient data from the analysis if available
|
| 114 |
+
nutrient_data = None
|
| 115 |
+
if "NUTRIENT_DATA:" in summary:
|
| 116 |
+
try:
|
| 117 |
+
parts = summary.split("NUTRIENT_DATA:")
|
| 118 |
+
summary = parts[0].strip()
|
| 119 |
+
# Assume the nutrient JSON is on the first line after the marker
|
| 120 |
+
nutrient_json_str = parts[1].strip().split("\n")[0]
|
| 121 |
+
nutrient_data = json.loads(nutrient_json_str)
|
| 122 |
+
except Exception as e:
|
| 123 |
+
nutrient_data = None
|
| 124 |
+
|
| 125 |
+
final_output = f"""
|
| 126 |
+
# 🌱 Soil Report Analysis
|
| 127 |
+
|
| 128 |
+
{summary}
|
| 129 |
+
|
| 130 |
+
---
|
| 131 |
+
"""
|
| 132 |
+
fixed_output = format_markdown(final_output)
|
| 133 |
+
html_output = markdown2.markdown(
|
| 134 |
+
fixed_output,
|
| 135 |
+
extras=[
|
| 136 |
+
'tables',
|
| 137 |
+
'fenced-code-blocks',
|
| 138 |
+
'break-on-newline',
|
| 139 |
+
'cuddled-lists',
|
| 140 |
+
'code-friendly'
|
| 141 |
+
]
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
return jsonify({
|
| 145 |
+
"summary": fixed_output,
|
| 146 |
+
"html_summary": html_output,
|
| 147 |
+
})
|
| 148 |
+
else:
|
| 149 |
+
return jsonify({"error": "No analysis could be generated"})
|
| 150 |
+
except Exception as e:
|
| 151 |
+
return jsonify({"error": f"Error processing files: {str(e)}"})
|
| 152 |
+
return render_template("index.html")
|
| 153 |
+
|
| 154 |
+
if __name__ == "__main__":
|
| 155 |
+
port = int(os.environ.get("PORT", 7860))
|
| 156 |
+
app.run(host='0.0.0.0', port=port)
|