Coverage for src/refinire/agents/clarify_agent.py: 83%

174 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-15 18:51 +0900

1from __future__ import annotations 

2 

3"""ClarifyAgent — Interactive Requirements Clarification Agent for Flow workflows. 

4 

5ClarifyAgentはユーザーとの対話を通じて必要なデータモデルクラスの情報を収集するStepクラスです。 

6GenAgentを参考に作成されており、Flowワークフロー内で使用できます。 

7""" 

8 

9import asyncio 

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

11from dataclasses import dataclass 

12import json 

13 

14from .flow.step import Step 

15from .flow.context import Context 

16from .pipeline.llm_pipeline import ( 

17 LLMPipeline, LLMResult, InteractivePipeline, InteractionResult, InteractionQuestion 

18) 

19 

20try: 

21 from pydantic import BaseModel # type: ignore 

22except ImportError: 

23 BaseModel = object # type: ignore 

24 

25# English: Generic type variable for user requirement type 

26# 日本語: ユーザー要求型用のジェネリック型変数 

27T = TypeVar('T') 

28 

29 

30class ClarifyBase(BaseModel): 

31 """ 

32 Base class for requirement clarification output 

33 要件明確化出力のベースクラス 

34  

35 Attributes: 

36 clearity: True if requirements are confirmed / 要件が確定した場合True 

37 """ 

38 clearity: bool # True if requirements are confirmed / 要件が確定した場合True 

39 

40 

41class ClarifyGeneric(ClarifyBase, Generic[T]): 

42 """ 

43 Generic clarification output with typed user requirement 

44 型付きユーザー要求を持つジェネリック明確化出力 

45  

46 Attributes: 

47 clearity: True if requirements are confirmed / 要件が確定した場合True  

48 user_requirement: Confirmed user requirement / 確定したユーザー要求 

49 """ 

50 user_requirement: Optional[T] = None # Confirmed user requirement / 確定したユーザー要求 

51 

52 

53class Clarify(ClarifyBase): 

54 """ 

55 Default clarification output with string user requirement 

56 文字列ユーザー要求を持つデフォルト明確化出力 

57  

58 Attributes: 

59 clearity: True if requirements are confirmed / 要件が確定した場合True 

60 user_requirement: Confirmed user requirement as string / 文字列として確定したユーザー要求 

61 """ 

62 user_requirement: Optional[str] = None # Confirmed user requirement as string / 文字列として確定したユーザー要求 

63 

64 

65@dataclass 

66class ClarificationQuestion: 

67 """ 

68 Represents a clarification question from the pipeline 

69 パイプラインからの明確化質問を表現するクラス 

70  

71 Attributes: 

72 question: The clarification question text / 明確化質問テキスト 

73 turn: Current turn number / 現在のターン番号 

74 remaining_turns: Remaining turns / 残りターン数 

75 """ 

76 question: str # The clarification question text / 明確化質問テキスト 

77 turn: int # Current turn number / 現在のターン番号 

78 remaining_turns: int # Remaining turns / 残りターン数 

79 

80 def __str__(self) -> str: 

81 """ 

82 String representation of the clarification question 

83 明確化質問の文字列表現 

84  

85 Returns: 

86 str: Formatted question with turn info / ターン情報付きフォーマット済み質問 

87 """ 

88 return f"[ターン {self.turn}/{self.turn + self.remaining_turns}] {self.question}" 

89 

90 

91class ClarifyPipeline: 

92 """ 

93 ClarifyPipeline class for requirements clarification using InteractivePipeline 

94 InteractivePipelineを使用した要件明確化パイプラインクラス 

95  

96 This class wraps InteractivePipeline to handle: 

97 このクラスはInteractivePipelineをラップして以下を処理します: 

98 - Iterative requirement clarification / 反復的な要件明確化 

99 - Type-safe output wrapping / 型安全な出力ラッピング 

100 - Maximum turn control / 最大ターン数制御 

101 - Structured requirement extraction / 構造化された要求抽出 

102 """ 

103 

104 def __init__( 

105 self, 

106 name: str, 

107 generation_instructions: str, 

108 output_data: Optional[Type[Any]] = None, 

109 clerify_max_turns: int = 20, 

110 evaluation_instructions: Optional[str] = None, 

111 model: Optional[str] = None, 

112 evaluation_model: Optional[str] = None, 

113 threshold: int = 85, 

114 retries: int = 3, 

115 tools: Optional[List[Dict]] = None, 

116 mcp_servers: Optional[List[str]] = None, 

117 **kwargs 

118 ) -> None: 

