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
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-04 17:38 +0900
1from __future__ import annotations
3"""GenAgent — AgentPipeline as a Step for Flow workflows.
5GenAgentはAgentPipelineをStepとして使用するためのクラスです。
6これにより、AgentPipelineをFlowワークフロー内で直接使用できます。
7"""
9import asyncio
10from typing import Any, Callable, List, Dict, Optional, Type
11from concurrent.futures import ThreadPoolExecutor
13from .step import Step
14from .context import Context
15from .pipeline import AgentPipeline, EvaluationResult
18class GenAgent(Step):
19 """
20 Step implementation that wraps AgentPipeline functionality
21 AgentPipeline機能をラップするStep実装
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 """
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を初期化する
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)
85 # Store flow-specific configuration
86 # フロー固有の設定を保存
87 self.next_step = next_step
88 self.store_result_key = store_result_key or f"{name}_result"
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 )
114 async def run(self, user_input: Optional[str], ctx: Context) -> Context:
115 """
116 Execute GenAgent step using AgentPipeline
117 AgentPipelineを使用してGenAgentステップを実行する
119 Args:
120 user_input: User input for the pipeline / パイプライン用ユーザー入力
121 ctx: Current workflow context / 現在のワークフローコンテキスト
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)
130 try:
131 # English: Determine input text for pipeline
132 # 日本語: パイプライン用入力テキストを決定
133 input_text = user_input or ctx.last_user_input or ""
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
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
156 # English: Add result as assistant message
157 # 日本語: 結果をアシスタントメッセージとして追加
158 ctx.add_assistant_message(str(result))
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
169 # English: Add failure system message
170 # 日本語: 失敗システムメッセージを追加
171 ctx.add_system_message(f"GenAgent {self.name}: Pipeline execution failed (evaluation threshold not met)")
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
181 # English: Log error for debugging
182 # 日本語: デバッグ用エラーログ
183 print(f"🚨 {error_msg}")
185 # English: Set next step if specified
186 # 日本語: 指定されている場合は次ステップを設定
187 if self.next_step:
188 ctx.goto(self.next_step)
190 return ctx
192 def get_pipeline_history(self) -> List[Dict[str, str]]:
193 """
194 Get the internal pipeline history
195 内部パイプライン履歴を取得する
197 Returns:
198 List[Dict[str, str]]: Pipeline history / パイプライン履歴
199 """
200 return self.pipeline._pipeline_history
202 def get_session_history(self) -> Optional[List[str]]:
203 """
204 Get the session history
205 セッション履歴を取得する
207 Returns:
208 Optional[List[str]]: Session history / セッション履歴
209 """
210 return self.pipeline.session_history
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 パイプライン指示を更新する
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()
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()
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()
247 def set_threshold(self, threshold: int) -> None:
248 """
249 Update evaluation threshold
250 評価閾値を更新する
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")
260 def __str__(self) -> str:
261 return f"GenAgent({self.name}, model={self.pipeline.model})"
263 def __repr__(self) -> str:
264 return self.__str__()
267# Utility function for creating GenAgent with common configurations
268# 共通設定でGenAgentを作成するユーティリティ関数
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を作成
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 / リトライ回数
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 )
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を作成
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 / リトライ回数
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 )