guardia-esn/backend/src/main/java/com/zioinfo/esn/wise/WiseAskController.java

42 lines
1.9 KiB
Java

package com.zioinfo.esn.wise;
import com.zioinfo.esn.common.ApiResponse;
import com.zioinfo.esn.rag.RagAiService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* WISE AI 자유 질의 프록시 — 중앙 guardia-rag {@code /rag/answer} 경유(근거·인용·환각차단).
*
* <p><b>Enterprise AI for Trusted Knowledge.</b> 브라우저 → ESN 백엔드 → 중앙 rag(8020) 프록시.
* 기존 {@code /api/ai/*}(AiController) · {@code /api/ai/rag/*}(RagController) 는 <b>불변</b> —
* 신규 경로만 추가한다. LLM 직접 호출 신설 없음(전부 중앙 rag 경유, {@link RagAiService#wiseAsk} 재사용).
*
* <p><b>인증</b>: SecurityConfig 가 {@code POST /api/**} 를 인증 사용자로 통제 → JWT 뒤에서만 동작.
* <p><b>테넌트 격리</b>: {@code X-Tenant-Code} 헤더 또는 {@code tenantCode} 바디 필드(없으면 솔루션 공용).
* <p><b>보안 불변</b>: 온프레미스 전용. 실패는 요약 메시지(스택/자격증명/PII 미노출).
*/
@RestController
@RequestMapping("/api/wise")
@RequiredArgsConstructor
public class WiseAskController {
private final RagAiService service;
@PostMapping("/ask")
public ApiResponse<Map<String, Object>> ask(
@RequestBody Map<String, Object> req,
@RequestHeader(value = "X-Tenant-Code", required = false) String tenantHeader,
Authentication auth) {
String tenant = (tenantHeader != null && !tenantHeader.isBlank())
? tenantHeader
: (req.get("tenantCode") == null ? null : String.valueOf(req.get("tenantCode")));
String query = req.get("query") == null ? "" : String.valueOf(req.get("query"));
String mode = req.get("retrievalMode") == null ? null : String.valueOf(req.get("retrievalMode"));
return ApiResponse.ok(service.wiseAsk(tenant, query, mode));
}
}