119 """ 

120 Initialize the ClarifyPipeline with configuration parameters 

121 設定パラメータでClarifyPipelineを初期化する 

122  

123 Args: 

124 name: Pipeline name / パイプライン名 

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

126 output_data: Output data model type / 出力データモデル型 

127 clerify_max_turns: Maximum number of clarification turns / 最大明確化ターン数 

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

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

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

131 threshold: Evaluation threshold / 評価閾値 

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

133 **kwargs: Additional arguments for GenAgent / GenAgent用追加引数 

134 """ 

135 

136 # English: Store original output data type before wrapping 

137 # 日本語: ラッピング前の元の出力データ型を保存 

138 self.original_output_data = output_data 

139 self.clerify_max_turns = clerify_max_turns 

140 

141 # English: Create wrapped output model based on provided type 

142 # 日本語: 提供された型に基づいてラップされた出力モデルを作成 

143 if output_data is not None: 

144 # English: For typed output, create generic wrapper 

145 # 日本語: 型付き出力の場合、ジェネリックラッパーを作成 

146 wrapped_output_model = self._create_wrapped_model(output_data) 

147 else: 

148 # English: For untyped output, use default string wrapper 

149 # 日本語: 型なし出力の場合、デフォルトの文字列ラッパーを使用 

150 wrapped_output_model = Clarify 

151 

152 # English: Enhanced generation instructions for clarification 

153 # 日本語: 明確化用の拡張生成指示 

154 enhanced_instructions = self._build_clarification_instructions( 

155 generation_instructions, 

156 output_data 

157 ) 

158 

159 # English: Filter kwargs for InteractivePipeline compatibility 

160 # 日本語: InteractivePipeline互換性のためkwargsをフィルタリング 

161 pipeline_kwargs = { 

162 k: v for k, v in kwargs.items() 

163 if k in [ 

164 'temperature', 'max_tokens', 'timeout', 'input_guardrails', 

165 'output_guardrails', 'session_history', 'history_size', 

166 'improvement_callback', 'locale' 

167 ] 

168 } 

169 

170 # English: Add tools and MCP servers if provided 

171 # 日本語: 提供された場合はtoolsとMCPサーバーを追加 

172 if tools is not None: 

173 pipeline_kwargs['tools'] = tools 

174 if mcp_servers is not None: 

175 pipeline_kwargs['mcp_servers'] = mcp_servers 

176 

177 # English: Create internal InteractivePipeline instance 

178 # 日本語: 内部InteractivePipelineインスタンスを作成 

179 self.interactive_pipeline = InteractivePipeline( 

180 name=f"{name}_pipeline", 

181 generation_instructions=enhanced_instructions, 

182 evaluation_instructions=evaluation_instructions, 

183 output_model=wrapped_output_model, 

184 completion_check=self._is_clarification_complete, 

185 max_turns=clerify_max_turns, 

186 question_format=self._format_clarification_question, 

187 model=model, 

188 evaluation_model=evaluation_model, 

189 threshold=threshold, 

190 max_retries=retries, 

191 **pipeline_kwargs 

192 ) 

193 

194 def _create_wrapped_model(self, output_data_type: Type[Any]) -> Type[BaseModel]: 

195 """ 

196 Create a wrapped output model for the given type 

197 指定された型用のラップされた出力モデルを作成する 

198  

199 Args: 

200 output_data_type: Original output data type / 元の出力データ型 

201  

202 Returns: 

203 Type[BaseModel]: Wrapped model type / ラップされたモデル型 

204 """ 

205 # English: Create dynamic Pydantic model that wraps the original type 

206 # 日本語: 元の型をラップする動的Pydanticモデルを作成 

207 

208 class WrappedClarify(BaseModel): 

209 clearity: bool # True if requirements are confirmed / 要件が確定した場合True 

210 user_requirement: Optional[output_data_type] = None # Confirmed user requirement / 確定したユーザー要求 

211 

212 return WrappedClarify 

213 

214 def _is_clarification_complete(self, result: Any) -> bool: 

