Skip to content

Commit 8779839

Browse files
Copilotphrocker
andauthored
Add refine button to prompt advisor page (#187)
* Initial plan * Add refine button to prompt advisor page with backend support for validation after refinement Co-authored-by: phrocker <[email protected]> * Address code review feedback: fix formatting and use ID-based prompt storage Co-authored-by: phrocker <[email protected]> * Implement LLM-based prompt refinement that actually calls the LLM to rewrite prompts Co-authored-by: phrocker <[email protected]> * Address code review feedback: fix edge cases and improve error handling Co-authored-by: phrocker <[email protected]> * Always show refined prompt in UI, with indicator if unchanged Co-authored-by: phrocker <[email protected]> * cokmmit --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: phrocker <[email protected]> Co-authored-by: Marc Parisi <[email protected]>
1 parent 8a6cd63 commit 8779839

File tree

10 files changed

+696
-100
lines changed

10 files changed

+696
-100
lines changed

api/src/main/java/io/sentrius/sso/controllers/api/PromptAdvisorApiController.java

Lines changed: 68 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
package io.sentrius.sso.controllers.api;
22

33
import io.sentrius.sso.core.annotations.LimitAccess;
4+
import io.sentrius.sso.core.config.SystemOptions;
5+
import io.sentrius.sso.core.controllers.BaseController;
46
import io.sentrius.sso.core.model.security.enums.ApplicationAccessEnum;
7+
import io.sentrius.sso.core.model.verbs.Endpoint;
8+
import io.sentrius.sso.core.promptadvisor.model.RefinePromptResponse;
9+
import io.sentrius.sso.core.promptadvisor.model.ValidatePromptRequest;
10+
import io.sentrius.sso.core.promptadvisor.service.PromptAdvisorService;
11+
import io.sentrius.sso.core.services.ErrorOutputService;
12+
import io.sentrius.sso.core.services.UserService;
13+
import jakarta.servlet.http.HttpServletRequest;
14+
import jakarta.servlet.http.HttpServletResponse;
515
import lombok.extern.slf4j.Slf4j;
616
import org.springframework.beans.factory.annotation.Value;
717
import org.springframework.http.*;
@@ -17,13 +27,23 @@
1727
@Slf4j
1828
@RestController
1929
@RequestMapping("/api/v1/prompt-advisor")
20-
public class PromptAdvisorApiController {
30+
public class PromptAdvisorApiController extends BaseController {
2131

2232
private final RestTemplate restTemplate = new RestTemplate();
33+
private final PromptAdvisorService promptAdvisorService;
34+
2335

2436
@Value("${sentrius.prompt-advisor.url:http://sentrius-prompt-advisor:80}")
2537
private String promptAdvisorUrl;
2638

39+
protected PromptAdvisorApiController(
40+
UserService userService, SystemOptions systemOptions,
41+
ErrorOutputService errorOutputService, PromptAdvisorService promptAdvisorService
42+
) {
43+
super(userService, systemOptions, errorOutputService);
44+
this.promptAdvisorService = promptAdvisorService;
45+
}
46+
2747
/**
2848
* Get current ATPL criteria and their weights
2949
*/
@@ -72,54 +92,54 @@ public ResponseEntity<Map<String, Object>> validatePrompt(@RequestBody Map<Strin
7292
* Interactive prompt refinement session
7393
*/
7494
@PostMapping("/refine")
75-
@LimitAccess(applicationAccess = {ApplicationAccessEnum.CAN_MANAGE_APPLICATION})
76-
public ResponseEntity<Map<String, Object>> refinePrompt(@RequestBody Map<String, Object> request) {
77-
try {
78-
// First validate the prompt
79-
String prompt = (String) request.get("prompt");
80-
String sessionId = (String) request.getOrDefault("sessionId", UUID.randomUUID().toString());
81-
82-
Map<String, Object> validateRequest = new HashMap<>();
83-
validateRequest.put("prompt", prompt);
84-
85-
// Only include context if it's a non-empty Map (prompt-advisor expects Dict or null)
86-
Object contextObj = request.get("context");
87-
if (contextObj instanceof Map && !((Map<?, ?>) contextObj).isEmpty()) {
88-
validateRequest.put("context", contextObj);
89-
}
90-
// If context is null or not provided, don't include it - let the service use its default
91-
92-
String url = promptAdvisorUrl + "/validate_prompt";
93-
94-
HttpHeaders headers = new HttpHeaders();
95-
headers.setContentType(MediaType.APPLICATION_JSON);
96-
97-
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(validateRequest, headers);
98-
99-
ResponseEntity<Map> response = restTemplate.postForEntity(url, entity, Map.class);
100-
Map<String, Object> validationResult = response.getBody();
101-
102-
// Build refinement response with suggestions
103-
Map<String, Object> refinementResponse = new HashMap<>();
104-
refinementResponse.put("sessionId", sessionId);
105-
refinementResponse.put("originalPrompt", prompt);
106-
refinementResponse.put("score", validationResult.get("score"));
107-
refinementResponse.put("ratings", validationResult.get("ratings"));
108-
refinementResponse.put("explanation", validationResult.get("explanation"));
109-
refinementResponse.put("recommendations", validationResult.get("recommendations"));
110-
111-
// Generate refinement suggestions based on scores
112-
List<String> suggestions = generateRefinementSuggestions(validationResult);
113-
refinementResponse.put("suggestions", suggestions);
114-
115-
return ResponseEntity.ok(refinementResponse);
116-
} catch (Exception e) {
117-
log.error("Error refining prompt with prompt-advisor", e);
118-
Map<String, Object> error = new HashMap<>();
119-
error.put("status", "error");
120-
error.put("message", "Failed to refine prompt: " + e.getMessage());
121-
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(error);
95+
@Endpoint(description = "Refine a prompt using LLM to apply recommendations and improve quality")
96+
public ResponseEntity<?> refinePrompt(
97+
@RequestBody ValidatePromptRequest request,
98+
HttpServletRequest httpRequest,
99+
HttpServletResponse httpResponse
100+
) {
101+
if (!systemOptions.getEnablePromptAdvisor()) {
102+
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
103+
.body(Map.of("error", "Prompt advisor service is disabled"));
122104
}
105+
106+
var operatingUser = getOperatingUser(httpRequest, httpResponse);
107+
if (operatingUser == null) {
108+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
109+
.body(Map.of("error", "Authentication required"));
110+
}
111+
112+
log.info("Refining prompt using LLM for user: {}", operatingUser.getUsername());
113+
114+
// Use the new LLM-based refinement that actually rewrites the prompt
115+
RefinePromptResponse refineResponse = promptAdvisorService.refinePromptWithLLM(
116+
request.getPrompt(),
117+
request.getContext()
118+
);
119+
120+
if (refineResponse == null) {
121+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
122+
.body(Map.of("error", "Failed to refine prompt"));
123+
}
124+
125+
// Build response with all refinement data
126+
Map<String, Object> result = new HashMap<>();
127+
result.put("original_prompt", refineResponse.getOriginalPrompt());
128+
result.put("refined_prompt", refineResponse.getRefinedPrompt());
129+
if (refineResponse.getScore() != null) {
130+
result.put("score", refineResponse.getScore());
131+
}
132+
if (refineResponse.getRatings() != null) {
133+
result.put("ratings", refineResponse.getRatings());
134+
}
135+
if (refineResponse.getExplanation() != null) {
136+
result.put("explanation", refineResponse.getExplanation());
137+
}
138+
if (refineResponse.getRecommendations() != null) {
139+
result.put("recommendations", refineResponse.getRecommendations());
140+
}
141+
142+
return ResponseEntity.ok(result);
123143
}
124144

125145
/**

0 commit comments

Comments
 (0)