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

93 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-08 20:40 +0800

1""" 

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

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

4""" 

5 

6import json 

7import os 

8from dataclasses import dataclass, field 

9from datetime import datetime 

10 

11 

12@dataclass 

13class PromptTemplate: 

14 """Prompt 模板。""" 

15 

16 name: str 

17 version: str 

18 template: str 

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

20 description: str = "" 

21 parent: str | None = None 

22 created_at: str = "" 

23 metadata: dict = field(default_factory=dict) 

24 

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

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

27 result = self.template 

28 for var in self.variables: 

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

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

31 return result 

32 

33 

34class PromptRegistry: 

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

36 

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

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

39 self.storage_path = storage_path 

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

41 self._load() 

42 

43 def register(self, template: PromptTemplate): 

44 if template.name not in self._templates: 

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

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

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

48 self._save() 

49 

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

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

52 if not versions: 

53 return None 

54 if version == "latest": 

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

56 return versions[sorted_vers[-1]] 

57 return versions.get(version) 

58 

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

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

61 

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

63 result = [] 

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

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

66 result.append( 

67 { 

68 "name": name, 

69 "versions": sorted_vers, 

70 "latest": sorted_vers[-1], 

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

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

73 } 

74 ) 

75 return result 

76 

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

78 tmpl = self.get(name, version) 

79 if not tmpl: 

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

81 return tmpl.render(**kwargs) 

82 

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

84 if name not in self._templates: 

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

86 versions = self._templates[name] 

87 if target_version not in versions: 

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

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

90 latest_ver = sorted_vers[-1] 

91 if latest_ver == target_version: 

92 return 

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

94 target = versions[target_version] 

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

96 new_ver_parts[-1] += 1 

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

98 rolled = PromptTemplate( 

99 name=name, 

100 version=new_ver, 

101 template=target.template, 

102 variables=list(target.variables), 

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

104 parent=target_version, 

105 ) 

106 self.register(rolled) 

107 return rolled 

108 

109 def _save(self): 

110 if not self.storage_path: 

111 return 

112 data = {} 

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

114 data[name] = {} 

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

116 data[name][ver] = { 

117 "template": tmpl.template, 

118 "variables": tmpl.variables, 

119 "description": tmpl.description, 

120 "parent": tmpl.parent, 

121 "created_at": tmpl.created_at, 

122 "metadata": tmpl.metadata, 

123 } 

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

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

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

127 

128 def _load(self): 

129 with open(self.storage_path) as f: 

130 data = json.load(f) 

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

132 if name not in self._templates: 

133 self._templates[name] = {} 

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

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

136 name=name, 

137 version=ver, 

138 template=vdata["template"], 

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

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

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

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

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

144 ) 

145 

146 def stats(self) -> dict: 

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

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

149 

150 

151# ── 预置Prompt模板 ──────────────────────────────── 

152 

153DEFAULT_PROMPTS = { 

154 "agent_system": PromptTemplate( 

155 name="agent_system", 

156 version="1.0.0", 

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

158你的任务:{{task}} 

159可用工具:{{tools}} 

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

161 

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

1631. 思考(thinking) 

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

1653. 最终回答""", 

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

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

168 ), 

169 "code_review": PromptTemplate( 

170 name="code_review", 

171 version="1.0.0", 

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

173 

174代码: 

175``` 

176{{code}} 

177``` 

178 

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

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

181 description="代码审查Prompt", 

182 ), 

183 "research_deep": PromptTemplate( 

184 name="research_deep", 

185 version="1.0.0", 

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

187 

188要求: 

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

1902. 引用权威来源 

1913. 对比不同观点 

1924. 给出可操作的结论 

193 

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

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

196 description="深度调研Prompt", 

197 ), 

198 "summarize": PromptTemplate( 

199 name="summarize", 

200 version="1.0.0", 

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

202 

203内容: 

204{{content}} 

205 

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

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

208 description="文档摘要Prompt", 

209 ), 

210 "creative_writing": PromptTemplate( 

211 name="creative_writing", 

212 version="1.0.0", 

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

214风格:{{style}} 

215字数:{{words}} 

216 

217要求: 

2181. 开头引人入胜 

2192. 结构清晰 

2203. 结尾有力""", 

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

222 description="创意写作Prompt", 

223 ), 

224}