Coverage for src\agents_sdk_models\gen_agent.py: 99%

70 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-06-04 17:38 +0900

1from __future__ import annotations 

2 

3"""GenAgent — AgentPipeline as a Step for Flow workflows. 

4 

5GenAgentはAgentPipelineをStepとして使用するためのクラスです。 

6これにより、AgentPipelineをFlowワークフロー内で直接使用できます。 

7""" 

8 

9import asyncio 

10from typing import Any, Callable, List, Dict, Optional, Type 

11from concurrent.futures import ThreadPoolExecutor 

12 

13from .step import Step 

14from .context import Context 

15from .pipeline import AgentPipeline, EvaluationResult 

16 

17 

18class GenAgent(Step): 

19 """ 

20 Step implementation that wraps AgentPipeline functionality 

21 AgentPipeline機能をラップするStep実装 

22  

23 This class allows using AgentPipeline directly as a Step in Flow workflows, 

24 providing generation, evaluation, and retry capabilities within a workflow context. 

25 このクラスはAgentPipelineをFlowワークフロー内で直接Stepとして使用できるようにし、 

26 ワークフローコンテキスト内で生成、評価、リトライ機能を提供します。 

27 """ 

28 

29 def __init__( 

30 self, 

31 name: str, 

32 generation_instructions: str, 

33 evaluation_instructions: Optional[str] = None, 

34 *, 

35 input_guardrails: Optional[list] = None, 

36 output_guardrails: Optional[list] = None, 

37 output_model: Optional[Type[Any]] = None, 

38 model: str | None = None, 

39 evaluation_model: str | None = None, 

40 generation_tools: Optional[list] = None, 

41 evaluation_tools: Optional[list] = None, 

42 routing_func: Optional[Callable[[Any], Any]] = None, 

43 session_history: Optional[list] = None, 

44 history_size: int = 10, 

45 threshold: int = 85, 

46 retries: int = 3, 

47 improvement_callback: Optional[Callable[[Any, EvaluationResult], None]] = None, 

48 dynamic_prompt: Optional[Callable[[str], str]] = None, 

49 retry_comment_importance: Optional[list[str]] = None, 

50 locale: str = "en", 

51 next_step: Optional[str] = None, 

52 store_result_key: Optional[str] = None, 

53 ) -> None: 

54 """ 

55 Initialize GenAgent with AgentPipeline configuration 

56 AgentPipeline設定でGenAgentを初期化する 

57 

58 Args: 

59 name: Step name / ステップ名 

60 generation_instructions: System prompt for generation / 生成用システムプロンプト 

61 evaluation_instructions: System prompt for evaluation / 評価用システムプロンプト 

62 input_guardrails: Guardrails for generation / 生成用ガードレール 

63 output_guardrails: Guardrails for evaluation / 評価用ガードレール 

64 output_model: Model for output formatting / 出力フォーマット用モデル 

65 model: LLM model name / LLMモデル名 

66 evaluation_model: Optional LLM model name for evaluation / 評価用LLMモデル名(任意) 

67 generation_tools: Tools for generation / 生成用ツール 

68 evaluation_tools: Tools for evaluation / 評価用ツール 

69 routing_func: Function for output routing / 出力ルーティング用関数 

70 session_history: Session history / セッション履歴 

71 history_size: Size of history to keep / 保持する履歴サイズ 

72 threshold: Evaluation score threshold / 評価スコア閾値 

73 retries: Number of retry attempts / リトライ試行回数 

74 improvement_callback: Callback for improvement suggestions / 改善提案用コールバック 

75 dynamic_prompt: Optional function to dynamically build prompt / 動的プロンプト生成関数(任意) 

76 retry_comment_importance: Importance levels of comments to include on retry / リトライ時コメント重要度レベル 

77 locale: Language code for localized messages / ローカライズメッセージ用言語コード 

78 next_step: Next step after pipeline execution / パイプライン実行後の次ステップ 

79 store_result_key: Key to store result in context shared_state / コンテキスト共有状態に結果を格納するキー 

80 """ 

81 # Initialize Step base class 

82 # Step基底クラスを初期化 

83 super().__init__(name) 

84 

85 # Store flow-specific configuration 

86 # フロー固有の設定を保存 

87 self.next_step = next_step 

88 self.store_result_key = store_result_key or f"{name}_result" 

89 

90 # Create internal AgentPipeline instance 

91 # 内部AgentPipelineインスタンスを作成 

