1
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package consts
|
||||
|
||||
// KgAliasMap 法律领域实体常见简称/变体 → 标准名(标准名统一为短形式,与归一化的
|
||||
// 去「中华人民共和国」前缀规则方向一致,保证幂等)。
|
||||
// 供 common.NormalizeKgTerm 传入做全串精确映射(调用方取用,common 不依赖本包)。
|
||||
// 规则:只收录高置信映射(全称/简称、明示别称),禁止模糊近似(防误合并)。
|
||||
// 新数据集出现新的别名规律时在此补充。
|
||||
var KgAliasMap = map[string]string{
|
||||
"民诉法": "民事诉讼法",
|
||||
"刑诉法": "刑事诉讼法",
|
||||
"治安处罚法": "治安管理处罚法",
|
||||
"治安管理法": "治安管理处罚法",
|
||||
"最高法院": "最高人民法院",
|
||||
"最高法": "最高人民法院",
|
||||
"高法": "最高人民法院",
|
||||
}
|
||||
|
||||
// KgPredicateAliasMap 关系谓词变体 → 标准谓词(同义合并,减少"发布/颁布"类重复边)。
|
||||
// 只收语义等价的映射;"依据/按照/根据"等近似义不合并。
|
||||
var KgPredicateAliasMap = map[string]string{
|
||||
"颁布": "发布",
|
||||
"施行": "实施",
|
||||
"实行": "实施",
|
||||
"规定了": "规定",
|
||||
"规定有": "规定",
|
||||
"作出的规定": "规定",
|
||||
"予以规定": "规定",
|
||||
}
|
||||
Reference in New Issue
Block a user