Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -21,6 +21,9 @@ SF_SECURITY_TOKEN = os.getenv('SF_SECURITY_TOKEN')
|
|
| 21 |
# Initialize Salesforce connection
|
| 22 |
sf = Salesforce(username=SF_USERNAME, password=SF_PASSWORD, security_token=SF_SECURITY_TOKEN)
|
| 23 |
|
|
|
|
|
|
|
|
|
|
| 24 |
# Load BLIP model and processor
|
| 25 |
processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
|
| 26 |
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
|
|
@@ -28,28 +31,35 @@ model.eval()
|
|
| 28 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 29 |
model.to(device)
|
| 30 |
|
| 31 |
-
#
|
| 32 |
def generate_captions_from_image(image):
|
| 33 |
if image.mode != "RGB":
|
| 34 |
image = image.convert("RGB")
|
| 35 |
-
|
|
|
|
| 36 |
inputs = processor(image, return_tensors="pt").to(device, torch.float16)
|
| 37 |
output = model.generate(**inputs, max_new_tokens=50)
|
| 38 |
caption = processor.decode(output[0], skip_special_tokens=True)
|
| 39 |
-
|
| 40 |
return caption
|
|
|
|
| 41 |
|
| 42 |
# Function to create PDF and upload to Salesforce
|
| 43 |
def create_and_upload_pdf(dpr_content):
|
|
|
|
| 44 |
pdf = FPDF()
|
| 45 |
pdf.set_auto_page_break(auto=True, margin=15)
|
| 46 |
pdf.add_page()
|
|
|
|
|
|
|
| 47 |
pdf.set_font("Arial", size=12)
|
| 48 |
pdf.cell(200, 10, txt="Daily Progress Report", ln=True, align='C')
|
| 49 |
-
pdf.ln(10)
|
|
|
|
|
|
|
| 50 |
pdf.multi_cell(0, 10, dpr_content)
|
| 51 |
|
| 52 |
-
# Save PDF to file
|
| 53 |
pdf_output_path = "/tmp/dpr_report.pdf"
|
| 54 |
pdf.output(pdf_output_path)
|
| 55 |
|
|
@@ -57,74 +67,98 @@ def create_and_upload_pdf(dpr_content):
|
|
| 57 |
with open(pdf_output_path, 'rb') as pdf_file:
|
| 58 |
pdf_data = pdf_file.read()
|
| 59 |
|
| 60 |
-
#
|
| 61 |
content_version_payload = {
|
| 62 |
"Title": "Daily Progress Report",
|
| 63 |
-
"PathOnClient": "DPR_Report.pdf"
|
| 64 |
}
|
| 65 |
-
|
| 66 |
-
content_version_url = f"https://
|
| 67 |
headers = {
|
| 68 |
-
"Authorization": f"Bearer {sf.session_id}"
|
|
|
|
| 69 |
}
|
| 70 |
|
| 71 |
-
#
|
| 72 |
-
metadata_response = requests.post(content_version_url, headers=headers, json=content_version_payload)
|
| 73 |
-
if metadata_response.status_code != 201:
|
| 74 |
-
raise Exception("Metadata creation error: " + metadata_response.text)
|
| 75 |
-
|
| 76 |
-
content_version_id = metadata_response.json()["Id"]
|
| 77 |
-
|
| 78 |
-
# Upload file separately
|
| 79 |
files = {
|
| 80 |
-
"VersionData": ("DPR_Report.pdf", pdf_data,
|
| 81 |
}
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
else:
|
| 87 |
-
raise Exception("Error uploading PDF: " +
|
| 88 |
|
| 89 |
-
# Function to generate the daily progress report
|
| 90 |
def generate_dpr(files):
|
|
|
|
| 91 |
last_report = sf.query("SELECT Name FROM Daily_Progress_Reports__c ORDER BY CreatedDate DESC LIMIT 1")
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
new_report_name = f"Daily Progress Report {report_number}"
|
| 94 |
|
|
|
|
| 95 |
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 96 |
dpr_text = [f"Daily Progress Report\nGenerated on: {current_time}\n"]
|
| 97 |
|
|
|
|
| 98 |
for file in files:
|
| 99 |
-
image
|
|
|
|
|
|
|
| 100 |
if image.mode != "RGB":
|
| 101 |
image = image.convert("RGB")
|
|
|
|
|
|
|
| 102 |
caption = generate_captions_from_image(image)
|
|
|
|
|
|
|
| 103 |
dpr_section = f"\nImage: {file.name}\nDescription: {caption}\n"
|
| 104 |
dpr_text.append(dpr_section)
|
| 105 |
|
|
|
|
| 106 |
dpr_content = "\n".join(dpr_text)
|
|
|
|
|
|
|
| 107 |
pdf_url = create_and_upload_pdf(dpr_content)
|
| 108 |
|
|
|
|
| 109 |
new_report_data = {
|
| 110 |
-
"Name": new_report_name,
|
| 111 |
-
"Report_Date__c": current_time,
|
| 112 |
-
"Detected_Activities__c": dpr_content,
|
| 113 |
-
"Photo_Uploads__c": ", ".join([file.name for file in files]),
|
| 114 |
-
"PDF_URL__c": pdf_url
|
| 115 |
}
|
| 116 |
|
| 117 |
-
|
|
|
|
|
|
|
| 118 |
return f"New report created in Salesforce with PDF URL: {pdf_url}"
|
| 119 |
|
| 120 |
-
# Gradio interface for uploading
|
| 121 |
iface = gr.Interface(
|
| 122 |
fn=generate_dpr,
|
| 123 |
-
inputs=gr.Files(type="filepath", label="Upload Site Photos"),
|
| 124 |
-
outputs="text",
|
| 125 |
title="Daily Progress Report Generator",
|
| 126 |
-
description="Upload up to 10 site photos. The AI model
|
| 127 |
-
allow_flagging="never"
|
| 128 |
)
|
| 129 |
|
| 130 |
-
iface.launch()
|
|
|
|
| 21 |
# Initialize Salesforce connection
|
| 22 |
sf = Salesforce(username=SF_USERNAME, password=SF_PASSWORD, security_token=SF_SECURITY_TOKEN)
|
| 23 |
|
| 24 |
+
print(f"SF_USERNAME: {SF_USERNAME}, SF_PASSWORD: {SF_PASSWORD}, SF_SECURITY_TOKEN: {SF_SECURITY_TOKEN}")
|
| 25 |
+
print("Salesforce Base URL:", sf.base_url)
|
| 26 |
+
|
| 27 |
# Load BLIP model and processor
|
| 28 |
processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
|
| 29 |
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
|
|
|
|
| 31 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 32 |
model.to(device)
|
| 33 |
|
| 34 |
+
# Inference function to generate captions dynamically based on image content
|
| 35 |
def generate_captions_from_image(image):
|
| 36 |
if image.mode != "RGB":
|
| 37 |
image = image.convert("RGB")
|
| 38 |
+
|
| 39 |
+
# Preprocess the image and generate a caption
|
| 40 |
inputs = processor(image, return_tensors="pt").to(device, torch.float16)
|
| 41 |
output = model.generate(**inputs, max_new_tokens=50)
|
| 42 |
caption = processor.decode(output[0], skip_special_tokens=True)
|
| 43 |
+
|
| 44 |
return caption
|
| 45 |
+
|
| 46 |
|
| 47 |
# Function to create PDF and upload to Salesforce
|
| 48 |
def create_and_upload_pdf(dpr_content):
|
| 49 |
+
# Create PDF instance using FPDF
|
| 50 |
pdf = FPDF()
|
| 51 |
pdf.set_auto_page_break(auto=True, margin=15)
|
| 52 |
pdf.add_page()
|
| 53 |
+
|
| 54 |
+
# Set title and content for the PDF
|
| 55 |
pdf.set_font("Arial", size=12)
|
| 56 |
pdf.cell(200, 10, txt="Daily Progress Report", ln=True, align='C')
|
| 57 |
+
pdf.ln(10) # Add space between lines
|
| 58 |
+
|
| 59 |
+
# Add the content of the DPR text to the PDF
|
| 60 |
pdf.multi_cell(0, 10, dpr_content)
|
| 61 |
|
| 62 |
+
# Save PDF to a file (temporary storage)
|
| 63 |
pdf_output_path = "/tmp/dpr_report.pdf"
|
| 64 |
pdf.output(pdf_output_path)
|
| 65 |
|
|
|
|
| 67 |
with open(pdf_output_path, 'rb') as pdf_file:
|
| 68 |
pdf_data = pdf_file.read()
|
| 69 |
|
| 70 |
+
# Prepare request to Salesforce ContentVersion API
|
| 71 |
content_version_payload = {
|
| 72 |
"Title": "Daily Progress Report",
|
| 73 |
+
"PathOnClient": "DPR_Report.pdf",
|
| 74 |
}
|
| 75 |
+
|
| 76 |
+
content_version_url = f"https://sathkruthatechsolutionspvt6-dev-ed.develop.my.salesforce.com/services/data/v59.0/sobjects/ContentVersion/"
|
| 77 |
headers = {
|
| 78 |
+
"Authorization": f"Bearer {sf.session_id}",
|
| 79 |
+
"Content-Type": "application/json" # For metadata
|
| 80 |
}
|
| 81 |
|
| 82 |
+
# Pass the binary data in the files parameter (do not include it in the JSON payload)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
files = {
|
| 84 |
+
"VersionData": ("DPR_Report.pdf", pdf_data) # Tuple (filename, binary data)
|
| 85 |
}
|
| 86 |
+
|
| 87 |
+
# Make the POST request to upload the file
|
| 88 |
+
response = requests.post(content_version_url, headers=headers, files=files)
|
| 89 |
+
|
| 90 |
+
# Check the response status
|
| 91 |
+
if response.status_code == 201:
|
| 92 |
+
content_version = response.json()
|
| 93 |
+
pdf_url = f"/sfc/servlet.shepherd/version/download/{content_version['Id']}"
|
| 94 |
+
return pdf_url
|
| 95 |
else:
|
| 96 |
+
raise Exception("Error uploading PDF to Salesforce: " + response.text)
|
| 97 |
|
| 98 |
+
# Function to generate the daily progress report (DPR) text
|
| 99 |
def generate_dpr(files):
|
| 100 |
+
# Query the latest Daily Progress Report records to get the highest number
|
| 101 |
last_report = sf.query("SELECT Name FROM Daily_Progress_Reports__c ORDER BY CreatedDate DESC LIMIT 1")
|
| 102 |
+
|
| 103 |
+
# Generate the new report name
|
| 104 |
+
if last_report['totalSize'] > 0:
|
| 105 |
+
last_name = last_report['records'][0]['Name']
|
| 106 |
+
# Extract the number from the last report name, assuming format "Daily Progress Report X"
|
| 107 |
+
report_number = int(last_name.split()[-1]) + 1 # Increment the number
|
| 108 |
+
else:
|
| 109 |
+
# If no records exist, start with "1"
|
| 110 |
+
report_number = 1
|
| 111 |
+
|
| 112 |
+
# Generate the new report name dynamically
|
| 113 |
new_report_name = f"Daily Progress Report {report_number}"
|
| 114 |
|
| 115 |
+
# Prepare the current time and start the DPR text
|
| 116 |
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 117 |
dpr_text = [f"Daily Progress Report\nGenerated on: {current_time}\n"]
|
| 118 |
|
| 119 |
+
# Process each uploaded file (image)
|
| 120 |
for file in files:
|
| 121 |
+
# Open the image from the file path
|
| 122 |
+
image = Image.open(file.name) # Using file.name for filepath
|
| 123 |
+
|
| 124 |
if image.mode != "RGB":
|
| 125 |
image = image.convert("RGB")
|
| 126 |
+
|
| 127 |
+
# Generate a caption for the image
|
| 128 |
caption = generate_captions_from_image(image)
|
| 129 |
+
|
| 130 |
+
# Generate a section of the DPR for this image
|
| 131 |
dpr_section = f"\nImage: {file.name}\nDescription: {caption}\n"
|
| 132 |
dpr_text.append(dpr_section)
|
| 133 |
|
| 134 |
+
# Join the DPR sections into one complete string
|
| 135 |
dpr_content = "\n".join(dpr_text)
|
| 136 |
+
|
| 137 |
+
# Create and upload the PDF for this report to Salesforce
|
| 138 |
pdf_url = create_and_upload_pdf(dpr_content)
|
| 139 |
|
| 140 |
+
# Create the new Daily Progress Report record in Salesforce
|
| 141 |
new_report_data = {
|
| 142 |
+
"Name": new_report_name, # Set the dynamic name
|
| 143 |
+
"Report_Date__c": current_time, # Set the report date to the current time
|
| 144 |
+
"Detected_Activities__c": dpr_content, # Set the activities field to the generated text
|
| 145 |
+
"Photo_Uploads__c": ", ".join([file.name for file in files]), # Upload the image names as Photo Uploads
|
| 146 |
+
"PDF_URL__c": pdf_url # Set the PDF URL field with the generated PDF link
|
| 147 |
}
|
| 148 |
|
| 149 |
+
# Insert the new report into Salesforce
|
| 150 |
+
new_report = sf.Daily_Progress_Reports__c.create(new_report_data)
|
| 151 |
+
|
| 152 |
return f"New report created in Salesforce with PDF URL: {pdf_url}"
|
| 153 |
|
| 154 |
+
# Gradio interface for uploading multiple files and displaying the text-based DPR
|
| 155 |
iface = gr.Interface(
|
| 156 |
fn=generate_dpr,
|
| 157 |
+
inputs=gr.Files(type="filepath", label="Upload Site Photos"), # Handle batch upload of images
|
| 158 |
+
outputs="text", # Display the DPR as text in the output section
|
| 159 |
title="Daily Progress Report Generator",
|
| 160 |
+
description="Upload up to 10 site photos. The AI model will dynamically detect construction activities, materials, and progress and generate a text-based Daily Progress Report (DPR).",
|
| 161 |
+
allow_flagging="never" # Optional: Disable flagging
|
| 162 |
)
|
| 163 |
|
| 164 |
+
iface.launch()
|