Files changed (1) hide show
  1. app.py +48 -217
app.py CHANGED
@@ -1,225 +1,52 @@
 
1
  import random
2
  import gradio as gr
3
  from datetime import datetime
4
  from transformers import pipeline
 
5
 
6
- # ---------- Label Mapping (Unchanged) ----------
7
- label_to_issue_type = {
8
- "LABEL_0": "Performance",
9
- "LABEL_1": "Error",
10
- "LABEL_2": "Security",
11
- "LABEL_3": "Best Practice"
12
- }
13
 
14
- suggestions = {
15
- "Performance": "Consider optimizing loops and database access. Use collections to reduce SOQL queries.",
16
- "Error": "Add proper error handling and null checks. Use try-catch blocks effectively.",
17
- "Security": "Avoid dynamic SOQL. Use binding variables to prevent SOQL injection.",
18
- "Best Practice": "Refactor for readability and use bulk-safe patterns, such as processing records in batches."
19
- }
20
 
21
- severities = {
22
- "Performance": "Medium",
23
- "Error": "High",
24
- "Security": "High",
25
- "Best Practice": "Low"
26
- }
27
-
28
- # ---------- Mock Salesforce Knowledge Base ----------
29
- salesforce_knowledge_base = {
30
- "governor limits soql": "In Salesforce, the governor limit for SOQL queries is 100 per synchronous transaction and 200 per asynchronous transaction (e.g., Batch Apex, Queueable).",
31
- "governor limits dml": "The governor limit for DML statements is 150 per synchronous or asynchronous transaction.",
32
- "bulkify apex trigger": """
33
- To bulkify an Apex trigger, ensure it handles multiple records to stay within governor limits:
34
- - Use collections (e.g., Lists, Sets, Maps) to process records.
35
- - Perform SOQL queries outside loops.
36
- - Execute DML operations in bulk.
37
- Example:
38
- ```apex
39
- trigger AccountTrigger on Account (before insert) {
40
- Set<String> accountNames = new Set<String>();
41
- for (Account acc : Trigger.new) {
42
- accountNames.add(acc.Name);
43
- }
44
- List<Account> existingAccounts = [SELECT Name FROM Account WHERE Name IN :accountNames];
45
- // Process records
46
- }
47
- ```""",
48
- "soql injection": """
49
- To prevent SOQL injection:
50
- - Use bind variables (e.g., `:variable`) instead of dynamic SOQL.
51
- - Escape single quotes with `String.escapeSingleQuotes()`.
52
- Example:
53
- ```apex
54
- String userInput = 'Test';
55
- List<Account> accounts = [SELECT Name FROM Account WHERE Name = :userInput];
56
- ```""",
57
- "lwc best practices": """
58
- LWC best practices include:
59
- - Use `@api` decorators for public properties.
60
- - Leverage `@wire` for efficient data retrieval.
61
- - Avoid hardcoding IDs; use dynamic queries.
62
- - Follow SLDS for consistent UI.
63
- Example:
64
- ```javascript
65
- import { LightningElement, api } from 'lwc';
66
- export default class MyComponent extends LightningElement {
67
- @api recordId;
68
- }
69
- ```""",
70
- "batch apex": """
71
- Batch Apex processes records in chunks to handle large data volumes:
72
- - Implement `Database.Batchable<SObject>`.
73
- - Use `start`, `execute`, and `finish` methods.
74
- Example:
75
- ```apex
76
- global class MyBatch implements Database.Batchable<SObject> {
77
- global Database.QueryLocator start(Database.BatchableContext bc) {
78
- return Database.getQueryLocator('SELECT Id FROM Account');
79
- }
80
- global void execute(Database.BatchableContext bc, List<SObject> scope) {
81
- // Process records
82
- }
83
- global void finish(Database.BatchableContext bc) {}
84
- }
85
- ```""",
86
- }
87
-
88
- # ---------- Load QnA Model ----------
89
  try:
90
- qa_pipeline = pipeline("text2text-generation", model="google/flan-t5-large")
 
 
 
 
 
 
91
  except Exception as e:
