fix: health endpoint + graph/edge API + normalizeEntity Chinese + nl_query comparison

1. Add /api/v1/health endpoint (maps to HandleHealth)
2. Add POST /api/v1/graph/edge for adding relation edges
3. Fix normalizeEntity to preserve Chinese characters (0x4e00-0x9fa5)
4. Fix nl_query direct_path comparison to use normalizeEntity on both sides
This commit is contained in:
小唯 2026-06-16 16:16:35 +08:00
parent bd8008b3fd
commit d6188a2bd7
1 changed files with 39 additions and 3 deletions

View File

@ -31,9 +31,10 @@ func normalizeEntity(entity string) string {
if strings.HasPrefix(entity, "n_") {
entity = entity[2:]
}
// 过滤特殊字符
// 保留中文、字母、数字、下划线、连字符,过滤其他特殊字符
clean := strings.Map(func(r rune) rune {
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '-' {
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '-' ||
(r >= 0x4e00 && r <= 0x9fa5) { // 中文 Unicode 范围
return r
}
return '_'
@ -278,6 +279,7 @@ func NewServer() http.Handler {
// 后续在 catch-all 中处理(见文件末尾)
mux.HandleFunc("/health", routes.HandleHealth)
mux.HandleFunc("/api/v1/health", routes.HandleHealth)
// ─── Prometheus /metrics ─────────────────────
mux.Handle("/metrics", metrics.Handler())
@ -333,6 +335,38 @@ func NewServer() http.Handler {
mux.HandleFunc("/api/v1/graph/stats", graphAPI.Stats)
mux.HandleFunc("/api/v1/graph/query", graphAPI.Query)
mux.HandleFunc("/api/v1/graph/navigate", graphAPI.Navigate)
// 新增添加关系边POST JSON body: {"from":"实体A","to":"实体B","relation":"关系类型","namespace":""}
mux.HandleFunc("/api/v1/graph/edge", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "POST only", 405)
return
}
var req struct {
From string `json:"from"`
To string `json:"to"`
Relation string `json:"relation"`
Namespace string `json:"namespace"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), 400)
return
}
if req.From == "" || req.To == "" || req.Relation == "" {
http.Error(w, "from, to, relation required", 400)
return
}
ns := req.Namespace
if ns == "" {
ns = "default"
}
edgeID := fmt.Sprintf("e_%s_%s_%d", req.From, req.Relation, time.Now().UnixNano())
err := graphStore.AddEdge(edgeID, req.From, req.To, req.Relation, ns, 1.0)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
json.NewEncoder(w).Encode(map[string]interface{}{"status": "ok", "edge_id": edgeID})
})
// 新增pagerank + evidence_count
mux.HandleFunc("/api/v1/graph/pagerank", func(w http.ResponseWriter, r *http.Request) {
rank := graphStore.PageRank(0.85, 20)
@ -478,7 +512,9 @@ func NewServer() http.Handler {
// 找 A → B 的直接边
var directPath map[string]interface{}
for _, p := range paths {
if strings.TrimPrefix(p["to"].(string), "n_") == normalizeEntity(entityB) {
toNorm := normalizeEntity(p["to"].(string))
targetNorm := normalizeEntity(entityB)
if toNorm == targetNorm {
directPath = p
break
}