feat(wiki): PR-5 wikilink alias parsing + relation seed filter

This commit is contained in:
matevip 2026-04-25 09:56:19 +08:00
parent b41496ed46
commit ec0aaf7da6
2 changed files with 20 additions and 3 deletions

View File

@ -278,6 +278,12 @@ public class HybridRetriever {
List<WikiPageLite> seedLites = pageMapper.selectBatchLite(List.of(seedId));
if (seedLites.isEmpty()) continue;
WikiPageLite seed = seedLites.get(0);
// RFC-051 PR-5: don't expand 1-hop neighborhood from a system page seed.
// Otherwise the overview / log neighborhood typically every page that
// shares a raw with them leaks into search results via boost. PR-2's
// result-emit filter drops the system pages themselves; this guard ensures
// we don't even use them as expansion roots.
if (seed.isSystem()) continue;
try {
relationService.relatedPages(kbId, seed.slug(), 3)
.forEach(r -> {

View File

@ -472,15 +472,26 @@ public class WikiPageService {
}
/**
* Markdown 内容中提取 [[links]] 并返回 JSON 数组
* Extract {@code [[links]]} (and {@code [[target|label]]} alias form,
* RFC-051 PR-5) from Markdown content and return them as a JSON array of
* canonical slugs.
* <p>
* For aliased links the {@code label} part is purely display only
* {@code target} feeds slug resolution. Without this split we'd canonicalize
* "Spring AI|Spring AI Alibaba" as a single slug, polluting outgoingLinks
* and breaking graph view / backlinks.
*/
String extractLinksAsJson(String content) {
if (content == null) return "[]";
List<String> links = new ArrayList<>();
Matcher matcher = WIKI_LINK_PATTERN.matcher(content);
while (matcher.find()) {
String link = matcher.group(1).trim();
String slug = toSlug(link);
String raw = matcher.group(1).trim();
int pipe = raw.indexOf('|');
String target = pipe >= 0 ? raw.substring(0, pipe).trim() : raw;
if (target.isEmpty()) continue;
String slug = toSlug(target);
if (slug.isEmpty()) continue;
if (!links.contains(slug)) {
links.add(slug);
}