92
- print(f"Model loading error: {e}. Falling back to flan-t5-base.")
93
- qa_pipeline = pipeline("text2text-generation", model="google/flan-t5-base")
94
-
95
- # ---------- Local Logging (Unchanged) ----------
96
- def log_to_console(data, log_type):
97
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
98
- print(f"[{timestamp}] {log_type} Log: {data}")
99
-
100
- # ---------- Code Analyzer (Unchanged) ----------
101
- def analyze_code(code):
102
- if not code.strip():
103
- return "No code provided.", "", ""
104
-
105
- label = random.choice(list(label_to_issue_type.keys()))
106
- issue_type = label_to_issue_type[label]
107
- suggestion = suggestions[issue_type]
108
- severity = severities[issue_type]
109
-
110
- log_data = {
111
- "Name": f"Review_{issue_type}",
112
- "CodeSnippet": code,
113
- "IssueType": issue_type,
114
- "Suggestion": suggestion,
115
- "Severity": severity
116
- }
117
- log_to_console(log_data, "Code Review")
118
-
119
- return issue_type, suggestion, severity
120
-
121
- # ---------- Metadata Validator (Unchanged) ----------
122
- def validate_metadata(metadata):
123
- if not metadata.strip():
124
- return "No metadata provided.", "", ""
125
-
126
- mtype = "Field"
127
- issue = "Unused field detected"
128
- recommendation = "Remove it to improve performance or document its purpose."
129
-
130
- log_data = {
131
- "Name": f"MetadataLog_{mtype}",
132
- "MetadataType": mtype,
133
- "IssueDescription": issue,
134
- "Recommendation": recommendation,
135
- "Status": "Open"
136
- }
137
- log_to_console(log_data, "Metadata Validation")
138
-
139
- return mtype, issue, recommendation
140
-
141
- # ---------- Advanced Salesforce Chatbot ----------
142
- conversation_history = []
143
-
144
- def salesforce_chatbot(query, history=[]):
145
- global conversation_history
146
- if not query.strip():
147
- return "Please provide a valid Salesforce-related question."
148
-
149
- # Expanded Salesforce keywords
150
- salesforce_keywords = [
151
- "apex", "soql", "sosl", "trigger", "lwc", "aura", "visualforce", "salesforce",
152
- "governor limits", "bulkification", "dml", "query", "metadata", "flow",
153
- "process builder", "sobject", "schema", "lightning", "custom object",
154
- "validation rule", "workflow", "platform event", "batch apex", "queueable",
155
- "future method", "lightning web component", "api", "rest", "soap", "integration",
156
- "trigger", "profile", "permission set", "sharing rule", "field", "record type",
157
- "crm", "sfdc", "force.com"
158
- ]
159
 
160
- # Check if query is Salesforce-related
161
- if not any(keyword.lower() in query.lower() for keyword in salesforce_keywords):
162
- return "Please ask a Salesforce-related question (e.g., about Apex, SOQL, LWC, or Salesforce platform features)."
163
-
164
- # Check knowledge base for exact matches
165
- query_key = query.lower().strip()
166
- for kb_key, kb_answer in salesforce_knowledge_base.items():
167
- if kb_key in query_key:
168
- # Store in conversation history
169
- conversation_history.append((query, kb_answer))
170
- conversation_history = conversation_history[-6:] # Keep last 6 exchanges
171
- log_to_console({"Question": query, "Answer": kb_answer}, "Chatbot Query")
172
- return kb_answer
173
-
174
- # Build conversation context
175
- history_summary = "\n".join([f"User: {q}\nAssistant: {a}" for q, a in conversation_history[-4:]])
176
- prompt = f"""
177
- You are an expert Salesforce developer with deep knowledge of Apex, SOQL, SOSL, LWC, Aura, Visualforce, and Salesforce platform features. Your role is to provide 100% accurate answers based strictly on Salesforce official documentation and best practices (e.g., governor limits: 100 SOQL queries, 150 DML statements per transaction). Follow these guidelines:
178
- - Provide concise, accurate answers with no speculation.
179
- - Include code snippets in ```apex``` or ```javascript``` blocks for technical questions.
180
- - Reference governor limits or best practices explicitly.
181
- - If the question is ambiguous, ask for clarification within the response.
182
- - Use bullet points for lists or steps.
183
- - Leverage conversation history for context.
184
- - If unsure, admit limitations and suggest checking Salesforce documentation or Trailhead.
185
-
186
- Conversation History:
187
- {history_summary}
188
-
189
- Question: {query.strip()}
190
- Answer:
191
- """
192
 