215 """ 

216 Check if clarification is complete based on result 

217 結果に基づいて明確化が完了しているかをチェック 

218  

219 Args: 

220 result: LLM result content / LLM結果コンテンツ 

221  

222 Returns: 

223 bool: True if clarification is complete / 明確化が完了している場合True 

224 """ 

225 return (hasattr(result, 'clearity') and result.clearity) or \ 

226 (hasattr(result, 'user_requirement') and result.user_requirement is not None) 

227 

228 def _format_clarification_question(self, response: str, turn: int, remaining: int) -> str: 

229 """ 

230 Format clarification response as a question 

231 明確化応答を質問としてフォーマット 

232  

233 Args: 

234 response: AI response / AI応答 

235 turn: Current turn / 現在のターン 

236 remaining: Remaining turns / 残りターン 

237  

238 Returns: 

239 str: Formatted question / フォーマット済み質問 

240 """ 

241 return f"[ターン {turn}/{turn + remaining}] {response}" 

242 

243 def _build_clarification_instructions( 

244 self, 

245 base_instructions: str, 

246 output_data_type: Optional[Type[Any]] 

247 ) -> str: 

248 """ 

249 Build enhanced instructions for clarification process 

250 明確化プロセス用の拡張指示を構築する 

251  

252 Args: 

253 base_instructions: Base generation instructions / ベース生成指示 

254 output_data_type: Output data type for schema reference / スキーマ参照用出力データ型 

255  

256 Returns: 

257 str: Enhanced instructions / 拡張指示 

258 """ 

259 schema_info = "" 

260 if output_data_type is not None: 

261 try: 

262 # English: Try to get schema information if available 

263 # 日本語: 利用可能な場合はスキーマ情報を取得を試行 

264 if hasattr(output_data_type, 'model_json_schema'): 

265 schema = output_data_type.model_json_schema() 

266 schema_info = f"\n\n必要な出力形式のスキーマ:\n{json.dumps(schema, indent=2, ensure_ascii=False)}" 

267 elif hasattr(output_data_type, '__annotations__'): 

268 annotations = output_data_type.__annotations__ 

269 schema_info = f"\n\n必要なフィールド: {list(annotations.keys())}" 

270 except Exception: 

271 pass 

272 

273 enhanced_instructions = f""" 

274{base_instructions} 

275 

276あなたは要件明確化の専門家です。以下のルールに従ってください: 

277 

2781. ユーザーの要求を理解し、不明確な点や不足している情報を特定する 

2792. 要件が不完全な場合は、clarityをfalseにして、必要な追加情報を質問する 

2803. すべての必要な情報が揃い、要件が明確になった場合のみ、clarityをtrueにして確定する 

2814. 質問は一度に一つずつ、分かりやすく行う 

2825. 最大{self.clerify_max_turns}ターンまで質問できる 

283{schema_info} 

284 

285出力形式: 

286- clarity: 要件が確定した場合はtrue、追加質問が必要な場合はfalse 

287- user_requirement: 要件が確定した場合のみ、完全な要求データを含める 

288""" 

289 

290 return enhanced_instructions 

291 

292 def run(self, user_input: str) -> Any: 

293 """ 

294 Execute the clarification pipeline 

295 明確化パイプラインを実行する 

296  

297 Args: 

298 user_input: User input for clarification / 明確化用ユーザー入力 

299  

300 Returns: 

301 Any: Clarification result or question / 明確化結果または質問 

302 """ 

303 interaction_result = self.interactive_pipeline.run_interactive(user_input) 

304 return self._convert_interaction_result(interaction_result) 

305 

306 def continue_clarification(self, user_response: str) -> Any: 

307 """ 

308 Continue the clarification process with user response 

309 ユーザー応答で明確化プロセスを継続する 

310  

311 Args: 

312 user_response: User response to previous question / 前の質問へのユーザー応答 

313  

314 Returns: 

315 Any: Next clarification result or question / 次の明確化結果または質問 

316 """ 

317 interaction_result = self.interactive_pipeline.continue_interaction(user_response) 

318 return self._convert_interaction_result(interaction_result) 

319 

320 def _convert_interaction_result(self, interaction_result: InteractionResult) -> Any: 

321 """ 

322 Convert InteractionResult to ClarifyPipeline format 

323 InteractionResultをClarifyPipeline形式に変換する 

324  

325 Args: 

326 interaction_result: Result from InteractivePipeline / InteractivePipelineからの結果 

327  

328 Returns: 

329 Any: Clarification response / 明確化応答 

330 """ 

