mateclaw/mateclaw-server/src/main/java/vip/mate/wiki/relation/SharedChunkSignal.java
matevip 3d213eb281 chore: sync multiple commits from private dev
Covers 15 upstream commits (private mirror → public):

Multi-provider failover (RFC-009):
- PR-0: extract ChatModelBuilder strategy seam
- PR-1a: AvailableProviderPool data structure
- PR-1b: startup provider liveness probe + 4 protocol strategies
- PR-1c: wire AvailableProviderPool into runtime chat-model selection
- PR-1d: provider pool REST endpoint + UI badges
- PR-1e: manual reprobe trigger + auto-reprobe on provider config change
- PR-3: per-agent provider preferences (agents can override the
  org-wide fallback chain)

Wiki subsystem (RFC-029~033):
- Relation model, resilient background jobs, light-weight processing
  path, retrieval enhancement, frontend redesign (single landing commit)
- Follow-up fixes: null guards + stats query + i18n polish, move
  WikiProcessingJobMapper to repository/ for @MapperScan, align
  implementation with RFC-029~031 spec
- Copy pass: replace "富化 / enrich" wording with clearer "链接 / link"
- Style: switch enrich/repair buttons to @element-plus/icons-vue
2026-04-19 18:37:44 +08:00

45 lines
1.4 KiB
Java

package vip.mate.wiki.relation;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import vip.mate.wiki.dto.PageCitationWithRaw;
import vip.mate.wiki.repository.WikiPageCitationMapper;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* RFC-029: Shared-chunk signal — pages that share the same source chunk
* are strongly related (weight = 5.0).
*/
@Component
@RequiredArgsConstructor
public class SharedChunkSignal implements RelationSignalStrategy {
private final WikiPageCitationMapper citationMapper;
@Override
public String signalName() { return "shared_chunk"; }
@Override
public double weight() { return 5.0; }
@Override
public Map<Long, Double> score(Long seedPageId, Long kbId) {
List<Long> seedChunkIds = citationMapper.listWithRawByPageId(seedPageId)
.stream().map(PageCitationWithRaw::chunkId).distinct().toList();
if (seedChunkIds.isEmpty()) return Map.of();
Map<Long, Long> pageCount = new HashMap<>();
citationMapper.listByChunkIds(seedChunkIds).stream()
.filter(ref -> !ref.pageId().equals(seedPageId))
.forEach(ref -> pageCount.merge(ref.pageId(), 1L, Long::sum));
return pageCount.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue() * weight()));
}
}