refs #731: add QA vector MCP tools
This commit is contained in:
@@ -12,6 +12,7 @@ class McpSseServiceTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final SelectAiService selectAiService = new CapturingSelectAiService();
|
||||
private final QaVectorService qaVectorService = new CapturingQaVectorService();
|
||||
private final McpSseService service = new McpSseService(
|
||||
selectAiService,
|
||||
objectMapper,
|
||||
@@ -29,16 +30,23 @@ class McpSseServiceTest {
|
||||
"테스트 데이터의 조회 내용을 입력합니다.",
|
||||
"oracle.select_ai.test_data_showprompt",
|
||||
"테스트 데이터 SHOWPROMPT",
|
||||
"테스트 데이터의 Select AI prompt를 조회합니다."
|
||||
)
|
||||
"테스트 데이터의 Select AI prompt를 조회합니다.",
|
||||
"oracle.select_ai.test_qa_vector_search",
|
||||
"테스트 예제 SQL 조회",
|
||||
"테스트 질문에 사용할 예제 SQL을 조회합니다.",
|
||||
"oracle.select_ai.test_qa_vector_store",
|
||||
"테스트 예제 SQL 저장",
|
||||
"테스트 예제 SQL을 저장합니다."
|
||||
),
|
||||
qaVectorService
|
||||
);
|
||||
|
||||
@Test
|
||||
void listsQueryAndShowpromptToolsWithPromptInput() {
|
||||
void listsQueryShowpromptAndQaVectorToolsWithTheirInputs() {
|
||||
ObjectNode response = service.handle("default", request(1, "tools/list"));
|
||||
|
||||
var tools = response.path("result").path("tools");
|
||||
assertThat(tools).hasSize(2);
|
||||
assertThat(tools).hasSize(4);
|
||||
var selectAi = tools.get(0);
|
||||
assertThat(selectAi.path("name").asText()).isEqualTo("oracle.select_ai.test_data_text2sql");
|
||||
assertThat(selectAi.path("description").asText()).contains("SGMP_POC_OCI_GPT54MINI");
|
||||
@@ -58,6 +66,21 @@ class McpSseServiceTest {
|
||||
assertThat(showprompt.path("inputSchema").path("required"))
|
||||
.extracting(node -> node.asText())
|
||||
.contains("prompt");
|
||||
|
||||
var vectorSearch = tools.get(2);
|
||||
assertThat(vectorSearch.path("name").asText())
|
||||
.isEqualTo("oracle.select_ai.test_qa_vector_search");
|
||||
assertThat(vectorSearch.path("inputSchema").path("properties").path("question").path("type").asText())
|
||||
.isEqualTo("string");
|
||||
assertThat(vectorSearch.path("inputSchema").path("properties").path("topK").path("default").asInt())
|
||||
.isEqualTo(3);
|
||||
|
||||
var vectorStore = tools.get(3);
|
||||
assertThat(vectorStore.path("name").asText())
|
||||
.isEqualTo("oracle.select_ai.test_qa_vector_store");
|
||||
assertThat(vectorStore.path("inputSchema").path("required"))
|
||||
.extracting(node -> node.asText())
|
||||
.contains("question", "answerSql");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -120,6 +143,44 @@ class McpSseServiceTest {
|
||||
.contains("권한이 없습니다");
|
||||
}
|
||||
|
||||
@Test
|
||||
void searchesQaVectorExamplesForFewShotContext() {
|
||||
ObjectNode request = request(5, "tools/call");
|
||||
ObjectNode params = (ObjectNode) request.putObject("params");
|
||||
params.put("name", "oracle.select_ai.test_qa_vector_search");
|
||||
params.putObject("arguments").put("question", "active users by game").put("topK", 2);
|
||||
|
||||
ObjectNode response = service.handle("default", request, "user-bearer");
|
||||
|
||||
CapturingQaVectorService vectorService = (CapturingQaVectorService) qaVectorService;
|
||||
assertThat(vectorService.bearerToken).isEqualTo("user-bearer");
|
||||
assertThat(vectorService.question).isEqualTo("active users by game");
|
||||
assertThat(vectorService.topK).isEqualTo(2);
|
||||
assertThat(response.path("result").path("content").get(0).path("text").asText())
|
||||
.contains("QA_VECTOR_SEARCH")
|
||||
.contains("few-shot")
|
||||
.contains("SELECT COUNT(*) FROM APP_USER");
|
||||
}
|
||||
|
||||
@Test
|
||||
void storesReviewedSelectAiExampleSql() {
|
||||
ObjectNode request = request(6, "tools/call");
|
||||
ObjectNode params = (ObjectNode) request.putObject("params");
|
||||
params.put("name", "oracle.select_ai.test_qa_vector_store");
|
||||
params.putObject("arguments")
|
||||
.put("question", "active users by game")
|
||||
.put("answerSql", "SELECT COUNT(*) FROM APP_USER")
|
||||
.put("answer", "AU count");
|
||||
|
||||
ObjectNode response = service.handle("default", request, "user-bearer");
|
||||
|
||||
CapturingQaVectorService vectorService = (CapturingQaVectorService) qaVectorService;
|
||||
assertThat(vectorService.answerSql).isEqualTo("SELECT COUNT(*) FROM APP_USER");
|
||||
assertThat(response.path("result").path("content").get(0).path("text").asText())
|
||||
.contains("QA_VECTOR_STORED")
|
||||
.contains("exampleId");
|
||||
}
|
||||
|
||||
private ObjectNode request(int id, String method) {
|
||||
ObjectNode request = objectMapper.createObjectNode();
|
||||
request.put("jsonrpc", "2.0");
|
||||
@@ -163,4 +224,35 @@ class McpSseServiceTest {
|
||||
.put("selectAiPrompt", "assembled Select AI prompt");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CapturingQaVectorService extends QaVectorService {
|
||||
|
||||
private String bearerToken;
|
||||
private String question;
|
||||
private String answerSql;
|
||||
private int topK;
|
||||
|
||||
private CapturingQaVectorService() {
|
||||
super(null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VectorSearchResult search(String bearerToken, String question, int topK) {
|
||||
this.bearerToken = bearerToken;
|
||||
this.question = question;
|
||||
this.topK = topK;
|
||||
return new VectorSearchResult(question, topK, java.util.List.of(new VectorExample(
|
||||
42L, "active user count", "SELECT COUNT(*) FROM APP_USER", "AU count",
|
||||
"cohere.embed-v4.0", 0.12
|
||||
)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VectorStoreResult store(String bearerToken, String question, String answerSql, String answer) {
|
||||
this.bearerToken = bearerToken;
|
||||
this.question = question;
|
||||
this.answerSql = answerSql;
|
||||
return new VectorStoreResult(77L, question, "cohere.embed-v4.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user