331 if interaction_result.is_complete: 

332 # English: Interaction complete - return final result 

333 # 日本語: 対話完了 - 最終結果を返す 

334 return interaction_result.content 

335 else: 

336 # English: Convert InteractionQuestion to ClarificationQuestion 

337 # 日本語: InteractionQuestionをClarificationQuestionに変換 

338 if isinstance(interaction_result.content, InteractionQuestion): 

339 return ClarificationQuestion( 

340 question=interaction_result.content.question, 

341 turn=interaction_result.turn, 

342 remaining_turns=interaction_result.remaining_turns 

343 ) 

344 else: 

345 # English: Create ClarificationQuestion from content 

346 # 日本語: コンテンツからClarificationQuestionを作成 

347 return ClarificationQuestion( 

348 question=str(interaction_result.content), 

349 turn=interaction_result.turn, 

350 remaining_turns=interaction_result.remaining_turns 

351 ) 

352 

353 def reset_turns(self) -> None: 

354 """ 

355 Reset turn counter 

356 ターンカウンターをリセットする 

357 """ 

358 self.interactive_pipeline.reset_interaction() 

359 

360 def reset_session(self) -> None: 

361 """ 

362 Reset the entire clarification session 

363 明確化セッション全体をリセットする 

364 """ 

365 self.interactive_pipeline.reset_interaction() 

366 

367 @property 

368 def is_complete(self) -> bool: 

369 """ 

370 Check if clarification is complete 

371 明確化が完了しているかを確認する 

372  

373 Returns: 

374 bool: True if complete / 完了している場合True 

375 """ 

376 return self.interactive_pipeline.is_complete 

377 

378 @property 

379 def conversation_history(self) -> List[Dict[str, Any]]: 

380 """ 

381 Get conversation history 

382 会話履歴を取得する 

383  

384 Returns: 

385 List[Dict[str, Any]]: Conversation history / 会話履歴 

386 """ 

387 return self.interactive_pipeline.interaction_history 

388 

389 @property 

390 def current_turn(self) -> int: 

391 """ 

392 Get current turn number 

393 現在のターン番号を取得する 

394  

395 Returns: 

396 int: Current turn / 現在のターン 

397 """ 

398 return self.interactive_pipeline.current_turn 

399 

400 @property 

401 def remaining_turns(self) -> int: 

402 """ 

403 Get remaining turns 

404 残りターン数を取得する 

405  

406 Returns: 

407 int: Remaining turns / 残りターン数 

408 """ 

409 return self.interactive_pipeline.remaining_turns 

410 

411 @property 

412 def threshold(self) -> float: 

413 """ 

414 Get evaluation threshold from internal InteractivePipeline 

415 内部InteractivePipelineから評価閾値を取得する 

416  

417 Returns: 

418 float: Evaluation threshold / 評価閾値 

419 """ 

420 return self.interactive_pipeline.threshold 

421 

422 @property 

423 def retries(self) -> int: 

424 """ 

425 Get retry count from internal InteractivePipeline 

426 内部InteractivePipelineからリトライ回数を取得する 

427  

428 Returns: 

429 int: Retry count / リトライ回数 

430 """ 

431 return self.interactive_pipeline.max_retries 

432 

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

434 """ 

435 Get session history as string list 

436 セッション履歴を文字列リストとして取得する 

437  

438 Returns: 

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

440 """ 

441 return self.interactive_pipeline.get_session_history() 

442 

443 

444@dataclass 

445class ClarificationResult: 

446 """ 

447 Result of clarification process 

448 明確化プロセスの結果 

449  

450 Attributes: 

451 is_complete: True if clarification is complete / 明確化が完了した場合True 

452 data: Clarified data or next question / 明確化されたデータまたは次の質問 

453 turn: Current turn number / 現在のターン番号 

454 remaining_turns: Remaining turns / 残りターン数 

455 """ 

456 is_complete: bool # True if clarification is complete / 明確化が完了した場合True 

457 data: Any # Clarified data or next question / 明確化されたデータまたは次の質問 

458 turn: int # Current turn number / 現在のターン番号 

459 remaining_turns: int # Remaining turns / 残りターン数 

460 

461 

462class ClarifyAgent(Step): 

