refs #737: preserve unmatched game mentions in query plan

This commit is contained in:
devmrko
2026-07-27 16:25:33 +09:00
parent 3cc033e4e6
commit 8dffa2f515
5 changed files with 360 additions and 48 deletions

View File

@@ -0,0 +1,52 @@
package com.cloudhandson.vpdbackoffice.service;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import org.junit.jupiter.api.Test;
class GameCatalogVectorServiceTest {
private static final GameCatalogVectorService.GameCandidate CATALOG_GAME =
new GameCatalogVectorService.GameCandidate(
"GAME_KEY",
"GAME_ID",
"GME",
"Catalog Game",
"GME Catalog Game 카탈로그게임",
0.31
);
@Test
void acceptsCandidateWhoseCatalogIdentityContainsTheExtractedMention() {
var match = GameCatalogVectorService.selectMatchedCandidate(
"카탈로그 게임", List.of(CATALOG_GAME));
assertThat(match).contains(CATALOG_GAME);
}
@Test
void rejectsNearestVectorCandidateWithoutCatalogIdentityMatch() {
var match = GameCatalogVectorService.selectMatchedCandidate(
"Unknown title", List.of(CATALOG_GAME));
assertThat(match).isEmpty();
}
@Test
void choosesClosestCandidateAmongIdentityMatches() {
var farther = new GameCatalogVectorService.GameCandidate(
"GAME_KEY_2",
"GAME_ID_2",
"GM2",
"Catalog Game Plus",
"Catalog Game Plus",
0.44
);
var match = GameCatalogVectorService.selectMatchedCandidate(
"Catalog Game", List.of(farther, CATALOG_GAME));
assertThat(match).contains(CATALOG_GAME);
}
}

View File

@@ -245,6 +245,26 @@ class McpSseServiceTest {
.contains("REPORT_UNSUPPORTED");
}
@Test
void keepsUnmatchedMentionsInPartialGameQueryPlan() {
ObjectNode request = request(9, "tools/call");
ObjectNode params = (ObjectNode) request.putObject("params");
params.put("name", "oracle.select_ai.game_query_plan");
params.putObject("arguments")
.put("question", "supported game and unknown game");
ObjectNode response = service.handle("default", request, "user-bearer");
assertThat(response.path("result").path("isError").asBoolean()).isFalse();
String payload = response.path("result").path("content").get(0)
.path("text").asText();
assertThat(payload)
.contains("\"status\" : \"PARTIAL\"")
.contains("\"gameKey\" : \"SUPPORTED_GAME\"")
.contains("\"mention\" : \"Unknown game\"")
.contains("\"reasonCode\" : \"NO_CATALOG_IDENTITY_MATCH\"");
}
private ObjectNode request(int id, String method) {
ObjectNode request = objectMapper.createObjectNode();
request.put("jsonrpc", "2.0");
@@ -351,14 +371,40 @@ class McpSseServiceTest {
@Override
public Resolution resolve(String token, String question, int topK) {
return new Resolution("SINGLE_GAME", java.util.List.of(new GameCandidate(
GameCandidate supported = new GameCandidate(
"SUPPORTED_GAME",
"SUPPORTED_GAME_ID",
"SUPPORTED_PREFIX",
"Supported game",
"Supported",
0.1
)));
);
GameCandidate nearestUnknownCandidate = new GameCandidate(
"OTHER_GAME",
"OTHER_GAME_ID",
"OTHER_PREFIX",
"Other game",
"Other",
0.6
);
return new Resolution(
"MULTI_GAME",
java.util.List.of(supported),
java.util.List.of(
new MentionResolution(
"Supported game",
"MATCHED",
supported,
java.util.List.of(supported)
),
new MentionResolution(
"Unknown game",
"UNMATCHED",
null,
java.util.List.of(nearestUnknownCandidate)
)
)
);
}
}
}