Skip to content

Commit aabeb81

Browse files
Copilotfadidurah
andcommitted
Use AI model for impact detection instead of rigid regex matching
Co-authored-by: fadidurah <88730756+fadidurah@users.noreply.github.com>
1 parent 158da77 commit aabeb81

File tree

1 file changed

+121
-46
lines changed

1 file changed

+121
-46
lines changed

.github/workflows/copilot-issue-response.yml

Lines changed: 121 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -697,24 +697,20 @@ jobs:
697697
698698
// Prompt for customer impact data if not a simple question
699699
if (issueType === 'needs-investigation' || issueType === 'feature-request') {
700-
const bodyLower = (issue.body || '').toLowerCase();
701-
// Tightened regex: require "affected" or "impacted" to appear with the number
702-
// This avoids false positives like "Android 14 device"
703-
const hasImpactInfo = /\d+\s*(?:device|user|customer)s?\s+(?:affected|impacted)/i.test(issue.body || '') ||
704-
/(?:affected|impacted)[^\d]*\d+\s*(?:device|user|customer)/i.test(issue.body || '') ||
705-
bodyLower.includes('p0') || bodyLower.includes('p1') ||
706-
bodyLower.includes('codered') || bodyLower.includes('high priority');
700+
// Use simple check - just look for any number that might indicate impact
701+
// AI will do the real analysis in PING-COPILOT responses
702+
const hasAnyNumber = /\d{2,}/.test(issue.body || '');
703+
const hasPriorityKeyword = (issue.body || '').toLowerCase().includes('p0') ||
704+
(issue.body || '').toLowerCase().includes('p1') ||
705+
(issue.body || '').toLowerCase().includes('priority');
707706
708-
if (!hasImpactInfo) {
707+
if (!hasAnyNumber && !hasPriorityKeyword) {
709708
response += `### 📊 Help Us Prioritize\n\n`;
710709
response += `To help the team prioritize this issue, please provide information about customer impact:\n\n`;
711710
response += `\`\`\`\n`;
712711
response += `PING-COPILOT: We have <number> devices/users affected by this issue\n`;
713712
response += `\`\`\`\n\n`;
714-
response += `Or if this is blocking production or critical scenarios:\n`;
715-
response += `\`\`\`\n`;
716-
response += `PING-COPILOT: This is a production-blocking/critical issue affecting <specific impact details>\n`;
717-
response += `\`\`\`\n\n`;
713+
response += `The AI will analyze your impact information and apply the appropriate priority label based on device count thresholds.\n\n`;
718714
response += `---\n\n`;
719715
}
720716
}
@@ -775,7 +771,7 @@ jobs:
775771
core.setOutput('has_request', 'false');
776772
}
777773
778-
- name: Detect Customer Impact and Apply Priority
774+
- name: Detect Customer Impact with AI
779775
if: steps.extract_request.outputs.has_request == 'true'
780776
id: detect_impact
781777
uses: actions/github-script@v7
@@ -785,55 +781,131 @@ jobs:
785781
script: |
786782
const userRequest = process.env.USER_REQUEST;
787783
const issue = context.payload.issue;
788-
const requestLower = userRequest.toLowerCase();
789784
790-
// Detect customer impact indicators
785+
// Use AI to detect customer impact from the user's request
786+
// Focus on device count as primary indicator, as per guidelines
791787
let priorityLevel = null;
792788
let impactReason = '';
789+
let deviceCount = null;
793790
794-
// Check for numeric impact (devices/users)
795-
const deviceMatch = userRequest.match(/(\d+)\s*(device|user|customer|install|affected|impacted)/i);
796-
if (deviceMatch) {
797-
const count = parseInt(deviceMatch[1], 10);
798-
if (count >= 10000) {
791+
try {
792+
// Construct AI prompt to extract impact information
793+
const impactPrompt = "Analyze the following text and extract customer impact information. " +
794+
"Focus on finding the NUMBER of devices or users affected. " +
795+
"Respond with ONLY a JSON object in this format: " +
796+
'{"deviceCount": <number or null>, "hasExplicitPriority": <boolean>, "explicitPriority": "<p0|p1|null>"}. ' +
797+
"Examples:\n" +
798+
'- "We have 500 devices affected" → {"deviceCount": 500, "hasExplicitPriority": false, "explicitPriority": null}\n' +
799+
'- "This is a p0 issue" → {"deviceCount": null, "hasExplicitPriority": true, "explicitPriority": "p0"}\n' +
800+
'- "Critical question about config" → {"deviceCount": null, "hasExplicitPriority": false, "explicitPriority": null}\n' +
801+
"Text to analyze: " + userRequest;
802+
803+
const response = await github.request('POST /models/chat/completions', {
804+
model: 'gpt-4o-mini',
805+
messages: [
806+
{
807+
role: 'system',
808+
content: 'You are a data extraction assistant. Extract impact information and respond with only valid JSON. No explanations, just JSON.'
809+
},
810+
{
811+
role: 'user',
812+
content: impactPrompt
813+
}
814+
],
815+
temperature: 0.1,
816+
max_tokens: 200
817+
});
818+
819+
const aiResult = response.data.choices[0].message.content.trim();
820+
console.log('AI impact detection result:', aiResult);
821+
822+
// Parse AI response
823+
const extracted = JSON.parse(aiResult);
824+
deviceCount = extracted.deviceCount;
825+
826+
// Apply priority based on device count (primary method)
827+
if (deviceCount !== null && deviceCount > 0) {
828+
if (deviceCount >= 10000) {
829+
priorityLevel = 'p0-CodeRed';
830+
impactReason = `${deviceCount} devices/users affected`;
831+
} else if (deviceCount >= 1000) {
832+
priorityLevel = 'p1-High';
833+
impactReason = `${deviceCount} devices/users affected`;
834+
} else if (deviceCount >= 300) {
835+
priorityLevel = 'p2-Medium';
836+
impactReason = `${deviceCount} devices/users affected`;
837+
} else if (deviceCount >= 100) {
838+
priorityLevel = 'p3-Low';
839+
impactReason = `${deviceCount} devices/users affected`;
840+
} else {
841+
priorityLevel = 'p4-Minor';
842+
impactReason = `${deviceCount} devices/users affected`;
843+
}
844+
}
845+
846+
// Check for explicit priority mentions (secondary method)
847+
if (extracted.hasExplicitPriority && extracted.explicitPriority) {
848+
const explicitPri = extracted.explicitPriority.toLowerCase();
849+
if (explicitPri === 'p0' || explicitPri === 'codered') {
850+
priorityLevel = 'p0-CodeRed';
851+
if (!impactReason) impactReason = 'Customer explicitly requested priority p0/CodeRed';
852+
} else if (explicitPri === 'p1') {
853+
if (!priorityLevel || priorityLevel === 'p2-Medium' || priorityLevel === 'p3-Low' || priorityLevel === 'p4-Minor') {
854+
priorityLevel = 'p1-High';
855+
if (!impactReason) impactReason = 'Customer explicitly requested priority p1/High';
856+
}
857+
}
858+
}
859+
860+
} catch (error) {
861+
console.log('AI impact detection failed, using fallback regex:', error.message);
862+
863+
// Fallback to simple regex if AI fails
864+
const deviceMatch = userRequest.match(/(\d+)\s*(device|user|customer|install|affected|impacted)/i);
865+
if (deviceMatch) {
866+
const count = parseInt(deviceMatch[1], 10);
867+
deviceCount = count;
868+
869+
if (count >= 10000) {
870+
priorityLevel = 'p0-CodeRed';
871+
impactReason = `${count} ${deviceMatch[2]}s affected`;
872+
} else if (count >= 1000) {
873+
priorityLevel = 'p1-High';
874+
impactReason = `${count} ${deviceMatch[2]}s affected`;
875+
} else if (count >= 300) {
876+
priorityLevel = 'p2-Medium';
877+
impactReason = `${count} ${deviceMatch[2]}s affected`;
878+
} else if (count >= 100) {
879+
priorityLevel = 'p3-Low';
880+
impactReason = `${count} ${deviceMatch[2]}s affected`;
881+
} else if (count > 0) {
882+
priorityLevel = 'p4-Minor';
883+
impactReason = `${count} ${deviceMatch[2]}s affected`;
884+
}
885+
}
886+
887+
// Check for explicit priority mentions
888+
if (requestLower.includes('p0') || requestLower.includes('codered')) {
799889
priorityLevel = 'p0-CodeRed';
800-
impactReason = `${count} ${deviceMatch[2]}s affected`;
801-
} else if (count >= 1000) {
890+
if (!impactReason) impactReason = 'Customer explicitly requested priority p0/CodeRed';
891+
}
892+
893+
if (!priorityLevel && (requestLower.includes('p1') || requestLower.includes('high priority'))) {
802894
priorityLevel = 'p1-High';
803-
impactReason = `${count} ${deviceMatch[2]}s affected`;
804-
} else if (count >= 300) {
805-
priorityLevel = 'p2-Medium';
806-
impactReason = `${count} ${deviceMatch[2]}s affected`;
807-
} else if (count >= 100) {
808-
priorityLevel = 'p3-Low';
809-
impactReason = `${count} ${deviceMatch[2]}s affected`;
810-
} else if (count > 0) {
811-
priorityLevel = 'p4-Minor';
812-
impactReason = `${count} ${deviceMatch[2]}s affected`;
895+
if (!impactReason) impactReason = 'High priority issue reported';
813896
}
814897
}
815898
816-
// Check for explicit p0-CodeRed indicators (always set p0-CodeRed if detected, as it should override other priorities)
817-
// Restrict to explicit priority mentions to avoid false positives from general urgency words
818-
if (requestLower.includes('p0') || requestLower.includes('codered')) {
819-
priorityLevel = 'p0-CodeRed';
820-
if (!impactReason) impactReason = 'Customer explicitly requested priority p0/CodeRed';
821-
}
822-
823-
// Check for p1-High indicators (only if no higher priority already set)
824-
if (!priorityLevel && (requestLower.includes('p1') || requestLower.includes('high') ||
825-
requestLower.includes('major'))) {
826-
priorityLevel = 'p1-High';
827-
if (!impactReason) impactReason = 'High priority issue reported';
828-
}
829-
830899
core.setOutput('has_impact', priorityLevel ? 'true' : 'false');
831900
core.setOutput('priority_level', priorityLevel || '');
832901
core.setOutput('impact_reason', impactReason);
902+
core.setOutput('device_count', deviceCount !== null ? deviceCount.toString() : '');
833903
834904
if (priorityLevel) {
835905
console.log(`Customer impact detected: ${priorityLevel} - ${impactReason}`);
836906
}
907+
908+
}
837909
838910
- name: Apply Priority Label
839911
if: steps.detect_impact.outputs.has_impact == 'true'
@@ -931,6 +1003,7 @@ jobs:
9311003
HAS_IMPACT: ${{ steps.detect_impact.outputs.has_impact }}
9321004
PRIORITY_LEVEL: ${{ steps.detect_impact.outputs.priority_level }}
9331005
IMPACT_REASON: ${{ steps.detect_impact.outputs.impact_reason }}
1006+
DEVICE_COUNT: ${{ steps.detect_impact.outputs.device_count }}
9341007
COPILOT_INSTRUCTIONS: ${{ steps.fetch_guidance.outputs.copilot_instructions }}
9351008
COMMON_ISSUES: ${{ steps.fetch_guidance.outputs.common_issues }}
9361009
with:
@@ -939,6 +1012,7 @@ jobs:
9391012
const hasImpact = process.env.HAS_IMPACT === 'true';
9401013
const priorityLevel = process.env.PRIORITY_LEVEL;
9411014
const impactReason = process.env.IMPACT_REASON;
1015+
const deviceCount = process.env.DEVICE_COUNT;
9421016
const copilotInstructions = process.env.COPILOT_INSTRUCTIONS;
9431017
const commonIssues = process.env.COMMON_ISSUES;
9441018
const issue = context.payload.issue;
@@ -1007,6 +1081,7 @@ jobs:
10071081
"Title: " + issueTitle + "\n" +
10081082
"Description: " + issueBody + "\n\n" +
10091083
"User Question: " + sanitizedUserRequest + "\n\n" +
1084+
(deviceCount ? "Customer Impact: " + deviceCount + " devices/users affected\n\n" : "") +
10101085
"MSAL Latest Version: " + latestVersion + "\n\n" +
10111086
"Please provide a detailed, helpful response to the user's question based on the guidance documents. Focus on practical solutions and include relevant examples.";
10121087

0 commit comments

Comments
 (0)