463 """ 

464 Step implementation for interactive requirements clarification 

465 対話的要件明確化のためのStep実装 

466  

467 This class allows clarifying user requirements through interactive dialog 

468 within Flow workflows, providing structured data collection capabilities. 

469 このクラスはFlowワークフロー内で対話的なダイアログを通じてユーザー要求を明確化し、 

470 構造化されたデータ収集機能を提供します。 

471 """ 

472 

473 def __init__( 

474 self, 

475 name: str, 

476 generation_instructions: str, 

477 output_data: Optional[Type[Any]] = None, 

478 *, 

479 clerify_max_turns: int = 20, 

480 evaluation_instructions: Optional[str] = None, 

481 input_guardrails: Optional[list] = None, 

482 output_guardrails: Optional[list] = None, 

483 model: str | None = None, 

484 evaluation_model: str | None = None, 

485 generation_tools: Optional[list] = None, 

486 evaluation_tools: Optional[list] = None, 

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

488 session_history: Optional[list] = None, 

489 history_size: int = 10, 

490 threshold: int = 85, 

491 retries: int = 3, 

492 improvement_callback: Optional[Callable[[Any, Any], None]] = None, 

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

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

495 locale: str = "en", 

496 next_step: Optional[str] = None, 

497 store_result_key: Optional[str] = None, 

498 conversation_key: Optional[str] = None, 

499 ) -> None: 

500 """ 

501 Initialize ClarifyAgent with clarification configuration 

502 明確化設定でClarifyAgentを初期化する 

503 

504 Args: 

505 name: Step name / ステップ名 

506 generation_instructions: System prompt for clarification / 明確化用システムプロンプト 

507 output_data: Target data model type / ターゲットデータモデル型 

508 clerify_max_turns: Maximum number of clarification turns / 最大明確化ターン数 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

525 next_step: Next step after clarification completion / 明確化完了後の次ステップ 

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

527 conversation_key: Key to store conversation state / 会話状態を格納するキー 

528 """ 

529 # Initialize Step base class 

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

531 super().__init__(name) 

532 

533 # Store flow-specific configuration 

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

535 self.next_step = next_step 

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

537 self.conversation_key = conversation_key or f"{name}_conversation" 

538 

539 # Create internal ClarifyPipeline instance 

540 # 内部ClarifyPipelineインスタンスを作成 

541 self.pipeline = ClarifyPipeline( 

542 name=f"{name}_pipeline", 

543 generation_instructions=generation_instructions, 

544 evaluation_instructions=evaluation_instructions, 

545 output_data=output_data, 

546 clerify_max_turns=clerify_max_turns, 

547 input_guardrails=input_guardrails, 

548 output_guardrails=output_guardrails, 

549 model=model, 

550 evaluation_model=evaluation_model, 

551 generation_tools=generation_tools, 

552 evaluation_tools=evaluation_tools, 

553 routing_func=routing_func, 

554 session_history=session_history, 

555 history_size=history_size, 

556 threshold=threshold, 

557 retries=retries, 

558 improvement_callback=improvement_callback, 

559 dynamic_prompt=dynamic_prompt, 

560 retry_comment_importance=retry_comment_importance, 

561 locale=locale, 

562 ) 

563 

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

565 """ 

566 Execute ClarifyAgent step using ClarifyPipeline 

567 ClarifyPipelineを使用してClarifyAgentステップを実行する 

568 

569 Args: 

570 user_input: User input for clarification / 明確化用ユーザー入力 

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

572 

573 Returns: 

574 Context: Updated context with clarification results / 明確化結果付き更新済みコンテキスト 

575 """ 

576 # English: Update step information in context 

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

578 ctx.update_step_info(self.name) 

579 

580 try: 

581 # English: Determine input text for clarification 

582 # 日本語: 明確化用入力テキストを決定 

583 input_text = user_input or ctx.last_user_input or "" 

584 

585 if not input_text: 

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

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

588 ctx.add_system_message(f"ClarifyAgent {self.name}: No input available, skipping clarification") 

589 result = ClarificationResult( 

590 is_complete=False, 

591 data=None, 

592 turn=0, 

593 remaining_turns=self.pipeline.clerify_max_turns 

594 ) 

595 else: 

596 # English: Check if this is a continuation of existing conversation 

597 # 日本語: 既存の会話の継続かを確認 

598 existing_conversation = ctx.shared_state.get(self.conversation_key) 

599 

