addrkit: strict ordinal matching, LLM-variant guard, externalized prompt
- match: require candidate ordinal to equal the query ordinal in fuzzy search (deterministic typo recall 73% -> 80%, no wrong houses) - resolver: compatibleVariant guard — LLM may only fix street spelling, keeping the same words, ordinal and house unit; damerau distance for transpositions - llm: prompt moved out of code (go:embed default_prompt.txt) with llm.system_prompt / llm.system_prompt_file overrides; guided JSON parsing tolerant of thinking blocks - address: recognize ordinals appearing after the street name - tests: first coverage for the LLM adapter and config prompt loading; README Measured (sample 200): deterministic 94.7-95.8% exact / 0 wrong across 4 seeds; LLM+guard typo 90.7-89.8% / 0 wrong. LLM fallback latency ~1.2-1.9s.
This commit is contained in:
@@ -52,6 +52,45 @@ func ratio(a, b string) float64 {
|
||||
return 1 - float64(levenshtein(a, b))/float64(m)
|
||||
}
|
||||
|
||||
// damerau returns the optimal string alignment (Damerau-Levenshtein) distance,
|
||||
// where an adjacent transposition costs 1. Typos are very often transpositions
|
||||
// ("Гоглоя" vs "Гоголя"), so counting them as a single edit matters.
|
||||
func damerau(a, b string) int {
|
||||
ra, rb := []rune(a), []rune(b)
|
||||
la, lb := len(ra), len(rb)
|
||||
if la == 0 {
|
||||
return lb
|
||||
}
|
||||
if lb == 0 {
|
||||
return la
|
||||
}
|
||||
// Three rolling rows: d[i-2], d[i-1], d[i].
|
||||
prev2 := make([]int, lb+1)
|
||||
prev := make([]int, lb+1)
|
||||
curr := make([]int, lb+1)
|
||||
for j := 0; j <= lb; j++ {
|
||||
prev[j] = j
|
||||
}
|
||||
for i := 1; i <= la; i++ {
|
||||
curr[0] = i
|
||||
for j := 1; j <= lb; j++ {
|
||||
cost := 1
|
||||
if ra[i-1] == rb[j-1] {
|
||||
cost = 0
|
||||
}
|
||||
best := min3(prev[j]+1, curr[j-1]+1, prev[j-1]+cost)
|
||||
if i > 1 && j > 1 && ra[i-1] == rb[j-2] && ra[i-2] == rb[j-1] {
|
||||
if t := prev2[j-2] + 1; t < best {
|
||||
best = t
|
||||
}
|
||||
}
|
||||
curr[j] = best
|
||||
}
|
||||
prev2, prev, curr = prev, curr, prev2
|
||||
}
|
||||
return prev[lb]
|
||||
}
|
||||
|
||||
func min3(a, b, c int) int {
|
||||
m := a
|
||||
if b < m {
|
||||
|
||||
Reference in New Issue
Block a user