项目文件夹

文件
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

60 行
2.2 KiB
Go

package rerank
// FileCoherenceSignal boosts a candidate when several other
// candidates in the same batch come from the same file. The intuition:
// when BM25 (or vector search) returns multiple hits from one file,
// that file is more likely the user's actual target — the file's
// signal is stronger than any single chunk's. Orthogonal to FanIn
// (which scores graph-topology centrality) because a single
// load-bearing symbol can still live in a file with no other hits.
//
// Algorithm: the per-file score is the sum of (1 / (text_rank + 1))
// across that file's candidates — lower rank = bigger contribution.
// Each candidate's contribution to this signal is its file's score
// divided by the largest per-file score in the batch, clamped to
// [0, 1]. Files with only one candidate contribute 0 to the signal
// (no "multi-chunk" evidence yet); the BM25 / semantic signals already
// reward solo-hit relevance, so the signal stays orthogonal.
//
// Concretely:
// - File F has 3 candidates at ranks 0, 2, 9 → score = 1 + 1/3 + 1/10 = 1.43
// - File G has 1 candidate at rank 1 → solo, signal contributes 0
// - File H has 2 candidates at ranks 4, 7 → score = 1/5 + 1/8 = 0.325
// - max = 1.43; F candidates contribute 1.0, H candidates contribute 0.23
type FileCoherenceSignal struct{}
// Name returns the canonical signal name registered in DefaultWeights.
func (FileCoherenceSignal) Name() string { return SignalFileCoherence }
// Contribute returns the per-candidate file-coherence boost in [0, 1].
// Returns 0 when the candidate's file isn't a multi-chunk file (≤1
// candidate from that file) or when the candidate has no usable
// file path / text rank.
func (FileCoherenceSignal) Contribute(_ string, c *Candidate, ctx *Context) float64 {
if c == nil || c.Node == nil || ctx == nil {
return 0
}
fp := c.Node.FilePath
if fp == "" {
return 0
}
group := ctx.fileGroups[fp]
if len(group) < 2 {
// Solo-hit file → no multi-chunk evidence. The BM25 / semantic
// signals already cover this case.
return 0
}
if ctx.maxFileScoreSum <= 0 {
return 0
}
score := ctx.fileScoreSum[fp]
if score <= 0 {
return 0
}
out := score / ctx.maxFileScoreSum
if out > 1 {
out = 1
}
return out
}