neerajkalyank commited on
Commit
c3eb5f1
·
verified ·
1 Parent(s): a93d3ae

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +241 -0
  2. env +5 -0
  3. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import random
3
+ import gradio as gr
4
+ from datetime import datetime
5
+ from transformers import pipeline
6
+ from simple_salesforce import Salesforce, SalesforceLogin
7
+ from dotenv import load_dotenv
8
+ import xml.etree.ElementTree as ET
9
+
10
+ # ---------- Load Environment Variables ----------
11
+ load_dotenv()
12
+ SF_USERNAME = os.getenv("SF_USERNAME")
13
+ SF_PASSWORD = os.getenv("SF_PASSWORD")
14
+ SF_SECURITY_TOKEN = os.getenv("SF_SECURITY_TOKEN")
15
+
16
+ # ---------- Label Mapping ----------
17
+ label_to_issue_type = {
18
+ "LABEL_0": "Performance",
19
+ "LABEL_1": "Error",
20
+ "LABEL_2": "Security",
21
+ "LABEL_3": "Best Practice"
22
+ }
23
+
24
+ suggestions = {
25
+ "Performance": "Consider optimizing loops and database access. Use collections to reduce SOQL queries.",
26
+ "Error": "Add proper error handling and null checks. Use try-catch blocks effectively.",
27
+ "Security": "Avoid dynamic SOQL. Use binding variables to prevent SOQL injection.",
28
+ "Best Practice": "Refactor for readability and use bulk-safe patterns, such as processing records in batches."
29
+ }
30
+
31
+ severities = {
32
+ "Performance": "Medium",
33
+ "Error": "High",
34
+ "Security": "High",
35
+ "Best Practice": "Low"
36
+ }
37
+
38
+ # ---------- Load QnA Model ----------
39
+ qa_pipeline = pipeline("text2text-generation", model="google/flan-t5-large")
40
+
41
+ # ---------- Logging ----------
42
+ def log_to_console(data, log_type):
43
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
44
+ print(f"[{timestamp}] {log_type} Log: {data}")
45
+
46
+ # ---------- Salesforce Connection ----------
47
+ try:
48
+ session_id, instance = SalesforceLogin(
49
+ username=SF_USERNAME,
50
+ password=SF_PASSWORD,
51
+ security_token=SF_SECURITY_TOKEN
52
+ )
53
+ sf = Salesforce(instance=instance, session_id=session_id)
54
+ print("✅ Connected to Salesforce successfully")
55
+ except Exception as e:
56
+ sf = None
57
+ print(f"❌ Failed to connect to Salesforce: {e}")
58
+
59
+ # ---------- Code Analyzer ----------
60
+ def analyze_code(code):
61
+ if not code.strip():
62
+ return "No code provided.", "", ""
63
+
64
+ label = random.choice(list(label_to_issue_type.keys()))
65
+ issue_type = label_to_issue_type[label]
66
+ suggestion = suggestions[issue_type]
67
+ severity = severities[issue_type]
68
+
69
+ review_data = {
70
+ "Name": f"Review_{issue_type}",
71
+ "CodeSnippet__c": code,
72
+ "IssueType__c": issue_type,
73
+ "Suggestion__c": suggestion,
74
+ "Severity__c": severity
75
+ }
76
+
77
+ log_to_console(review_data, "Code Review")
78
+
79
+ if sf:
80
+ try:
81
+ result = sf.CodeReviewResult__c.create(review_data)
82
+ if result.get("success"):
83
+ log_to_console({"Salesforce Record ID": result["id"]}, "Salesforce Create")
84
+ else:
85
+ log_to_console(result, "Salesforce Error")
86
+ except Exception as e:
87
+ log_to_console({"Salesforce Exception": str(e)}, "Salesforce Error")
88
+ else:
89
+ log_to_console("Salesforce not connected.", "Salesforce Error")
90
+
91
+ return issue_type, suggestion, severity
92
+
93
+ # ---------- Metadata Validator ----------
94
+ def validate_metadata(metadata, admin_id=None):
95
+ if not metadata.strip():
96
+ return "No metadata provided.", "", ""
97
+
98
+ mtype = "Field"
99
+ issue = "Unknown"
100
+ recommendation = "No recommendation found."
101
+
102
+ try:
103
+ root = ET.fromstring(metadata)
104
+ description_found = any(elem.tag.endswith('description') for elem in root)
105
+
106
+ if not description_found:
107
+ issue = "Missing description"
108
+ recommendation = "Add a meaningful <description> to improve maintainability and clarity."
109
+ else:
110
+ issue = "Unused field detected"
111
+ recommendation = "Remove it to improve performance or document its purpose."
112
+ except Exception as e:
113
+ issue = "Invalid XML"
114
+ recommendation = f"Could not parse metadata XML. Error: {str(e)}"
115
+
116
+ log_data = {
117
+ "Name": f"MetadataLog_{mtype}",
118
+ "MetadataType__c": mtype,
119
+ "IssueDescription__c": issue,
120
+ "Recommendation__c": recommendation,
121
+ "Status__c": "Open"
122
+ }
123
+
124
+ if admin_id:
125
+ log_data["Admin__c"] = admin_id
126
+
127
+ log_to_console(log_data, "Metadata Validation")
128
+
129
+ if sf:
130
+ try:
131
+ result = sf.MetadataAuditLog__c.create(log_data)
132
+ if result.get("success"):
133
+ log_to_console({"Salesforce MetadataAuditLog Record ID": result["id"]}, "Salesforce Create")
134
+ else:
135
+ log_to_console(result, "Salesforce Metadata Error")
136
+ except Exception as e:
137
+ log_to_console({"Salesforce Exception": str(e)}, "Salesforce Error")
138
+ else:
139
+ log_to_console("Salesforce not connected.", "Salesforce Error")
140
+
141
+ return mtype, issue, recommendation
142
+
143
+ # ---------- Salesforce Chatbot (Final Improved Prompt) ----------
144
+ conversation_history = []
145
+
146
+ def salesforce_chatbot(query, history=[]):
147
+ global conversation_history
148
+ if not query.strip():
149
+ return "Please provide a valid Salesforce-related question."
150
+
151
+ salesforce_keywords = [
152
+ "apex", "soql", "trigger", "lwc", "aura", "visualforce", "salesforce", "governor limits",
153
+ "dml", "metadata", "batch apex", "queueable", "future method", "api", "sfdc", "heap", "limits"
154
+ ]
155
+
156
+ if not any(keyword.lower() in query.lower() for keyword in salesforce_keywords):
157
+ return "Please ask a Salesforce-related question."
158
+
159
+ history_summary = "\n".join([f"User: {q}\nAssistant: {a}" for q, a in conversation_history[-4:]])
160
+
161
+ prompt = f"""
162
+ You are a certified Salesforce developer and architect. You answer Salesforce questions with 100% accuracy and clarity, using official platform knowledge.
163
+
164
+ Guidelines:
165
+ - Always give answers that are at least 2 full lines long.
166
+ - When asked about Apex limits (e.g., DML, SOQL, heap), always:
167
+ - Mention the numeric limit (e.g., 150 DML statements)
168
+ - Include the transaction context (sync/async)
169
+ - Suggest using monitoring methods like Limits.getDMLStatements()
170
+ - Avoid making up numbers — if unsure, suggest Trailhead or official docs.
171
+ - Format clearly, using bullet points or code if helpful.
172
+
173
+ Conversation History:
174
+ {history_summary}
175
+
176
+ User: {query.strip()}
177
+ Assistant:
178
+ """
179
+
180
+ try:
181
+ result = qa_pipeline(prompt, max_new_tokens=1024, do_sample=False, temperature=0.1, top_k=50)
182
+ output = result[0]["generated_text"].strip()
183
+ if output.startswith("Assistant:"):
184
+ output = output.replace("Assistant:", "").strip()
185
+
186
+ if len(output.split()) < 20:
187
+ output += "\n\nPlease refer to: https://developer.salesforce.com/docs"
188
+
189
+ conversation_history.append((query, output))
190
+ conversation_history = conversation_history[-6:]
191
+ log_to_console({"Question": query, "Answer": output}, "Chatbot Query")
192
+ return output
193
+ except Exception as e:
194
+ return f"⚠️ Error generating response: {str(e)}"
195
+
196
+ # ---------- Gradio UI ----------
197
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
198
+ gr.Markdown("# 🤖 Advanced Salesforce AI Code Review & Chatbot")
199
+
200
+ with gr.Tab("Code Review"):
201
+ code_input = gr.Textbox(label="Apex / LWC Code", lines=8, placeholder="Enter your Apex or LWC code here")
202
+ issue_type = gr.Textbox(label="Issue Type")
203
+ suggestion = gr.Textbox(label="AI Suggestion")
204
+ severity = gr.Textbox(label="Severity")
205
+ code_button = gr.Button("Analyze Code")
206
+ code_button.click(analyze_code, inputs=code_input, outputs=[issue_type, suggestion, severity])
207
+
208
+ with gr.Tab("Metadata Validation"):
209
+ metadata_input = gr.Textbox(label="Metadata XML", lines=8, placeholder="Enter your metadata XML here")
210
+ mtype = gr.Textbox(label="Type")
211
+ issue = gr.Textbox(label="Issue")
212
+ recommendation = gr.Textbox(label="Recommendation")
213
+ metadata_button = gr.Button("Validate Metadata")
214
+ metadata_button.click(validate_metadata, inputs=metadata_input, outputs=[mtype, issue, recommendation])
215
+
216
+ with gr.Tab("Salesforce Chatbot"):
217
+ chatbot_output = gr.Chatbot(label="Conversation History", height=400)
218
+ query_input = gr.Textbox(label="Your Question", placeholder="e.g., How many DML operations are allowed in Apex?")
219
+ with gr.Row():
220
+ chatbot_button = gr.Button("Ask")
221
+ clear_button = gr.Button("Clear Chat")
222
+ chat_state = gr.State(value=[])
223
+
224
+ def update_chatbot(query, chat_history):
225
+ if not query.strip():
226
+ return chat_history, "Please enter a valid question."
227
+ response = salesforce_chatbot(query, chat_history)
228
+ chat_history.append((query, response))
229
+ return chat_history, ""
230
+
231
+ def clear_chat():
232
+ global conversation_history
233
+ conversation_history = []
234
+ return [], ""
235
+
236
+ chatbot_button.click(fn=update_chatbot, inputs=[query_input, chat_state], outputs=[chatbot_output, query_input])
237
+ clear_button.click(fn=clear_chat, inputs=None, outputs=[chatbot_output, query_input])
238
+
239
+ if __name__ == "__main__":
240
+ demo.launch()
241
+ how can i call an external api from apex?
env ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ SF_USERNAME= aicodereview@sathkrutha.com
2
+ SF_PASSWORD=aicode@123
3
+ SF_SECURITY_TOKEN=AkaHhoPeAZFNNSvw8zuDPxAaF
4
+ SF_DOMAIN=LOGIN
5
+ DEVELOPER_ID=005NS00000Sn2q9
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ transformers>=4.35.0
3
+ torch>=2.0.0
4
+ simple-salesforce>=1.12.3