This is an automated email from the ASF dual-hosted git repository.

jin pushed a commit to branch text2gql
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph-ai.git

commit 8e6df488fdaf4bcda912f8aaa57277ffc0505c26
Author: Lriver <[email protected]>
AuthorDate: Tue Sep 30 20:53:40 2025 +0800

    feat: add Gremlin base component library with synonym replacement and data 
instances
---
 text2gremlin/AST_Text2Gremlin/base/GremlinBase.py | 217 ++++++++++++++++++++++
 1 file changed, 217 insertions(+)

diff --git a/text2gremlin/AST_Text2Gremlin/base/GremlinBase.py 
b/text2gremlin/AST_Text2Gremlin/base/GremlinBase.py
new file mode 100644
index 00000000..00b0572c
--- /dev/null
+++ b/text2gremlin/AST_Text2Gremlin/base/GremlinBase.py
@@ -0,0 +1,217 @@
+
+"""
+Gremlin翻译引擎模块。
+
+提供Gremlin术语到中文的智能翻译,负责生成自然流畅的中文查询描述。
+"""
+
+import os
+import random
+from gremlin.GremlinParser import GremlinParser
+
+class GremlinBase:
+    def __init__(self, config):
+        """
+        Gremlin 基础类,作为项目的“工具箱”和“字典”。
+        """
+        self.config = config
+        
+        # 从 GremlinParser 加载rule_names
+        self.rule_names = GremlinParser.ruleNames
+
+        self.token_dict = {}
+        self.template = [] # 索引对应 token_dict 的值,每个元素是一个包含多种中文翻译模板的子列表。
+        self._initialize_translation_templates()
+
+        # 复用 schema_dict 加载同义词等
+        self.schema_dict = {}
+        self._load_schema_translations()
+
+    def get_rule_name(self, rule_index: int) -> str:
+        """根据索引获取 ANTLR 规则名。"""
+        if 0 <= rule_index < len(self.rule_names):
+            return self.rule_names[rule_index]
+        return "UnknownRule"
+
+    def _load_schema_translations(self):
+        """加载schema翻译字典"""
+        # 从Config获取路径,如果失败则使用默认路径
+        file_paths = []
+        
+        try:
+            if hasattr(self.config, 'get_schema_dict_path'):
+                schema_dict_paths = self.config.get_schema_dict_path()
+                # 为列表或字符串的情况
+                if isinstance(schema_dict_paths, list):
+                    file_paths.extend(schema_dict_paths)
+                elif isinstance(schema_dict_paths, str):
+                    file_paths.append(schema_dict_paths)
+            
+            if hasattr(self.config, 'get_syn_dict_path'):
+                syn_dict_path = self.config.get_syn_dict_path()
+                if syn_dict_path:
+                    file_paths.append(syn_dict_path)
+                    
+        except Exception as e:
+            print(f"[INFO] Config paths not available: {e}")
+        
+        # 如果没有从Config获取到路径,使用默认路径
+        if not file_paths:
+            current_dir = os.path.dirname(os.path.abspath(__file__))
+            file_paths = [
+                os.path.join(current_dir, 'template', 'schema_dict.txt'),
+                os.path.join(current_dir, 'template', 'syn_dict.txt')
+            ]
+        
+        # 加载schema翻译字典
+        existing_paths = [path for path in file_paths if os.path.exists(path)]
+        
+        # 如果没有找到配置的路径,尝试默认路径
+        if not existing_paths:
+            current_dir = os.path.dirname(os.path.abspath(__file__))
+            default_paths = [
+                os.path.join(current_dir, 'template', 'schema_dict.txt'),
+                os.path.join(current_dir, 'template', 'syn_dict.txt')
+            ]
+            existing_paths = [path for path in default_paths if 
os.path.exists(path)]
+            if existing_paths:
+                print(f"[INFO] Using default dictionary paths: 
{existing_paths}")
+        
+        if existing_paths:
+            self.load_dict_from_file(existing_paths)
+        else:
+            print(f"[WARNING] No dictionary files found in: {file_paths}")
+
+    def _initialize_translation_templates(self):
+        """
+        初始化 Gremlin 步骤的翻译模板。
+        """
+        # 定义模板数据
+        templates_data = {
+            # --- 起始步骤 ---
+            "v": ["查询图中的所有顶点", "获取所有节点"],
+            "e": ["查询图中的所有边", "获取所有关系"],
+            "addv": ["添加一个标签为 '{}' 的新顶点"],
+            "adde": ["添加一条从一个顶点到另一个顶点的 '{}' 边"],
+            # --- 遍历步骤 ---
+            "out": ["从当前位置出发,沿着 '{}' 方向的出边前进", "找到 '{}' 类型的邻居"],
+            "in": ["从当前位置出发,沿着 '{}' 方向的入边前进", "找到拥有 '{}' 类型关系的来源"],
+            "both": ["沿着 '{}' 方向的双向边进行遍历"],
+            "outv": ["从当前边,找到它的出射顶点", "获取边的头节点"],
+            "inv": ["从当前边,找到它的入射顶点", "获取边的尾节点"],
+            "bothv": ["从当前边,找到它的两个端点"],
+            # --- 过滤步骤 ---
+            "haslabel": ["并筛选出标签为 '{}' 的元素"],
+            "has": ["并筛选出属性 '{}' 为 '{}' 的元素", "查找其中 '{}' 是 '{}' 的数据"],
+            "where": ["并根据 '{}' 的条件进行过滤"],
+            "limit": ["并限制最多返回 {} 个结果", "取前 {} 条数据"],
+            "dedup": ["并对结果进行去重"],
+            # --- 映射/返回步骤 ---
+            "values": ["然后获取它们的 '{}' 属性值", "提取 '{}' 字段的值"],
+            "valuemap": ["然后以键值对的形式返回它们的属性"],
+            "label": ["然后获取它们的标签"],
+            "id": ["然后获取它们的ID"],
+            "path": ["然后返回完整的遍历路径"],
+            "project": ["然后将结果投影为以 '{}' 为键的映射"],
+            "by": ["通过 '{}' 来进行分组或投影"],
+            # --- 聚合/排序步骤 ---
+            "count": ["最后统计结果的总数"],
+            "group": ["然后根据 '{}' 进行分组"],
+            "order": ["然后对结果进行排序"],
+            # --- 修改/删除步骤 ---
+            "property": ["并将其 '{}' 属性的值更新为 '{}'"],
+            "drop": ["最后将这些元素从图中删除", "移除这些数据"]
+        }
+        
+        # 填充 self.token_dict 和 self.template
+        for index, (key, value) in enumerate(templates_data.items()):
+            self.token_dict[key.upper()] = index
+            self.template.append(value)
+
+    def get_token_desc(self, token_key: str, *args) -> str:
+        """
+        根据 token 和参数获取一个随机的、格式化后的中文描述。
+        """
+        key = token_key.upper()
+        if key in self.token_dict:
+            index = self.token_dict[key]
+            # 随机选择一个模板
+            selected_template = random.choice(self.template[index])
+            try:
+                # 翻译参数中的schema术语
+                translated_args = []
+                for arg in args:
+                    if isinstance(arg, str):
+                        # 尝试翻译schema术语
+                        translated_arg = self.get_schema_desc(arg)
+                        translated_args.append(translated_arg)
+                    else:
+                        translated_args.append(arg)
+                
+                # 使用翻译后的参数格式化模板
+                return selected_template.format(*translated_args)
+            except (IndexError, KeyError):
+                # 如果参数数量不匹配,返回原始模板
+                return selected_template
+        return "" # 如果 token 不存在,返回空字符串
+
+    # 复用的通用方法
+    def merge_desc(self, desc_list: list) -> str:
+        """合并多个描述片段,移除空字符串并用合适的连接词连接。"""
+        # 过滤掉空字符串
+        filtered_list = [s for s in desc_list if s and s.strip()]
+        return ",".join(filtered_list)
+
+    def load_dict_from_file(self, file_paths: list):
+        """从文件加载字典,例如同义词词典。"""
+        for file_path in file_paths:
+            if not os.path.exists(file_path):
+                print(f"[WARNING] Dictionary file not found: {file_path}")
+                continue
+            with open(file_path, "r", encoding="utf-8") as file:
+                for line in file:
+                    elements = line.strip().split()
+                    if elements:
+                        key = elements[0]
+                        values = elements[1:]
+                        self.schema_dict[key] = values
+
+    def get_schema_desc(self, key: str) -> str:
+        """从加载的字典中获取一个随机的同义词或描述。"""
+        try:
+            # 确保键存在
+            if key in self.schema_dict and self.schema_dict[key]:
+                return random.choice(self.schema_dict[key])
+            return key # 如果没有同义词,返回原词
+        except KeyError:
+            return key
+
+if __name__ == "__main__":
+    # 临时创建config 对象,用于测试
+    class MockConfig:
+        def get_schema_dict_path(self):
+            return "./template/schema_dict.txt" 
+        def get_syn_dict_path(self):
+            return "./template/syn_dict.txt" 
+
+    config = MockConfig()
+    gremlin_base = GremlinBase(config)
+
+    print("--- GremlinBase.py 测试 ---")
+    
+    # 1. 测试规则名加载
+    print(f"\n成功加载 {len(gremlin_base.rule_names)} 条 Gremlin 语法规则。")
+    print(f"第一条规则是: '{gremlin_base.get_rule_name(0)}'")
+
+    # 2. 测试翻译模板
+    print("\n--- 测试翻译功能 ---")
+    print("OUT('acted_in') 的一个翻译: ", gremlin_base.get_token_desc("OUT", 
"acted_in"))
+    print("HAS('name', 'marko') 的一个翻译: ", gremlin_base.get_token_desc("HAS", 
"name", "marko"))
+    print("LIMIT(10) 的一个翻译: ", gremlin_base.get_token_desc("LIMIT", 10))
+    print("COUNT() 的一个翻译: ", gremlin_base.get_token_desc("COUNT"))
+    
+    # 3. 测试描述合并
+    desc_parts = ["查找所有电影", "筛选出其中类型为科幻的", "最后统计总数"]
+    merged = gremlin_base.merge_desc(desc_parts)
+    print("\n合并后的描述: ", merged)
+

Reply via email to