600 # English: Execute clarification using GenAgent-based pipeline 

601 # 日本語: GenAgentベースのパイプラインを使用して明確化を実行 

602 if existing_conversation and not self.pipeline.is_complete: 

603 # English: Continue existing clarification 

604 # 日本語: 既存の明確化を継続 

605 pipeline_result = self.pipeline.continue_clarification(input_text) 

606 else: 

607 # English: Start new clarification 

608 # 日本語: 新しい明確化を開始 

609 pipeline_result = self.pipeline.run(input_text) 

610 

611 # English: Wrap pipeline result in ClarificationResult 

612 # 日本語: パイプライン結果をClarificationResultにラップ 

613 result = ClarificationResult( 

614 is_complete=self.pipeline.is_complete, 

615 data=pipeline_result, 

616 turn=self.pipeline.current_turn, 

617 remaining_turns=self.pipeline.remaining_turns 

618 ) 

619 

620 # English: Store conversation state 

621 # 日本語: 会話状態を保存 

622 ctx.shared_state[self.conversation_key] = { 

623 "is_complete": result.is_complete, 

624 "turn": result.turn, 

625 "remaining_turns": result.remaining_turns, 

626 "conversation_history": self.pipeline.conversation_history 

627 } 

628 

629 # English: Handle result based on completion status 

630 # 日本語: 完了状態に基づいて結果を処理 

631 if result.is_complete: 

632 # English: Clarification completed - store final result 

633 # 日本語: 明確化完了 - 最終結果を保存 

634 ctx.shared_state[self.store_result_key] = result.data 

635 ctx.prev_outputs[self.name] = result.data 

636 

637 # English: Add completion message 

638 # 日本語: 完了メッセージを追加 

639 ctx.add_assistant_message(f"要求明確化完了: {str(result.data)}") 

640 ctx.add_system_message(f"ClarifyAgent {self.name}: Clarification completed successfully") 

641 

642 # English: Set next step if specified 

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

644 if self.next_step: 

645 ctx.goto(self.next_step) 

646 

647 else: 

648 # English: Clarification in progress - store question 

649 # 日本語: 明確化進行中 - 質問を保存 

650 if isinstance(result.data, ClarificationQuestion): 

651 question_text = str(result.data) 

652 ctx.add_assistant_message(question_text) 

653 ctx.add_system_message(f"ClarifyAgent {self.name}: Clarification question asked (Turn {result.turn})") 

654 else: 

655 ctx.add_assistant_message(str(result.data)) 

656 ctx.add_system_message(f"ClarifyAgent {self.name}: Clarification in progress") 

657 

658 # English: Store intermediate result for potential continuation 

659 # 日本語: 継続可能性のため中間結果を保存 

660 ctx.shared_state[self.store_result_key] = result 

661 ctx.prev_outputs[self.name] = result 

662 

663 # English: Check if max turns reached and force completion 

664 # 日本語: 最大ターン数に達した場合は強制完了 

665 if result.remaining_turns <= 0 and self.next_step: 

666 ctx.add_system_message(f"ClarifyAgent {self.name}: Maximum turns reached, proceeding to next step") 

667 ctx.goto(self.next_step) 

668 

669 # English: Do not advance to next step - wait for user response 

670 # 日本語: 次ステップに進まない - ユーザー応答を待機 

671 

672 except Exception as e: 

673 # English: Handle execution errors 

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

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

676 ctx.add_system_message(error_msg) 

677 

678 # English: Store error result 

679 # 日本語: エラー結果を保存 

680 error_result = ClarificationResult( 

681 is_complete=False, 

682 data=None, 

683 turn=0, 

684 remaining_turns=0 

685 ) 

686 ctx.shared_state[self.store_result_key] = error_result 

687 ctx.prev_outputs[self.name] = error_result 

688 

689 # English: Log error for debugging 

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

691 print(f"🚨 {error_msg}") 

692 

693 return ctx 

694 

695 def get_conversation_history(self) -> List[Dict[str, Any]]: 

696 """ 

697 Get the conversation history from the internal pipeline 

698 内部パイプラインから会話履歴を取得する 

699 

700 Returns: 

701 List[Dict[str, Any]]: Conversation history / 会話履歴 

702 """ 

703 return self.pipeline.conversation_history 

704 

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

