From ac966af3d126d59081d119e05ba02f946257f669 Mon Sep 17 00:00:00 2001
From: ai_xiaopei <xiaopei@aisim.cn>
Date: Sun, 26 Jul 2026 23:22:36 +0800
Subject: [PATCH] fix: 移除所有help中的等号格式
---
cmd/graph.go | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 240 insertions(+), 0 deletions(-)
diff --git a/cmd/graph.go b/cmd/graph.go
new file mode 100644
index 0000000..337552b
--- /dev/null
+++ b/cmd/graph.go
@@ -0,0 +1,240 @@
+package cmd
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/aisim/kb-cli/internal/graph"
+ "github.com/aisim/kb-cli/internal/index"
+ "github.com/spf13/cobra"
+)
+
+var graphCmd = &cobra.Command{
+ Use: "graph",
+ Short: "知识图谱查询与管理",
+}
+
+var graphStatsCmd = &cobra.Command{
+ Use: "stats",
+ Short: "查看知识图谱统计信息",
+ Long: `kb-cli graph stats [--json] # 查看知识图谱统计信息(节点数、边数、关系类型分布)`,
+ RunE: runGraphStats,
+}
+
+var graphQueryCmd = &cobra.Command{
+ Use: "query <关键词>",
+ Short: "查询节点的关联关系",
+ Long: `kb-cli graph query <关键词> [--relation <类型>] [--depth <深度>] [--json] # 查询节点的关联关系`,
+ Args: cobra.ExactArgs(1),
+ RunE: runGraphQuery,
+}
+
+var graphRelatedCmd = &cobra.Command{
+ Use: "related <关键词>",
+ Short: "查找与关键词相关的所有节点",
+ Long: `kb-cli graph related <关键词> [--top N] [--json] # 查找与关键词相关的所有节点`,
+ Args: cobra.ExactArgs(1),
+ RunE: runGraphRelated,
+}
+
+var (
+ graphRelation string
+ graphDepth int
+ graphJSON bool
+ graphTopN int
+)
+
+func init() {
+ rootCmd.AddCommand(graphCmd)
+ graphCmd.AddCommand(graphStatsCmd)
+ graphCmd.AddCommand(graphQueryCmd)
+ graphCmd.AddCommand(graphRelatedCmd)
+
+ // graph stats flags
+ graphStatsCmd.Flags().BoolVar(&graphJSON, "json", false, "JSON 格式输出")
+
+ // graph query flags
+ graphQueryCmd.Flags().StringVar(&graphRelation, "relation", "", "关系类型(tag/entity/wikilink)")
+ graphQueryCmd.Flags().IntVar(&graphDepth, "depth", 1, "查询深度(1-3)")
+ graphQueryCmd.Flags().BoolVar(&graphJSON, "json", false, "JSON 格式输出")
+
+ // graph related flags
+ graphRelatedCmd.Flags().IntVar(&graphTopN, "top", 10, "返回前 N 条结果")
+ graphRelatedCmd.Flags().BoolVar(&graphJSON, "json", false, "JSON 格式输出")
+}
+
+func runGraphStats(cmd *cobra.Command, args []string) error {
+ // 打开索引
+ store, err := index.Open(dbPath)
+ if err != nil {
+ return fmt.Errorf("打开索引失败: %w", err)
+ }
+ defer store.Close()
+
+ // 获取节点数和边数
+ nodeCount, err := store.NodeCount()
+ if err != nil {
+ return fmt.Errorf("获取节点数失败: %w", err)
+ }
+
+ edgeCount, err := store.EdgeCount()
+ if err != nil {
+ return fmt.Errorf("获取边数失败: %w", err)
+ }
+
+ // 获取关系类型分布
+ relationStats, err := store.GetRelationStats()
+ if err != nil {
+ return fmt.Errorf("获取关系统计失败: %w", err)
+ }
+
+ if graphJSON {
+ stats := map[string]interface{}{
+ "node_count": nodeCount,
+ "edge_count": edgeCount,
+ "relations": relationStats,
+ }
+ data, err := json.MarshalIndent(stats, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(data))
+ } else {
+ fmt.Printf("知识图谱统计:\n")
+ fmt.Printf(" 节点数: %d\n", nodeCount)
+ fmt.Printf(" 边数: %d\n", edgeCount)
+ fmt.Printf("\n关系类型分布:\n")
+ for rel, count := range relationStats {
+ fmt.Printf(" %-12s %d\n", rel, count)
+ }
+ }
+
+ return nil
+}
+
+func runGraphQuery(cmd *cobra.Command, args []string) error {
+ keyword := args[0]
+
+ // 打开索引
+ store, err := index.Open(dbPath)
+ if err != nil {
+ return fmt.Errorf("打开索引失败: %w", err)
+ }
+ defer store.Close()
+
+ // 查找匹配关键词的节点
+ nodes, err := store.FindNodesByKeyword(keyword)
+ if err != nil {
+ return fmt.Errorf("查找节点失败: %w", err)
+ }
+
+ if len(nodes) == 0 {
+ fmt.Println("未找到匹配的节点")
+ return nil
+ }
+
+ // 查询每个节点的关联关系
+ var results []QueryResult
+ for _, node := range nodes {
+ edges, err := store.GetNodeEdges(node.ID, graphRelation, graphDepth)
+ if err != nil {
+ return fmt.Errorf("查询关联失败: %w", err)
+ }
+
+ results = append(results, QueryResult{
+ Node: node,
+ Edges: edges,
+ })
+ }
+
+ if graphJSON {
+ data, err := json.MarshalIndent(results, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(data))
+ } else {
+ for _, r := range results {
+ fmt.Printf("\n节点: %s (%s)\n", r.Node.Title, r.Node.Path)
+ if len(r.Edges) == 0 {
+ fmt.Println(" 无关联关系")
+ continue
+ }
+
+ // 按关系类型分组
+ grouped := make(map[string][]string)
+ for _, edge := range r.Edges {
+ grouped[edge.Relation] = append(grouped[edge.Relation], edge.Label)
+ }
+
+ for rel, labels := range grouped {
+ fmt.Printf(" [%s]\n", rel)
+ for _, label := range labels {
+ fmt.Printf(" - %s\n", label)
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func runGraphRelated(cmd *cobra.Command, args []string) error {
+ keyword := args[0]
+
+ // 打开索引
+ store, err := index.Open(dbPath)
+ if err != nil {
+ return fmt.Errorf("打开索引失败: %w", err)
+ }
+ defer store.Close()
+
+ // 查找相关节点
+ related, err := store.FindRelatedNodes(keyword, graphTopN)
+ if err != nil {
+ return fmt.Errorf("查找相关节点失败: %w", err)
+ }
+
+ if len(related) == 0 {
+ fmt.Println("未找到相关节点")
+ return nil
+ }
+
+ if graphJSON {
+ data, err := json.MarshalIndent(related, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(data))
+ } else {
+ fmt.Printf("与 '%s' 相关的节点:\n\n", keyword)
+ for i, r := range related {
+ fmt.Printf("%d. %s\n", i+1, r.Title)
+ fmt.Printf(" 路径: %s\n", r.Path)
+ fmt.Printf(" 板块: %s\n", r.Section)
+ fmt.Printf(" 关联度: %d\n", r.Relevance)
+ if len(r.Tags) > 0 {
+ fmt.Printf(" 标签: %v\n", r.Tags)
+ }
+ fmt.Println()
+ }
+ }
+
+ return nil
+}
+
+// QueryResult 查询结果
+type QueryResult struct {
+ Node *graph.Node `json:"node"`
+ Edges []*graph.Edge `json:"edges"`
+}
+
+// RelatedNode 相关节点
+type RelatedNode struct {
+ ID int64 `json:"id"`
+ Path string `json:"path"`
+ Title string `json:"title"`
+ Section string `json:"section"`
+ Tags []string `json:"tags"`
+ Relevance int `json:"relevance"`
+}
--
Gitblit v1.9.1