Composable Flow Architecture - 組み合わせ可能なフローアーキテクチャ¶
Refinireの第三の柱である組み合わせ可能なフローアーキテクチャは、複雑なAIワークフローを柔軟で再利用可能なコンポーネントから構築できる革新的なシステムです。
基本概念¶
従来の線形処理から脱却し、条件分岐、ループ、並列処理を含む複雑なワークフローを直感的に定義・実行できます。
from refinire import Flow, FunctionStep, Context
import asyncio
# シンプルなフロー定義
def analyze_input(user_input, ctx):
ctx.shared_state["analysis"] = f"分析済み: {user_input}"
return ctx
def generate_response(user_input, ctx):
analysis = ctx.shared_state["analysis"]
ctx.shared_state["response"] = f"{analysis}に基づく回答"
ctx.finish()
return ctx
# フロー構築
flow = Flow([
("analyze", FunctionStep("analyze", analyze_input)),
("respond", FunctionStep("respond", generate_response))
])
# 実行
result = asyncio.run(flow.run(input_data="ユーザーリクエスト"))
簡単な事例¶
1. 基本的な順次フロー¶
from refinire import Flow, FunctionStep, Context
def step1(input_data, context):
context.shared_state["step1_result"] = f"処理1: {input_data}"
print(f"ステップ1実行: {input_data}")
return context
def step2(input_data, context):
previous = context.shared_state["step1_result"]
context.shared_state["step2_result"] = f"処理2: {previous}"
print(f"ステップ2実行: {previous}")
context.finish() # フロー完了
return context
# 順次実行フロー
sequential_flow = Flow([
("first", FunctionStep("first", step1)),
("second", FunctionStep("second", step2))
])
# 実行
result = sequential_flow.run_sync(input_data="開始データ")
print(f"最終結果: {result.shared_state}")
2. 条件分岐フロー¶
from refinire import Flow, FunctionStep, ConditionStep
def check_input_length(context):
"""入力の長さで分岐判定"""
return len(context.user_input) > 10
def simple_process(input_data, context):
context.shared_state["result"] = f"簡単処理: {input_data}"
context.finish()
return context
def complex_process(input_data, context):
context.shared_state["result"] = f"複雑処理: {input_data[:10]}..."
context.finish()
return context
# 条件分岐フロー
conditional_flow = Flow({
"start": ConditionStep("start", check_input_length, "complex", "simple"),
"simple": FunctionStep("simple", simple_process),
"complex": FunctionStep("complex", complex_process)
})
# テスト
short_result = conditional_flow.run_sync("短い")
long_result = conditional_flow.run_sync("これは非常に長い入力データです")
print(f"短い入力: {short_result.shared_state['result']}")
print(f"長い入力: {long_result.shared_state['result']}")
中級事例¶
3. AIエージェント組み込みフロー¶
from refinire import Flow, FunctionStep, create_simple_gen_agent
def create_ai_workflow():
"""AIエージェントを組み込んだワークフロー"""
# AIエージェント作成
analyzer = create_simple_gen_agent(
"analyzer",
"入力を分析して要点を抽出してください",
"gpt-4o-mini"
)
responder = create_simple_gen_agent(
"responder",
"分析結果に基づいて親切な回答を生成してください",
"gpt-4o-mini"
)
def ai_analysis_step(input_data, context):
"""AI分析ステップ"""
analysis_result = analyzer.run_sync(input_data, context)
analysis = analysis_result.shared_state["analyzer_result"]
context.shared_state["analysis"] = analysis
print(f"AI分析完了: {analysis}")
return context
def ai_response_step(input_data, context):
"""AI回答生成ステップ"""
analysis = context.shared_state["analysis"]
prompt = f"以下の分析に基づいて回答してください: {analysis}"
response_result = responder.run_sync(prompt, context)
response = response_result.shared_state["responder_result"]
context.shared_state["final_response"] = response
context.finish()
return context
# AIワークフロー構築
ai_flow = Flow([
("analyze", FunctionStep("analyze", ai_analysis_step)),
("respond", FunctionStep("respond", ai_response_step))
])
return ai_flow
# 使用例
ai_workflow = create_ai_workflow()
result = ai_workflow.run_sync("プログラミング学習について相談があります")
print(f"最終回答: {result.shared_state['final_response']}")
4. DAG並列処理フロー¶
from refinire import Flow, FunctionStep, create_simple_gen_agent
def create_parallel_analysis_flow():
"""複数の分析を並列実行するフロー"""
# 前処理ステップ
def preprocess_step(input_data, context):
context.shared_state["preprocessed_data"] = f"前処理済み: {input_data}"
print(f"前処理完了: {input_data}")
return context
# 並列分析ステップ
def sentiment_analysis(input_data, context):
data = context.shared_state["preprocessed_data"]
# 実際にはAIエージェントを使用
context.shared_state["sentiment"] = f"感情分析結果: ポジティブ ({data})"
print("感情分析完了")
return context
def keyword_extraction(input_data, context):
data = context.shared_state["preprocessed_data"]
context.shared_state["keywords"] = f"キーワード: AI, 技術, 進歩 ({data})"
print("キーワード抽出完了")
return context
def category_classification(input_data, context):
data = context.shared_state["preprocessed_data"]
context.shared_state["category"] = f"カテゴリ: 技術 ({data})"
print("カテゴリ分類完了")
return context
# 結果統合ステップ
def aggregate_results(input_data, context):
sentiment = context.shared_state.get("sentiment", "")
keywords = context.shared_state.get("keywords", "")
category = context.shared_state.get("category", "")
final_result = f"""
分析結果統合:
- {sentiment}
- {keywords}
- {category}
"""
context.shared_state["final_analysis"] = final_result
context.finish()
return context
# DAG構造で並列処理を定義
parallel_flow = Flow({
"preprocess": FunctionStep("preprocess", preprocess_step),
"parallel_analysis": {
"parallel": [
FunctionStep("sentiment", sentiment_analysis),
FunctionStep("keywords", keyword_extraction),
FunctionStep("category", category_classification)
]
},
"aggregate": FunctionStep("aggregate", aggregate_results)
})
return parallel_flow
# 使用例
parallel_analysis = create_parallel_analysis_flow()
result = parallel_analysis.run_sync("AI技術について考えています")
print(result.shared_state["final_analysis"])
5. 動的フロー生成¶
class DynamicFlowBuilder:
"""動的にフローを構築するビルダー"""
def __init__(self):
self.steps = []
self.step_count = 0
def add_processing_step(self, name: str, process_func):
"""処理ステップを追加"""
self.steps.append((name, FunctionStep(name, process_func)))
self.step_count += 1
return self
def add_validation_step(self, name: str, validation_func):
"""検証ステップを追加"""
def validation_wrapper(input_data, context):
if validation_func(input_data, context):
print(f"✓ 検証成功: {name}")
return context
else:
context.shared_state["error"] = f"検証失敗: {name}"
context.finish()
return context
self.steps.append((name, FunctionStep(name, validation_wrapper)))
return self
def add_ai_agent_step(self, name: str, instructions: str, model: str = "gpt-4o-mini"):
"""AIエージェントステップを追加"""
agent = create_simple_gen_agent(name, instructions, model)
def ai_step(input_data, context):
result = agent.run_sync(input_data, context)
context.shared_state[f"{name}_result"] = result.shared_state[f"{name}_result"]
return context
self.steps.append((name, FunctionStep(name, ai_step)))
return self
def build(self) -> Flow:
"""フローを構築"""
if not self.steps:
raise ValueError("ステップが定義されていません")
# 最後のステップで finish() を呼ぶように調整
if self.steps:
last_step_name, last_step = self.steps[-1]
original_func = last_step.func
def finishing_wrapper(input_data, context):
context = original_func(input_data, context)
if not context.finished:
context.finish()
return context
self.steps[-1] = (last_step_name, FunctionStep(last_step_name, finishing_wrapper))
return Flow(self.steps)
# 使用例
builder = DynamicFlowBuilder()
# フローを動的に構築
complex_flow = (builder
.add_processing_step("preprocess", lambda data, ctx: ctx.update({"preprocessed": f"前処理済み: {data}"}))
.add_validation_step("validate", lambda data, ctx: len(data) > 5)
.add_ai_agent_step("analyze", "入力を詳細に分析してください")
.add_ai_agent_step("summarize", "分析結果を簡潔にまとめてください")
.build())
# 実行
result = complex_flow.run_sync("複雑なデータ処理タスク")
print(f"処理結果: {result.shared_state}")
高度な事例¶
5. エラーハンドリング付き復旧フロー¶
class ResilientFlowSystem:
"""エラー回復機能付きフローシステム"""
def __init__(self):
self.error_handlers = {}
self.retry_configs = {}
def add_error_handler(self, step_name: str, handler_func):
"""ステップ専用エラーハンドラーを追加"""
self.error_handlers[step_name] = handler_func
return self
def add_retry_config(self, step_name: str, max_retries: int = 3, delay: float = 1.0):
"""リトライ設定を追加"""
self.retry_configs[step_name] = {
"max_retries": max_retries,
"delay": delay
}
return self
def create_resilient_step(self, name: str, step_func):
"""エラー回復機能付きステップ作成"""
def resilient_wrapper(input_data, context):
"""エラー回復ラッパー"""
retry_config = self.retry_configs.get(name, {"max_retries": 1, "delay": 0})
max_retries = retry_config["max_retries"]
delay = retry_config["delay"]
for attempt in range(max_retries):
try:
# ステップ実行
result = step_func(input_data, context)
if attempt > 0:
print(f"✓ {name}: {attempt + 1}回目の試行で成功")
return result
except Exception as e:
error_info = {
"step": name,
"attempt": attempt + 1,
"error": str(e),
"max_retries": max_retries
}
# エラーハンドラーの実行
if name in self.error_handlers:
try:
recovery_result = self.error_handlers[name](error_info, context)
if recovery_result:
print(f"✓ {name}: エラーハンドラーで復旧成功")
return recovery_result
except Exception as handler_error:
print(f"✗ {name}: エラーハンドラーも失敗 - {handler_error}")
# 最後の試行でない場合はリトライ
if attempt < max_retries - 1:
print(f"⚠️ {name}: 試行{attempt + 1}失敗、{delay}秒後にリトライ - {e}")
import time
time.sleep(delay)
else:
# 最終的に失敗
context.shared_state["error"] = error_info
context.shared_state["failed_step"] = name
print(f"✗ {name}: 全ての試行が失敗 - {e}")
raise e
return context
return FunctionStep(name, resilient_wrapper)
def create_fault_tolerant_flow(self, step_definitions: List[Dict]) -> Flow:
"""フォルトトレラントフロー作成"""
steps = []
for step_def in step_definitions:
name = step_def["name"]
func = step_def["func"]
# エラーハンドラー設定
if "error_handler" in step_def:
self.add_error_handler(name, step_def["error_handler"])
# リトライ設定
if "retry_config" in step_def:
retry_config = step_def["retry_config"]
self.add_retry_config(
name,
retry_config.get("max_retries", 3),
retry_config.get("delay", 1.0)
)
# エラー回復機能付きステップを作成
resilient_step = self.create_resilient_step(name, func)
steps.append((name, resilient_step))
return Flow(steps)
# 使用例
resilient_system = ResilientFlowSystem()
# エラーが発生する可能性のある処理関数
def unreliable_data_fetch(input_data, context):
"""不安定なデータ取得(ランダムに失敗)"""
import random
if random.random() < 0.7: # 70%の確率で失敗
raise Exception("ネットワークエラー")
context.shared_state["fetched_data"] = f"取得データ: {input_data}"
return context
def unreliable_ai_processing(input_data, context):
"""不安定なAI処理(ランダムに失敗)"""
import random
if random.random() < 0.5: # 50%の確率で失敗
raise Exception("AI処理エラー")
data = context.shared_state.get("fetched_data", input_data)
context.shared_state["ai_result"] = f"AI処理結果: {data}"
context.finish()
return context
# エラーハンドラー定義
def data_fetch_error_handler(error_info, context):
"""データ取得エラーのハンドラー"""
print(f"データ取得エラーハンドラー実行: {error_info['error']}")
# フォールバックデータを設定
context.shared_state["fetched_data"] = "フォールバックデータ"
return context
def ai_processing_error_handler(error_info, context):
"""AI処理エラーのハンドラー"""
print(f"AI処理エラーハンドラー実行: {error_info['error']}")
# 簡易処理で代替
data = context.shared_state.get("fetched_data", "デフォルトデータ")
context.shared_state["ai_result"] = f"簡易処理結果: {data}"
context.finish()
return context
# フォルトトレラントフロー定義
fault_tolerant_steps = [
{
"name": "data_fetch",
"func": unreliable_data_fetch,
"retry_config": {"max_retries": 3, "delay": 0.5},
"error_handler": data_fetch_error_handler
},
{
"name": "ai_process",
"func": unreliable_ai_processing,
"retry_config": {"max_retries": 2, "delay": 1.0},
"error_handler": ai_processing_error_handler
}
]
# フロー作成・実行
fault_tolerant_flow = resilient_system.create_fault_tolerant_flow(fault_tolerant_steps)
try:
result = fault_tolerant_flow.run_sync("テストデータ")
print(f"\n最終結果: {result.shared_state}")
except Exception as e:
print(f"\nフロー実行失敗: {e}")
メリット¶
- 柔軟性: 複雑なワークフローを直感的に定義
- 再利用性: ステップの組み合わせで多様なフローを構築
- 拡張性: 新しいステップタイプの簡単な追加
- デバッグ性: 各ステップの状態とデータフローが透明
組み合わせ可能なフローアーキテクチャにより、開発者は複雑なAIワークフローを効率的に構築・保守できます。