Yaswanth56 commited on
Commit
f32706c
·
verified ·
1 Parent(s): a8277c4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +258 -1
app.py CHANGED
@@ -1,10 +1,267 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  iface = gr.Interface(
2
  fn=generate_dpr,
3
  inputs=gr.Files(type="filepath", label="Upload Site Photos"),
4
- outputs=[gr.Textbox(label="Daily Progress Report"), gr.File(label="Download PDF")],
 
 
 
5
  title="Daily Progress Report Generator",
6
  description="Upload up to 10 site photos. The AI model will generate a text-based Daily Progress Report (DPR), save it as a PDF, and upload the PDF and images to Salesforce under Daily_Progress_Reports__c in the Files related list. Download the PDF locally if needed.",
7
  allow_flagging="never",
8
  show_api=False,
9
  show_tips=False
10
  )
 
 
 
 
1
+ from transformers import BlipProcessor, BlipForConditionalGeneration
2
+ from PIL import Image
3
+ import gradio as gr
4
+ import torch
5
+ from datetime import datetime
6
+ from reportlab.lib.pagesizes import letter
7
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image as PDFImage
8
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
9
+ from reportlab.lib import colors
10
+ from simple_salesforce import Salesforce
11
+ import os
12
+ from dotenv import load_dotenv
13
+ import base64
14
+ import io
15
+ import concurrent.futures
16
+
17
+ # Load environment variables from .env file
18
+ load_dotenv()
19
+
20
+ # Salesforce credentials
21
+ SF_USERNAME = os.getenv('SF_USERNAME')
22
+ SF_PASSWORD = os.getenv('SF_PASSWORD')
23
+ SF_SECURITY_TOKEN = os.getenv('SF_SECURITY_TOKEN')
24
+
25
+ # Initialize Salesforce connection
26
+ try:
27
+ sf = Salesforce(username=SF_USERNAME, password=SF_PASSWORD, security_token=SF_SECURITY_TOKEN)
28
+ except Exception as e:
29
+ sf = None
30
+ print(f"Failed to connect to Salesforce: {str(e)}")
31
+
32
+ # Load BLIP model and processor
33
+ processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
34
+ model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")
35
+ model.eval()
36
+ device = "cuda" if torch.cuda.is_available() else "cpu"
37
+ model.to(device)
38
+
39
+ # Inference function to generate captions dynamically based on image content
40
+ def generate_captions_from_image(image):
41
+ if image.mode != "RGB":
42
+ image = image.convert("RGB")
43
+
44
+ # Resize image for faster processing (use smaller resolution to speed up inference)
45
+ image = image.resize((320, 320)) # Reduced size for faster processing
46
+
47
+ # Preprocess the image and generate a caption
48
+ inputs = processor(image, return_tensors="pt").to(device, torch.float16)
49
+ output = model.generate(**inputs, max_new_tokens=50)
50
+ caption = processor.decode(output[0], skip_special_tokens=True)
51
+
52
+ return caption
53
+
54
+ # Function to save DPR text to a PDF file
55
+ def save_dpr_to_pdf(dpr_text, image_paths, captions, filename):
56
+ try:
57
+ # Create a PDF document
58
+ doc = SimpleDocTemplate(filename, pagesize=letter)
59
+ styles = getSampleStyleSheet()
60
+
61
+ # Define custom styles
62
+ title_style = ParagraphStyle(
63
+ name='Title',
64
+ fontSize=16,
65
+ leading=20,
66
+ alignment=1, # Center
67
+ spaceAfter=20,
68
+ textColor=colors.black,
69
+ fontName='Helvetica-Bold'
70
+ )
71
+ body_style = ParagraphStyle(
72
+ name='Body',
73
+ fontSize=12,
74
+ leading=14,
75
+ spaceAfter=10,
76
+ textColor=colors.black,
77
+ fontName='Helvetica'
78
+ )
79
+
80
+ # Build the PDF content
81
+ flowables = []
82
+
83
+ # Add title
84
+ flowables.append(Paragraph("Daily Progress Report", title_style))
85
+
86
+ # Split DPR text into lines and add as paragraphs (excluding descriptions for images)
87
+ for line in dpr_text.split('\n'):
88
+ # Replace problematic characters for PDF
89
+ line = line.replace('\u2019', "'").replace('\u2018', "'")
90
+ if line.strip():
91
+ flowables.append(Paragraph(line, body_style))
92
+ else:
93
+ flowables.append(Spacer(1, 12))
94
+
95
+ # Add images and captions in the correct order (no need to add description to dpr_text again)
96
+ for img_path, caption in zip(image_paths, captions):
97
+ try:
98
+ # Add image first
99
+ img = PDFImage(img_path, width=200, height=150) # Adjust image size if needed
100
+ flowables.append(img)
101
+ # Add description below the image
102
+ description = f"Description: {caption}"
103
+ flowables.append(Paragraph(description, body_style))
104
+ flowables.append(Spacer(1, 12)) # Add some space between images
105
+ except Exception as e:
106
+ flowables.append(Paragraph(f"Error loading image: {str(e)}", body_style))
107
+
108
+ # Build the PDF
109
+ doc.build(flowables)
110
+ return f"PDF saved successfully as {filename}", filename
111
+ except Exception as e:
112
+ return f"Error saving PDF: {str(e)}", None
113
+
114
+ # Function to upload a file to Salesforce as ContentVersion
115
+ def upload_file_to_salesforce(file_path, filename, sf_connection, file_type):
116
+ try:
117
+ # Read file content and encode in base64
118
+ with open(file_path, 'rb') as f:
119
+ file_content = f.read()
120
+ file_content_b64 = base64.b64encode(file_content).decode('utf-8')
121
+
122
+ # Set description based on file type
123
+ description = "Daily Progress Report PDF" if file_type == "pdf" else "Site Image"
124
+
125
+ # Create ContentVersion
126
+ content_version = sf_connection.ContentVersion.create({
127
+ 'Title': filename,
128
+ 'PathOnClient': filename,
129
+ 'VersionData': file_content_b64,
130
+ 'Description': description
131
+ })
132
+
133
+ # Get ContentDocumentId
134
+ content_version_id = content_version['id']
135
+ content_document = sf_connection.query(
136
+ f"SELECT ContentDocumentId FROM ContentVersion WHERE Id = '{content_version_id}'"
137
+ )
138
+ content_document_id = content_document['records'][0]['ContentDocumentId']
139
+
140
+ # Generate a valid Salesforce URL for the ContentDocument
141
+ content_document_url = f"https://{sf_connection.sf_instance}/sfc/servlet.shepherd/version/download/{content_version_id}"
142
+
143
+ # Ensure the link is valid
144
+ return content_document_id, content_document_url, f"File {filename} uploaded successfully"
145
+ except Exception as e:
146
+ return None, None, f"Error uploading {filename} to Salesforce: {str(e)}"
147
+
148
+ # Function to generate the daily progress report (DPR), save as PDF, and upload to Salesforce
149
+ def generate_dpr(files):
150
+ dpr_text = []
151
+ captions = []
152
+ image_paths = []
153
+ current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
154
+
155
+ # Add header to the DPR
156
+ dpr_text.append(f"Daily Progress Report\nGenerated on: {current_time}\n")
157
+
158
+ # Process images in parallel for faster performance
159
+ with concurrent.futures.ThreadPoolExecutor() as executor:
160
+ results = list(executor.map(lambda file: generate_captions_from_image(Image.open(file.name)), files))
161
+
162
+ for i, file in enumerate(files):
163
+ caption = results[i]
164
+ captions.append(caption)
165
+
166
+ # Generate DPR section for this image with dynamic caption
167
+ dpr_section = f"\nImage: {file.name}\nDescription: {caption}\n"
168
+ dpr_text.append(dpr_section)
169
+
170
+ # Save image path for embedding in the report
171
+ image_paths.append(file.name)
172
+
173
+ # Combine DPR text
174
+ dpr_output = "\n".join(dpr_text)
175
+
176
+ # Generate PDF filename with timestamp
177
+ pdf_filename = f"DPR_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf"
178
+
179
+ # Save DPR text to PDF
180
+ pdf_result, pdf_filepath = save_dpr_to_pdf(dpr_output, image_paths, captions, pdf_filename)
181
+
182
+ salesforce_result = ""
183
+ pdf_content_document_id = None
184
+ pdf_url = None
185
+ image_content_document_ids = []
186
+
187
+ if sf and pdf_filepath:
188
+ try:
189
+ # Create Daily_Progress_Reports__c record
190
+ report_description = "; ".join(captions)[:255] # Concatenate captions, limit to 255 chars
191
+ dpr_record = sf.Daily_Progress_Reports__c.create({
192
+ 'Detected_Activities__c': report_description # Store in Detected_Activities__c field
193
+ })
194
+ dpr_record_id = dpr_record['id']
195
+ salesforce_result += f"Created Daily_Progress_Reports__c record with ID: {dpr_record_id}\n"
196
+
197
+ # Upload PDF to Salesforce
198
+ pdf_content_document_id, pdf_url, pdf_upload_result = upload_file_to_salesforce(
199
+ pdf_filepath, pdf_filename, sf, "pdf"
200
+ )
201
+ salesforce_result += pdf_upload_result + "\n"
202
+
203
+ # Link PDF to DPR record
204
+ if pdf_content_document_id:
205
+ sf.ContentDocumentLink.create({
206
+ 'ContentDocumentId': pdf_content_document_id,
207
+ 'LinkedEntityId': dpr_record_id,
208
+ 'ShareType': 'V'
209
+ })
210
+
211
+ # Update the DPR record with the PDF URL
212
+ if pdf_url:
213
+ sf.Daily_Progress_Reports__c.update(dpr_record_id, {
214
+ 'PDF_URL__c': pdf_url # Storing the PDF URL correctly
215
+ })
216
+ salesforce_result += f"Updated PDF URL for record ID {dpr_record_id}\n"
217
+
218
+ # Upload images to Salesforce and link them to DPR record
219
+ for file in files:
220
+ image_filename = os.path.basename(file.name)
221
+ image_content_document_id, image_url, image_upload_result = upload_file_to_salesforce(
222
+ file.name, image_filename, sf, "image"
223
+ )
224
+
225
+ if image_content_document_id:
226
+ # Link image to the Daily Progress Report record (DPR) using ContentDocumentLink
227
+ sf.ContentDocumentLink.create({
228
+ 'ContentDocumentId': image_content_document_id,
229
+ 'LinkedEntityId': dpr_record_id, # Link image to DPR record
230
+ 'ShareType': 'V' # 'V' means Viewer access
231
+ })
232
+
233
+ # Now, update the DPR record with the ContentDocumentId in the Site_Images field (if it's a text or URL field)
234
+ sf.Daily_Progress_Reports__c.update(dpr_record_id, {
235
+ 'Site_Images__c': image_content_document_id # Storing the ContentDocumentId directly
236
+ })
237
+
238
+ salesforce_result += image_upload_result + "\n"
239
+
240
+ except Exception as e:
241
+ salesforce_result += f"Error interacting with Salesforce: {str(e)}\n"
242
+ else:
243
+ salesforce_result = "Salesforce connection not available or PDF generation failed.\n"
244
+
245
+ # Return DPR text, PDF file, and Salesforce upload status
246
+ return (
247
+ dpr_output + f"\n\n{pdf_result}\n\nSalesforce Upload Status:\n{salesforce_result}",
248
+ pdf_filepath
249
+ )
250
+
251
+ # Gradio interface for uploading multiple files, displaying DPR, and downloading PDF
252
  iface = gr.Interface(
253
  fn=generate_dpr,
254
  inputs=gr.Files(type="filepath", label="Upload Site Photos"),
255
+ outputs=[
256
+ gr.Textbox(label="Daily Progress Report"),
257
+ gr.File(label="Download PDF")
258
+ ],
259
  title="Daily Progress Report Generator",
260
  description="Upload up to 10 site photos. The AI model will generate a text-based Daily Progress Report (DPR), save it as a PDF, and upload the PDF and images to Salesforce under Daily_Progress_Reports__c in the Files related list. Download the PDF locally if needed.",
261
  allow_flagging="never",
262
  show_api=False,
263
  show_tips=False
264
  )
265
+
266
+ if __name__ == "__main__":
267
+ iface.launch()