Coverage for agentos/prompts/manager.py: 29%

93 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-06 10:59 +0800

1""" 

2AgentOS v0.30 Prompt模板管理 — 版本化Prompt仓库。 

3支持模板继承、变量注入、A/B测试、回滚。 

4""" 

5 

6from dataclasses import dataclass, field 

7from datetime import datetime 

8import json 

9import os 

10 

11 

12@dataclass 

13class PromptTemplate: 

14 """Prompt 模板。""" 

15 name: str 

16 version: str 

17 template: str 

18 variables: list[str] = field(default_factory=list) 

19 description: str = "" 

20 parent: str | None = None 

21 created_at: str = "" 

22 metadata: dict = field(default_factory=dict) 

23 

24 def render(self, **kwargs) -> str: 

25 """渲染模板,注入变量。""" 

26 result = self.template 

27 for var in self.variables: 

28 value = kwargs.get(var, kwargs.get(f"{{{var}}}", f"{{{{{var}}}}}")) 

29 result = result.replace(f"{{{{{var}}}}}", str(value)) 

30 return result 

31 

32 

33class PromptRegistry: 

34 """Prompt模板注册中心。""" 

35 

36 def __init__(self, storage_path: str = ""): 

37 self._templates: dict[str, dict[str, PromptTemplate]] = {} 

38 self.storage_path = storage_path 

39 if storage_path and os.path.exists(storage_path): 

40 self._load() 

41 

42 def register(self, template: PromptTemplate): 

43 if template.name not in self._templates: 

44 self._templates[template.name] = {} 

45 template.created_at = template.created_at or datetime.now().isoformat() 

46 self._templates[template.name][template.version] = template 

47 self._save() 

48 

49 def get(self, name: str, version: str = "latest") -> PromptTemplate | None: 

50 versions = self._templates.get(name, {}) 

51 if not versions: 

52 return None 

53 if version == "latest": 

54 sorted_vers = sorted(versions.keys(), key=lambda v: [int(x) for x in v.split(".")]) 

55 return versions[sorted_vers[-1]] 

56 return versions.get(version) 

57 

58 def get_version(self, name: str, version: str) -> PromptTemplate | None: 

59 return self._templates.get(name, {}).get(version) 

60 

61 def list_templates(self) -> list[dict]: 

62 result = [] 

63 for name, versions in self._templates.items(): 

64 sorted_vers = sorted(versions.keys(), key=lambda v: [int(x) for x in v.split(".")]) 

65 result.append({ 

66 "name": name, 

67 "versions": sorted_vers, 

68 "latest": sorted_vers[-1], 

69 "description": versions[sorted_vers[-1]].description, 

70 "variables": versions[sorted_vers[-1]].variables, 

71 }) 

72 return result 

73 

74 def render(self, name: str, version: str = "latest", **kwargs) -> str: 

75 tmpl = self.get(name, version) 

76 if not tmpl: 

77 raise ValueError(f"Template '{name}' not found") 

78 return tmpl.render(**kwargs) 

79 

80 def rollback(self, name: str, target_version: str): 

81 if name not in self._templates: 

82 raise ValueError(f"Template '{name}' not found") 

83 versions = self._templates[name] 

84 if target_version not in versions: 

85 raise ValueError(f"Version '{target_version}' not found for '{name}'") 

86 sorted_vers = sorted(versions.keys(), key=lambda v: [int(x) for x in v.split(".")]) 

87 latest_ver = sorted_vers[-1] 

88 if latest_ver == target_version: 

89 return 

90 # 回滚:基于目标版本创建新版本 

91 target = versions[target_version] 

92 new_ver_parts = [int(x) for x in latest_ver.split(".")] 

93 new_ver_parts[-1] += 1 

94 new_ver = ".".join(str(x) for x in new_ver_parts) 

95 rolled = PromptTemplate( 

96 name=name, 

97 version=new_ver, 

98 template=target.template, 

99 variables=list(target.variables), 

100 description=f"Rollback from {latest_ver} to {target_version}", 

101 parent=target_version, 

102 ) 

