Composable Flow Architecture - 組み合わせ可能なフローアーキテクチャ - Refinire
Author: kitfactory
Description: 複数のLLMプロバイダーに対応した統一インターフェースライブラリ

コンテンツにスキップ

# 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ワークフローを効率的に構築・保守できます。