42 lines
1.9 KiB
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));
|
|
}
|
|
}
|