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