|
9 | 9 |
|
10 | 10 | logger = get_logger(__name__) |
11 | 11 |
|
| 12 | +import json |
| 13 | +import inspect |
| 14 | +from typing import Any, Dict, List |
| 15 | + |
| 16 | +def _safe_json_val(val: Any) -> Any: |
| 17 | + if val is inspect.Parameter.empty: |
| 18 | + return None |
| 19 | + if isinstance(val, type) or callable(val): |
| 20 | + return str(val) |
| 21 | + try: |
| 22 | + json.dumps(val) |
| 23 | + return val |
| 24 | + except TypeError: |
| 25 | + return str(val) |
| 26 | + |
| 27 | +def _param_to_dict(p: inspect.Parameter) -> Dict[str, Any]: |
| 28 | + return { |
| 29 | + "name": p.name, |
| 30 | + "default_value": _safe_json_val(p.default), |
| 31 | + "kind": p.kind.name, |
| 32 | + } |
| 33 | + |
| 34 | +def _get_method_params(method: Any, skip_first_self: bool = False) -> List[Dict[str, Any]]: |
| 35 | + try: |
| 36 | + if method is None: |
| 37 | + return [] |
| 38 | + sig = inspect.signature(method) |
| 39 | + params = list(sig.parameters.values()) |
| 40 | + if skip_first_self and params and params[0].name == "self": |
| 41 | + params = params[1:] |
| 42 | + return [_param_to_dict(p) for p in params] |
| 43 | + except Exception: |
| 44 | + return [] |
| 45 | + |
| 46 | +def _get_docstring(obj) -> str: |
| 47 | + """ |
| 48 | + Return cleaned docstring (dedented), fallback to ''. |
| 49 | + """ |
| 50 | + try: |
| 51 | + return inspect.getdoc(obj) or "" |
| 52 | + except Exception: |
| 53 | + return "" |
| 54 | + |
12 | 55 |
|
13 | 56 | class PromptRegistry: |
14 | 57 | """ |
@@ -80,48 +123,48 @@ def list_operator_prompts(self) -> OperatorPromptMapOut: |
80 | 123 | return OperatorPromptMapOut(operator_prompts=result) |
81 | 124 |
|
82 | 125 | def list_prompt_info(self) -> PromptInfoMapOut: |
83 | | - |
84 | 126 | prompt_map = self._prompt_registry.get_obj_map() |
85 | 127 | operator_map = self._operator_registry.get_obj_map() |
86 | 128 |
|
87 | | - # ---- 第一部分:构建 Prompt → Operators 列表 ---- |
| 129 | + # Prompt → Operators |
88 | 130 | prompt_to_ops: Dict[str, List[str]] = {} |
89 | | - |
90 | 131 | for op_name, op_cls in operator_map.items(): |
91 | 132 | allowed = getattr(op_cls, "ALLOWED_PROMPTS", []) |
92 | 133 | for p_cls in allowed: |
93 | | - p_name = p_cls.__name__ |
94 | | - prompt_to_ops.setdefault(p_name, []).append(op_name) |
| 134 | + prompt_to_ops.setdefault(p_cls.__name__, []).append(op_name) |
95 | 135 |
|
96 | | - # ---- 第二部分:获取 Prompt 的分类信息 ---- |
97 | 136 | prompt_types = self._prompt_registry.get_type_of_objects() |
98 | | - |
99 | | - # ---- 第三部分:构造最终结构 ---- |
100 | 137 | result: Dict[str, PromptInfoOut] = {} |
101 | 138 |
|
102 | 139 | for p_name, p_cls in prompt_map.items(): |
103 | 140 | if not isclass(p_cls): |
104 | 141 | continue |
105 | 142 |
|
106 | | - # operator list |
107 | 143 | ops = prompt_to_ops.get(p_name, []) |
108 | | - |
109 | | - # class path string |
110 | 144 | class_str = f"{p_cls.__module__}.{p_cls.__name__}" |
111 | 145 |
|
112 | | - # categories |
113 | 146 | type_path = prompt_types.get(p_name, []) |
114 | 147 | primary_type = type_path[0] if len(type_path) > 0 else "Unknown" |
115 | 148 | secondary_type = type_path[1] if len(type_path) > 1 else "Unknown" |
116 | 149 |
|
| 150 | + |
| 151 | + # ✅ docstring |
| 152 | + description = _get_docstring(p_cls) |
| 153 | + # ✅ 新增:init 参数 |
| 154 | + init_params = _get_method_params(getattr(p_cls, "__init__", None), skip_first_self=True) |
| 155 | + build_params = _get_method_params(getattr(p_cls, "build_prompt", None), skip_first_self=True) |
| 156 | + |
117 | 157 | result[p_name] = PromptInfoOut( |
118 | 158 | operator=ops, |
119 | 159 | class_str=class_str, |
120 | 160 | primary_type=primary_type, |
121 | | - secondary_type=secondary_type |
| 161 | + secondary_type=secondary_type, |
| 162 | + description=description, |
| 163 | + parameter={"init": init_params, "build_prompt": build_params}, # ✅ 新字段 |
122 | 164 | ) |
123 | 165 |
|
124 | 166 | return PromptInfoMapOut(prompts=result) |
125 | 167 |
|
| 168 | + |
126 | 169 | # 全局单例 |
127 | 170 | # _PROMPT_REGISTRY = PromptRegistry() |
0 commit comments