193
  try:
194
- # Generate response with strict parameters
195
- result = qa_pipeline(prompt, max_new_tokens=1024, do_sample=False, temperature=0.1, top_k=50)
196
- output = result[0]["generated_text"].strip()
197
-
198
- # Clean up response
199
- if output.startswith("Answer:"):
200
- output = output[7:].strip()
201
-
202
- # Validate response quality
203
- if len(output) < 20 or output.lower() in ["unknown", "i don't know", "not sure"]:
204
- output = f"I'm sorry, I couldn't find a precise answer for '{query}'. Please clarify or refer to Salesforce documentation at https://developer.salesforce.com/docs."
205
-
206
- # Store in conversation history
207
- conversation_history.append((query, output))
208
- conversation_history = conversation_history[-6:] # Keep last 6 exchanges
209
-
210
- # Log question and answer
211
- log_to_console({"Question": query, "Answer": output}, "Chatbot Query")
212
-
213
- return output
214
  except Exception as e:
215
- error_msg = f"⚠️ Error generating response: {str(e)}. Please try rephrasing your question or check Salesforce documentation at https://developer.salesforce.com/docs."
216
- log_to_console({"Question": query, "Error": error_msg}, "Chatbot Error")
217
- return error_msg
218
 
219
  # ---------- Gradio UI ----------
220
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
221
  gr.Markdown("# 🤖 Advanced Salesforce AI Code Review & Chatbot")
222
 
 
223
  with gr.Tab("Code Review"):
224
  code_input = gr.Textbox(label="Apex / LWC Code", lines=8, placeholder="Enter your Apex or LWC code here")
225
  issue_type = gr.Textbox(label="Issue Type")
@@ -228,6 +55,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
228
  code_button = gr.Button("Analyze Code")
229
  code_button.click(analyze_code, inputs=code_input, outputs=[issue_type, suggestion, severity])
230
 
 
231
  with gr.Tab("Metadata Validation"):
232
  metadata_input = gr.Textbox(label="Metadata XML", lines=8, placeholder="Enter your metadata XML here")
233
  mtype = gr.Textbox(label="Type")
@@ -236,6 +64,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
236
  metadata_button = gr.Button("Validate Metadata")
237
  metadata_button.click(validate_metadata, inputs=metadata_input, outputs=[mtype, issue, recommendation])
238
 
 
239
  with gr.Tab("Salesforce Chatbot"):
240
  gr.Markdown("### Ask a Salesforce Question\nGet expert answers on Apex, SOQL, LWC, and more!")
241
  chatbot_output = gr.Chatbot(label="Conversation History", height=400)
@@ -243,8 +72,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
243
  with gr.Row():
244
  chatbot_button = gr.Button("Ask")
245
  clear_button = gr.Button("Clear Chat")
246
-
247
- # State to manage chat history
248
  chat_state = gr.State(value=[])
249
 
250
  def update_chatbot(query, chat_history):
@@ -259,17 +87,20 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
259
  conversation_history = []
260
  return [], ""
261
 
262
- chatbot_button.click(
263
- fn=update_chatbot,
264
- inputs=[query_input, chat_state],
265
- outputs=[chatbot_output, query_input]
266
- )
267
- clear_button.click(
268
- fn=clear_chat,
269
- inputs=None,
270
- outputs=[chatbot_output, query_input]
271
- )
 
 
 
272
 
273
  # ---------- Start UI ----------
274
  if __name__ == "__main__":
275
- demo.launch()
 
1
+ # [All your existing imports]
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, SFType
7
 
8
+ # [Your existing mappings, knowledge base, and model loading code remain unchanged]
 
 
 
 
 
 
9
 