92 self.pipeline = AgentPipeline( 

93 name=f"{name}_pipeline", 

94 generation_instructions=generation_instructions, 

95 evaluation_instructions=evaluation_instructions, 

96 input_guardrails=input_guardrails, 

97 output_guardrails=output_guardrails, 

98 output_model=output_model, 

99 model=model, 

100 evaluation_model=evaluation_model, 

101 generation_tools=generation_tools, 

102 evaluation_tools=evaluation_tools, 

103 routing_func=routing_func, 

104 session_history=session_history, 

105 history_size=history_size, 

106 threshold=threshold, 

107 retries=retries, 

108 improvement_callback=improvement_callback, 

109 dynamic_prompt=dynamic_prompt, 

110 retry_comment_importance=retry_comment_importance, 

111 locale=locale, 

112 ) 

113 

114 async def run(self, user_input: Optional[str], ctx: Context) -> Context: 

115 """ 

116 Execute GenAgent step using AgentPipeline 

117 AgentPipelineを使用してGenAgentステップを実行する 

118 

119 Args: 

120 user_input: User input for the pipeline / パイプライン用ユーザー入力 

121 ctx: Current workflow context / 現在のワークフローコンテキスト 

122 

123 Returns: 

124 Context: Updated context with pipeline results / パイプライン結果付き更新済みコンテキスト 

125 """ 

126 # English: Update step information in context 

127 # 日本語: コンテキストのステップ情報を更新 

128 ctx.update_step_info(self.name) 

129 

130 try: 

131 # English: Determine input text for pipeline 

132 # 日本語: パイプライン用入力テキストを決定 

133 input_text = user_input or ctx.last_user_input or "" 

134 

135 if not input_text: 

136 # English: If no input available, add system message and continue 

137 # 日本語: 入力がない場合、システムメッセージを追加して続行 

138 ctx.add_system_message(f"GenAgent {self.name}: No input available, skipping pipeline execution") 

139 result = None 

140 else: 

141 # English: Execute pipeline in thread pool to handle sync methods 

142 # 日本語: 同期メソッドを処理するためにスレッドプールでパイプラインを実行 

143 loop = asyncio.get_event_loop() 

144 with ThreadPoolExecutor() as executor: 

145 future = loop.run_in_executor(executor, self.pipeline.run, input_text) 

146 result = await future 

147 

148 # English: Store result in context 

149 # 日本語: 結果をコンテキストに保存 

150 if result is not None: 

151 # English: Store in shared state for other steps to access 

152 # 日本語: 他のステップがアクセスできるよう共有状態に保存 

153 ctx.shared_state[self.store_result_key] = result 

154 ctx.prev_outputs[self.name] = result 

155 

156 # English: Add result as assistant message 

157 # 日本語: 結果をアシスタントメッセージとして追加 

158 ctx.add_assistant_message(str(result)) 

159 

160 # English: Add success system message 

161 # 日本語: 成功システムメッセージを追加 

162 ctx.add_system_message(f"GenAgent {self.name}: Pipeline executed successfully") 

163 else: 

164 # English: Handle case where pipeline returned None (evaluation failed) 

165 # 日本語: パイプラインがNoneを返した場合(評価失敗)を処理 

166 ctx.shared_state[self.store_result_key] = None 

167 ctx.prev_outputs[self.name] = None 

168 

169 # English: Add failure system message 

170 # 日本語: 失敗システムメッセージを追加 

171 ctx.add_system_message(f"GenAgent {self.name}: Pipeline execution failed (evaluation threshold not met)") 

172 

173 except Exception as e: 

174 # English: Handle execution errors 

175 # 日本語: 実行エラーを処理 

176 error_msg = f"GenAgent {self.name} execution error: {str(e)}" 

177 ctx.add_system_message(error_msg) 

178 ctx.shared_state[self.store_result_key] = None 

179 ctx.prev_outputs[self.name] = None 

180 

181 # English: Log error for debugging 

182 # 日本語: デバッグ用エラーログ 

183 print(f"🚨 {error_msg}") 

184 

185 # English: Set next step if specified 

186 # 日本語: 指定されている場合は次ステップを設定 

187 if self.next_step: 

188 ctx.goto(self.next_step) 

189 

190 return ctx 

191 

192 def get_pipeline_history(self) -> List[Dict[str, str]]: 

193 """ 

194 Get the internal pipeline history 

195 内部パイプライン履歴を取得する 

196 

197 Returns: 

198 List[Dict[str, str]]: Pipeline history / パイプライン履歴 

199 """ 

200 return self.pipeline._pipeline_history 

201 

202 def get_session_history(self) -> Optional[List[str]]: 

203 """ 

204 Get the session history 

205 セッション履歴を取得する 

206 

207 Returns: 

208 Optional[List[str]]: Session history / セッション履歴 

209 """ 

210 return self.pipeline.session_history 

211 