706 """ 

707 Get the session history from the internal pipeline 

708 内部パイプラインからセッション履歴を取得する 

709 

710 Returns: 

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

712 """ 

713 return self.pipeline.get_session_history() 

714 

715 def reset_clarification(self) -> None: 

716 """ 

717 Reset the clarification session 

718 明確化セッションをリセットする 

719 """ 

720 self.pipeline.reset_session() 

721 

722 def is_clarification_complete(self) -> bool: 

723 """ 

724 Check if the clarification process is complete 

725 明確化プロセスが完了しているかを確認する 

726 

727 Returns: 

728 bool: True if complete / 完了している場合True 

729 """ 

730 return self.pipeline.is_complete 

731 

732 @property 

733 def current_turn(self) -> int: 

734 """ 

735 Get current turn number 

736 現在のターン番号を取得する 

737 

738 Returns: 

739 int: Current turn number / 現在のターン番号 

740 """ 

741 return self.pipeline.current_turn 

742 

743 @property 

744 def remaining_turns(self) -> int: 

745 """ 

746 Get remaining turn count 

747 残りターン数を取得する 

748 

749 Returns: 

750 int: Remaining turns / 残りターン数 

751 """ 

752 return self.pipeline.remaining_turns 

753 

754 def __str__(self) -> str: 

755 return f"ClarifyAgent(name={self.name}, turns={self.current_turn}/{self.pipeline.clerify_max_turns})" 

756 

757 def __repr__(self) -> str: 

758 return self.__str__() 

759 

760 

761def create_simple_clarify_agent( 

762 name: str, 

763 instructions: str, 

764 output_data: Optional[Type[Any]] = None, 

765 max_turns: int = 20, 

766 model: Optional[str] = None, 

767 next_step: Optional[str] = None, 

768 tools: Optional[List[Dict]] = None, 

769 mcp_servers: Optional[List[str]] = None 

770) -> ClarifyAgent: 

771 """ 

772 Create a simple ClarifyAgent with basic configuration 

773 基本設定でシンプルなClarifyAgentを作成する 

774 

775 Args: 

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

777 instructions: Clarification instructions / 明確化指示 

778 output_data: Target data model type / ターゲットデータモデル型 

779 max_turns: Maximum clarification turns / 最大明確化ターン数 

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

781 next_step: Next step after completion / 完了後の次ステップ 

782 

783 Returns: 

784 ClarifyAgent: Configured ClarifyAgent instance / 設定済みClarifyAgentインスタンス 

785 """ 

786 return ClarifyAgent( 

787 name=name, 

788 generation_instructions=instructions, 

789 output_data=output_data, 

790 clerify_max_turns=max_turns, 

791 model=model, 

792 next_step=next_step 

793 ) 

794 

795 

796def create_evaluated_clarify_agent( 

797 name: str, 

798 generation_instructions: str, 

799 evaluation_instructions: str, 

800 output_data: Optional[Type[Any]] = None, 

801 max_turns: int = 20, 

802 model: Optional[str] = None, 

803 evaluation_model: Optional[str] = None, 

804 next_step: Optional[str] = None, 

805 threshold: int = 85, 

806 retries: int = 3, 

807 tools: Optional[List[Dict]] = None, 

808 mcp_servers: Optional[List[str]] = None 

809) -> ClarifyAgent: 

810 """ 

811 Create a ClarifyAgent with evaluation capabilities 

812 評価機能付きClarifyAgentを作成する 

813 

814 Args: 

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

816 generation_instructions: Generation instructions / 生成指示 

817 evaluation_instructions: Evaluation instructions / 評価指示 

818 output_data: Target data model type / ターゲットデータモデル型 

819 max_turns: Maximum clarification turns / 最大明確化ターン数 

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

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

822 next_step: Next step after completion / 完了後の次ステップ 

823 threshold: Evaluation threshold / 評価閾値 

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

825 

826 Returns: 

827 ClarifyAgent: Configured ClarifyAgent instance / 設定済みClarifyAgentインスタンス 

828 """ 

829 return ClarifyAgent( 

830 name=name, 

831 generation_instructions=generation_instructions, 

832 evaluation_instructions=evaluation_instructions, 

833 output_data=output_data, 

834 clerify_max_turns=max_turns, 

835 model=model, 

836 evaluation_model=evaluation_model, 

837 next_step=next_step, 

838 threshold=threshold, 

839 retries=retries 

840 )