103 self.register(rolled) 

104 return rolled 

105 

106 def _save(self): 

107 if not self.storage_path: 

108 return 

109 data = {} 

110 for name, versions in self._templates.items(): 

111 data[name] = {} 

112 for ver, tmpl in versions.items(): 

113 data[name][ver] = { 

114 "template": tmpl.template, 

115 "variables": tmpl.variables, 

116 "description": tmpl.description, 

117 "parent": tmpl.parent, 

118 "created_at": tmpl.created_at, 

119 "metadata": tmpl.metadata, 

120 } 

121 os.makedirs(os.path.dirname(self.storage_path) or ".", exist_ok=True) 

122 with open(self.storage_path, "w") as f: 

123 json.dump(data, f, indent=2, ensure_ascii=False) 

124 

125 def _load(self): 

126 with open(self.storage_path) as f: 

127 data = json.load(f) 

128 for name, versions in data.items(): 

129 if name not in self._templates: 

130 self._templates[name] = {} 

131 for ver, vdata in versions.items(): 

132 self._templates[name][ver] = PromptTemplate( 

133 name=name, 

134 version=ver, 

135 template=vdata["template"], 

136 variables=vdata.get("variables", []), 

137 description=vdata.get("description", ""), 

138 parent=vdata.get("parent"), 

139 created_at=vdata.get("created_at", ""), 

140 metadata=vdata.get("metadata", {}), 

141 ) 

142 

143 def stats(self) -> dict: 

144 total = sum(len(v) for v in self._templates.values()) 

145 return {"total_templates": len(self._templates), "total_versions": total} 

146 

147 

148# ── 预置Prompt模板 ──────────────────────────────── 

149 

150DEFAULT_PROMPTS = { 

151 "agent_system": PromptTemplate( 

152 name="agent_system", 

153 version="1.0.0", 

154 template="""你是一个专业的AI助手,运行在 AgentOS v0.30 上。 

155你的任务:{{task}} 

156可用工具:{{tools}} 

157当前上下文:{{context}} 

158 

159请逐步思考并执行。输出格式: 

1601. 思考(thinking) 

1612. 工具调用(如果需要) 

1623. 最终回答""", 

163 variables=["task", "tools", "context"], 

164 description="Agent核心系统提示", 

165 ), 

166 "code_review": PromptTemplate( 

167 name="code_review", 

168 version="1.0.0", 

169 template="""审查以下代码。检查维度:{{dimensions}} 

170 

171代码: 

172``` 

173{{code}} 

174``` 

175 

176输出结构化报告。""", 

177 variables=["code", "dimensions"], 

178 description="代码审查Prompt", 

179 ), 

180 "research_deep": PromptTemplate( 

181 name="research_deep", 

182 version="1.0.0", 

183 template="""对以下主题进行深度调研:{{topic}} 

184 

185要求: 

1861. 多角度分析(至少3个视角) 

1872. 引用权威来源 

1883. 对比不同观点 

1894. 给出可操作的结论 

190 

191调研深度:{{depth}}""", 

192 variables=["topic", "depth"], 

193 description="深度调研Prompt", 

194 ), 

195 "summarize": PromptTemplate( 

196 name="summarize", 

197 version="1.0.0", 

198 template="""总结以下内容。摘要长度:{{length}} 

199 

200内容: 

201{{content}} 

202 

203输出格式:{{format}}""", 

204 variables=["content", "length", "format"], 

205 description="文档摘要Prompt", 

206 ), 

207 "creative_writing": PromptTemplate( 

208 name="creative_writing", 

209 version="1.0.0", 

210 template="""创作一篇{{genre}},主题:{{topic}} 

211风格:{{style}} 

212字数:{{words}} 

213 

214要求: 

2151. 开头引人入胜 

2162. 结构清晰 

2173. 结尾有力""", 

218 variables=["genre", "topic", "style", "words"], 

219 description="创意写作Prompt", 

220 ), 

221}