This commit is contained in:
2026-08-11 11:52:08 +08:00
parent 12b0eb24e7
commit aa24e54120
2 changed files with 127 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
package common
import (
"strings"
"unicode"
)
// NormalizeKgTerm 知识图谱术语归一化(实体名与关系谓词共用,别名表由调用方传入)。
// 幂等:NormalizeKgTerm(NormalizeKgTerm(x)) == NormalizeKgTerm(x)。
// 规则保守,只做高置信合并,不做模糊相似度合并,防误合并("人民法院"与"最高人民法院"绝不合并)。
// 返回空串表示归一化后无意义(调用方应丢弃);原本合法但归一化后为空时保留原名(如"中华人民共和国")。
func NormalizeKgTerm(name string, aliasMap map[string]string) string {
orig := name
s := strings.TrimSpace(name)
s = fullToHalf(s)
s = strings.Join(strings.Fields(s), " ")
s = strings.Trim(s, "《》")
// 去版本注记括号及内容:内容含 年/修正/修订/施行/数字 才剥(人名限定语"张三(北京分公司)"不剥)
s = stripVersionParens(s)
s = strings.TrimRight(s, "。,;、!?,;!?.·。、")
s = strings.TrimSpace(s)
// 去"中华人民共和国"前缀(仅前缀;去完为空则保留原名,防实体"中华人民共和国"被删)
if strings.HasPrefix(s, "中华人民共和国") {
if rest := strings.TrimSpace(strings.TrimPrefix(s, "中华人民共和国")); rest != "" {
s = rest
}
}
// 别名全串精确映射(非 contains 替换,防"民诉法"吃掉"民诉法解释"
if std, ok := aliasMap[s]; ok && std != "" {
s = std
}
if s == "" && orig != "" {
return orig
}
return s
}
// fullToHalf 全角转半角(ASCII 可见区 U+FF01~U+FF5E → U+21~U+7E,全角空格 → 半角空格)
func fullToHalf(s string) string {
return strings.Map(func(r rune) rune {
switch {
case r == ' ':
return ' '
case r >= '' && r <= '':
return r - '' + '\x21'
}
return r
}, s)
}
// stripVersionParens 剥去含版本注记的括号及内容。注记判定:内容含 年/修正/修订/施行 或任一数字。
func stripVersionParens(s string) string {
pairs := [][2]rune{{'(', ')'}, {'', ''}, {'【', '】'}, {'[', ']'}, {'', ''}}
var out strings.Builder
runes := []rune(s)
for i := 0; i < len(runes); {
stripped := false
for _, p := range pairs {
if runes[i] == p[0] {
end := findCloseParen(runes, i, p[1])
if end > i && isVersionNote(runes[i+1:end]) {
i = end + 1
stripped = true
break
}
}
}
if !stripped {
out.WriteRune(runes[i])
i++
}
}
return out.String()
}
func findCloseParen(runes []rune, start int, close rune) int {
for j := start + 1; j < len(runes); j++ {
if runes[j] == close {
return j
}
}
return -1
}
// isVersionNote 括号内容是否版本注记(年/修正/修订/施行 或数字)
func isVersionNote(content []rune) bool {
for _, r := range content {
if unicode.IsDigit(r) {
return true
}
}
text := string(content)
for _, kw := range []string{"年", "修正", "修订", "施行"} {
if strings.Contains(text, kw) {
return true
}
}
return false
}
+28
View File
@@ -0,0 +1,28 @@
package consts
// KgAliasMap 法律领域实体常见简称/变体 → 标准名(标准名统一为短形式,与归一化的
// 去「中华人民共和国」前缀规则方向一致,保证幂等)。
// 供 common.NormalizeKgTerm 传入做全串精确映射(调用方取用,common 不依赖本包)。
// 规则:只收录高置信映射(全称/简称、明示别称),禁止模糊近似(防误合并)。
// 新数据集出现新的别名规律时在此补充。
var KgAliasMap = map[string]string{
"民诉法": "民事诉讼法",
"刑诉法": "刑事诉讼法",
"治安处罚法": "治安管理处罚法",
"治安管理法": "治安管理处罚法",
"最高法院": "最高人民法院",
"最高法": "最高人民法院",
"高法": "最高人民法院",
}
// KgPredicateAliasMap 关系谓词变体 → 标准谓词(同义合并,减少"发布/颁布"类重复边)。
// 只收语义等价的映射;"依据/按照/根据"等近似义不合并。
var KgPredicateAliasMap = map[string]string{
"颁布": "发布",
"施行": "实施",
"实行": "实施",
"规定了": "规定",
"规定有": "规定",
"作出的规定": "规定",
"予以规定": "规定",
}