212 def update_instructions( 

213 self, 

214 generation_instructions: Optional[str] = None, 

215 evaluation_instructions: Optional[str] = None 

216 ) -> None: 

217 """ 

218 Update pipeline instructions 

219 パイプライン指示を更新する 

220 

221 Args: 

222 generation_instructions: New generation instructions / 新しい生成指示 

223 evaluation_instructions: New evaluation instructions / 新しい評価指示 

224 """ 

225 if generation_instructions is not None: 

226 self.pipeline.generation_instructions = generation_instructions.strip() 

227 # English: Update the agent instructions 

228 # 日本語: エージェント指示を更新 

229 self.pipeline.gen_agent.instructions = generation_instructions.strip() 

230 

231 if evaluation_instructions is not None: 

232 self.pipeline.evaluation_instructions = evaluation_instructions.strip() if evaluation_instructions else None 

233 # English: Update evaluation agent if it exists 

234 # 日本語: 評価エージェントが存在する場合は更新 

235 if self.pipeline.eval_agent and evaluation_instructions: 

236 self.pipeline.eval_agent.instructions = evaluation_instructions.strip() 

237 

238 def clear_history(self) -> None: 

239 """ 

240 Clear both pipeline and session history 

241 パイプライン履歴とセッション履歴の両方をクリア 

242 """ 

243 self.pipeline._pipeline_history.clear() 

244 if self.pipeline.session_history: 

245 self.pipeline.session_history.clear() 

246 

247 def set_threshold(self, threshold: int) -> None: 

248 """ 

249 Update evaluation threshold 

250 評価閾値を更新する 

251 

252 Args: 

253 threshold: New threshold value (0-100) / 新しい閾値(0-100) 

254 """ 

255 if 0 <= threshold <= 100: 

256 self.pipeline.threshold = threshold 

257 else: 

258 raise ValueError("Threshold must be between 0 and 100") 

259 

260 def __str__(self) -> str: 

261 return f"GenAgent({self.name}, model={self.pipeline.model})" 

262 

263 def __repr__(self) -> str: 

264 return self.__str__() 

265 

266 

267# Utility function for creating GenAgent with common configurations 

268# 共通設定でGenAgentを作成するユーティリティ関数 

269 

270def create_simple_gen_agent( 

271 name: str, 

272 instructions: str, 

273 model: Optional[str] = None, 

274 next_step: Optional[str] = None, 

275 threshold: int = 85, 

276 retries: int = 3 

277) -> GenAgent: 

278 """ 

279 Create a simple GenAgent with basic configuration 

280 基本設定でシンプルなGenAgentを作成 

281 

282 Args: 

283 name: Agent name / エージェント名 

284 instructions: Generation instructions / 生成指示 

285 model: LLM model name / LLMモデル名 

286 next_step: Next step after execution / 実行後の次ステップ 

287 threshold: Evaluation threshold / 評価閾値 

288 retries: Number of retries / リトライ回数 

289 

290 Returns: 

291 GenAgent: Configured GenAgent instance / 設定済みGenAgentインスタンス 

292 """ 

293 return GenAgent( 

294 name=name, 

295 generation_instructions=instructions, 

296 evaluation_instructions=None, # No evaluation for simple agent 

297 model=model, 

298 next_step=next_step, 

299 threshold=threshold, 

300 retries=retries 

301 ) 

302 

303 

304def create_evaluated_gen_agent( 

305 name: str, 

306 generation_instructions: str, 

307 evaluation_instructions: str, 

308 model: Optional[str] = None, 

309 evaluation_model: Optional[str] = None, 

310 next_step: Optional[str] = None, 

311 threshold: int = 85, 

312 retries: int = 3 

313) -> GenAgent: 

314 """ 

315 Create a GenAgent with both generation and evaluation 

316 生成と評価の両方を持つGenAgentを作成 

317 

318 Args: 

319 name: Agent name / エージェント名 

320 generation_instructions: Generation instructions / 生成指示 

321 evaluation_instructions: Evaluation instructions / 評価指示 

322 model: LLM model name / LLMモデル名 

323 evaluation_model: Evaluation model name / 評価モデル名 

324 next_step: Next step after execution / 実行後の次ステップ 

325 threshold: Evaluation threshold / 評価閾値 

326 retries: Number of retries / リトライ回数 

327 

328 Returns: 

329 GenAgent: Configured GenAgent instance / 設定済みGenAgentインスタンス 

330 """ 

331 return GenAgent( 

332 name=name, 

333 generation_instructions=generation_instructions, 

334 evaluation_instructions=evaluation_instructions, 

335 model=model, 

336 evaluation_model=evaluation_model, 

337 next_step=next_step, 

338 threshold=threshold, 

339 retries=retries 

340 )