10
+ # ---------- Salesforce Connection Setup ----------
11
+ # Replace these with your actual Salesforce credentials or use environment variables for security
12
+ SF_USERNAME = "your_username@example.com"
13
+ SF_PASSWORD = "your_password"
14
+ SF_SECURITY_TOKEN = "your_security_token"
 
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  try:
17
+ session_id, instance = SalesforceLogin(
18
+ username=SF_USERNAME,
19
+ password=SF_PASSWORD,
20
+ security_token=SF_SECURITY_TOKEN
21
+ )
22
+ sf = Salesforce(instance=instance, session_id=session_id)
23
+ print("✅ Connected to Salesforce successfully")
24
  except Exception as e:
25
+ sf = None
26
+ print(f" Failed to connect to Salesforce: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ # ---------- Function to Create Salesforce Record ----------
29
+ def create_salesforce_record(object_type, field_name, field_value):
30
+ if not sf:
31
+ return "Salesforce connection not established."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  try:
34
+ sobject = SFType(object_type, sf.session_id, sf.sf_instance)
35
+ result = sobject.create({field_name: field_value})
36
+ if result.get("success"):
37
+ return f"✅ Record created successfully in {object_type} with ID: {result['id']}"
38
+ else:
39
+ return f"❌ Failed to create record: {result}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  except Exception as e:
41
+ return f"⚠️ Error: {str(e)}"
42
+
43
+ # [Your existing functions: analyze_code, validate_metadata, salesforce_chatbot, etc. remain unchanged]
44
 
45
  # ---------- Gradio UI ----------
46
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
47
  gr.Markdown("# 🤖 Advanced Salesforce AI Code Review & Chatbot")
48
 
49
+ # Tab 1: Code Review
50
  with gr.Tab("Code Review"):
51
  code_input = gr.Textbox(label="Apex / LWC Code", lines=8, placeholder="Enter your Apex or LWC code here")
52
  issue_type = gr.Textbox(label="Issue Type")
 
55
  code_button = gr.Button("Analyze Code")
56
  code_button.click(analyze_code, inputs=code_input, outputs=[issue_type, suggestion, severity])
57
 
58
+ # Tab 2: Metadata Validation
59
  with gr.Tab("Metadata Validation"):
60
  metadata_input = gr.Textbox(label="Metadata XML", lines=8, placeholder="Enter your metadata XML here")
61
  mtype = gr.Textbox(label="Type")
 
64
  metadata_button = gr.Button("Validate Metadata")
65
  metadata_button.click(validate_metadata, inputs=metadata_input, outputs=[mtype, issue, recommendation])
66
 
67
+ # Tab 3: Salesforce Chatbot
68
  with gr.Tab("Salesforce Chatbot"):
69
  gr.Markdown("### Ask a Salesforce Question\nGet expert answers on Apex, SOQL, LWC, and more!")
70
  chatbot_output = gr.Chatbot(label="Conversation History", height=400)
 
72
  with gr.Row():
73
  chatbot_button = gr.Button("Ask")
74
  clear_button = gr.Button("Clear Chat")
75
+
 
76
  chat_state = gr.State(value=[])
77
 
78
  def update_chatbot(query, chat_history):
 
87
  conversation_history = []
88
  return [], ""
89
 
90
+ chatbot_button.click(fn=update_chatbot, inputs=[query_input, chat_state], outputs=[chatbot_output, query_input])
91
+ clear_button.click(fn=clear_chat, inputs=None, outputs=[chatbot_output, query_input])
92
+
93
+ # Tab 4: Create Salesforce Record
94
+ with gr.Tab("Create Salesforce Record"):
95
+ gr.Markdown("### 📇 Create a New Salesforce Record")
96
+ object_type = gr.Textbox(label="Salesforce Object API Name", placeholder="e.g., Account")
97
+ field_name = gr.Textbox(label="Field API Name", placeholder="e.g., Name")
98
+ field_value = gr.Textbox(label="Field Value", placeholder="e.g., Test Company")
99
+ create_button = gr.Button("Create Record")
100
+ record_result = gr.Textbox(label="Result")
101
+
102
+ create_button.click(create_salesforce_record, inputs=[object_type, field_name, field_value], outputs=record_result)
103
 
104
  # ---------- Start UI ----------
105
  if __name__ == "__main__":
106
+ demo.launch()