コンテンツにスキップ

Composable Flow Architecture - 組み合わせ可能なフローアーキテクチャ

Refinireの第三の柱である組み合わせ可能なフローアーキテクチャは、複雑なAIワークフローを柔軟で再利用可能なコンポーネントから構築できる革新的なシステムです。

基本概念

従来の線形処理から脱却し、条件分岐、ループ、並列処理を含む複雑なワークフローを直感的に定義・実行できます。

from refinire import Flow, FunctionStep, create_simple_gen_agent
import asyncio

# 超シンプルなFlow - エージェント1つだけ
flow = Flow(steps=gen_agent)

# 複数ステップのFlow - 自動シーケンシャル実行
flow = Flow([
    ("preprocess", FunctionStep("preprocess", preprocess_func)),
    ("generate", gen_agent),
    ("postprocess", FunctionStep("postprocess", postprocess_func))
])

# 複雑な条件分岐Flow
flow = Flow({
    "input_analysis": FunctionStep("analyze", analyze_input),
    "simple_case": {
        "condition": lambda ctx: len(ctx.user_input) < 50,
        "step": simple_agent,
        "next_step": "output"
    },
    "complex_case": {
        "condition": lambda ctx: len(ctx.user_input) >= 50,
        "step": complex_agent, 
        "next_step": "output"
    },
    "output": FunctionStep("format", format_output)
})

核となる設計原則

1. 組み合わせ可能性 (Composability)

各ステップは独立したコンポーネントとして設計され、自由に組み合わせできます。

# 基本ステップを定義
preprocess_step = FunctionStep("preprocess", preprocess_data)
analysis_step = create_simple_gen_agent("analyzer", "データを分析してください", "gpt-4o-mini")
format_step = FunctionStep("format", format_results)

# 異なる組み合わせで再利用
quick_flow = Flow([("analyze", analysis_step)])
detailed_flow = Flow([
    ("preprocess", preprocess_step),
    ("analyze", analysis_step), 
    ("format", format_step)
])

2. 宣言的設定 (Declarative Configuration)

処理の「手順」ではなく「構造」を宣言的に定義します。

# 命令的な書き方(従来)
def process_text(input_text):
    if len(input_text) < 100:
        return simple_processor(input_text)
    else:
        preprocessed = preprocess(input_text)
        analyzed = complex_analysis(preprocessed)
        return postprocess(analyzed)

# 宣言的な書き方(Refinire)
flow = Flow({
    "route": ConditionStep("router", 
        condition=lambda ctx: "simple" if len(ctx.user_input) < 100 else "complex",
        branches={"simple": simple_agent, "complex": complex_pipeline}
    )
})

3. 状態管理の分離 (Separated State Management)

ステップ間の状態共有は Context オブジェクトによって明示的に管理されます。

def step1(user_input: str, ctx: Context) -> Context:
    """最初のステップ - データを処理して次ステップに渡す"""
    # English: First step - process data and pass to next step
    processed_data = preprocess(user_input)
    ctx.shared_state["processed"] = processed_data
    ctx.shared_state["timestamp"] = datetime.now()
    return ctx

def step2(user_input: str, ctx: Context) -> Context:
    """2番目のステップ - 前ステップの結果を使用"""
    # English: Second step - use results from previous step
    previous_result = ctx.shared_state["processed"]
    result = analyze(previous_result)
    ctx.shared_state["analysis"] = result
    return ctx

Flow作成パターン

パターン1: 単一エージェントFlow(最もシンプル)

from refinire import create_simple_gen_agent, Flow

# エージェント作成
agent = create_simple_gen_agent(
    name="assistant",
    instructions="ユーザーの質問に親切に回答してください。",
    model="gpt-4o-mini"
)

# 超シンプルなFlow - 1行で完成
flow = Flow(steps=agent)

# 実行
result = await flow.run(input_data="AIについて教えて")
print(result.shared_state["assistant_result"])

パターン2: シーケンシャルFlow(自動順次実行)

from refinire import Flow, FunctionStep, create_simple_gen_agent

def validate_input(user_input: str, ctx: Context) -> Context:
    """入力データの検証を行う"""
    # English: Validate input data
    if not user_input.strip():
        raise ValueError("空の入力は許可されていません")
    ctx.shared_state["validated_input"] = user_input.strip()
    return ctx

def preprocess_text(user_input: str, ctx: Context) -> Context:
    """テキストの前処理を実行"""
    # English: Execute text preprocessing
    validated = ctx.shared_state["validated_input"]
    processed = validated.lower().replace('\n', ' ')
    ctx.shared_state["preprocessed"] = processed
    return ctx

# 生成エージェント
generator = create_simple_gen_agent(
    name="content_gen",
    instructions="前処理されたテキストに基づいて、有用な内容を生成してください。",
    model="gpt-4o-mini"
)

def format_output(user_input: str, ctx: Context) -> Context:
    """出力フォーマットを整える"""
    # English: Format the output
    generated = ctx.shared_state["content_gen_result"]
    formatted = f"=== 生成結果 ===\n{generated}\n=== 終了 ==="
    ctx.shared_state["final_output"] = formatted
    ctx.finish()  # フロー終了を明示
    return ctx

# シーケンシャルFlow(自動で順次実行)
flow = Flow([
    ("validate", FunctionStep("validate", validate_input)),
    ("preprocess", FunctionStep("preprocess", preprocess_text)),
    ("generate", generator),
    ("format", FunctionStep("format", format_output))
])

# 実行
result = await flow.run(input_data="AIの未来について")
print(result.shared_state["final_output"])

パターン3: 条件分岐Flow

from refinire import Flow, ConditionStep, FunctionStep

def analyze_complexity(user_input: str, ctx: Context) -> Context:
    """入力の複雑さを分析"""
    # English: Analyze input complexity
    word_count = len(user_input.split())
    ctx.shared_state["word_count"] = word_count
    ctx.shared_state["complexity"] = "simple" if word_count < 20 else "complex"
    return ctx

def route_by_complexity(ctx: Context) -> str:
    """複雑さに基づいてルーティング"""
    # English: Route based on complexity
    return ctx.shared_state["complexity"]

# 単純な処理用エージェント
simple_agent = create_simple_gen_agent(
    name="simple_processor",
    instructions="簡潔に回答してください。",
    model="gpt-4o-mini"
)

# 複雑な処理用エージェント
complex_agent = create_simple_gen_agent(
    name="complex_processor", 
    instructions="詳細で包括的な分析を行い、段階的に説明してください。",
    model="gpt-4o-mini"
)

# 条件分岐Flow
flow = Flow({
    "analyze": FunctionStep("analyze", analyze_complexity),
    "router": ConditionStep("router", route_by_complexity, "simple", "complex"),
    "simple": simple_agent,
    "complex": complex_agent
})

# 実行
result = await flow.run(input_data="こんにちは")  # → simple_agent
result = await flow.run(input_data="人工知能の倫理的問題について詳しく教えて")  # → complex_agent

パターン4: 並列処理Flow(3.9倍高速化)

from refinire import Flow, FunctionStep
import asyncio

def preprocess_text(user_input: str, ctx: Context) -> Context:
    """テキストの前処理"""
    # English: Text preprocessing
    ctx.shared_state["processed_text"] = user_input.strip().lower()
    return ctx

def sentiment_analysis(user_input: str, ctx: Context) -> Context:
    """感情分析"""
    # English: Sentiment analysis
    # 実際の分析処理をシミュレート
    import time
    time.sleep(0.5)  # 0.5秒の処理時間をシミュレート
    ctx.shared_state["sentiment"] = "positive"
    return ctx

def keyword_extraction(user_input: str, ctx: Context) -> Context:
    """キーワード抽出"""
    # English: Keyword extraction
    import time
    time.sleep(0.5)  # 0.5秒の処理時間をシミュレート
    text = ctx.shared_state["processed_text"]
    ctx.shared_state["keywords"] = text.split()[:5]
    return ctx

def topic_classification(user_input: str, ctx: Context) -> Context:
    """トピック分類"""
    # English: Topic classification
    import time
    time.sleep(0.5)  # 0.5秒の処理時間をシミュレート
    ctx.shared_state["topic"] = "technology"
    return ctx

def readability_check(user_input: str, ctx: Context) -> Context:
    """可読性チェック"""
    # English: Readability check
    import time
    time.sleep(0.5)  # 0.5秒の処理時間をシミュレート
    ctx.shared_state["readability_score"] = 85
    return ctx

def aggregate_results(user_input: str, ctx: Context) -> Context:
    """結果を統合"""
    # English: Aggregate results
    sentiment = ctx.shared_state.get("sentiment", "unknown")
    keywords = ctx.shared_state.get("keywords", [])
    topic = ctx.shared_state.get("topic", "unknown")
    readability = ctx.shared_state.get("readability_score", 0)

    summary = {
        "sentiment": sentiment,
        "keywords": keywords,
        "topic": topic,
        "readability": readability
    }
    ctx.shared_state["analysis_summary"] = summary
    ctx.finish()
    return ctx

# 並列処理Flow
flow = Flow({
    "preprocess": FunctionStep("preprocess", preprocess_text),
    "parallel_analysis": {
        "parallel": [
            FunctionStep("sentiment", sentiment_analysis),
            FunctionStep("keywords", keyword_extraction),
            FunctionStep("topic", topic_classification),
            FunctionStep("readability", readability_check)
        ],
        "next_step": "aggregate",
        "max_workers": 4  # 最大4つの並列実行
    },
    "aggregate": FunctionStep("aggregate", aggregate_results)
})

# パフォーマンス比較
import time

# 順次実行: 約2.0秒(0.5 × 4)
start_time = time.time()
result_sequential = await flow.run(input_data="This is a comprehensive analysis test.")
sequential_time = time.time() - start_time

# 並列実行: 約0.5秒(3.9倍高速化)
start_time = time.time()
result_parallel = await flow.run(input_data="This is a comprehensive analysis test.")
parallel_time = time.time() - start_time

print(f"順次実行: {sequential_time:.2f}秒")
print(f"並列実行: {parallel_time:.2f}秒")
print(f"速度向上: {sequential_time/parallel_time:.1f}倍")

パターン5: 複合Flow(エージェント+関数+条件分岐)

from refinire import Flow, FunctionStep, ConditionStep, create_evaluated_gen_agent

# 入力分析
def analyze_request(user_input: str, ctx: Context) -> Context:
    """リクエストの種類を分析"""
    # English: Analyze request type
    if "コード" in user_input or "プログラム" in user_input:
        ctx.shared_state["request_type"] = "coding"
    elif "説明" in user_input or "教えて" in user_input:
        ctx.shared_state["request_type"] = "explanation"
    else:
        ctx.shared_state["request_type"] = "general"
    return ctx

# ルーティング関数
def route_request(ctx: Context) -> str:
    """リクエストタイプに基づくルーティング"""
    # English: Route based on request type
    return ctx.shared_state["request_type"]

# 専門エージェント(評価機能付き)
coding_agent = create_evaluated_gen_agent(
    name="coding_expert",
    generation_instructions="""
    あなたはプログラミングの専門家です。
    実行可能で品質の高いコードを生成し、詳細な説明を付けてください。
    """,
    evaluation_instructions="""
    生成されたコードを以下の観点で評価してください:
    - 正確性(40点)
    - 可読性(30点)
    - 効率性(30点)
    """,
    threshold=80.0,
    model="gpt-4o-mini"
)

explanation_agent = create_evaluated_gen_agent(
    name="explanation_expert",
    generation_instructions="""
    あなたは教育の専門家です。
    分かりやすく段階的に説明し、具体例を含めてください。
    """,
    evaluation_instructions="""
    説明の品質を以下の観点で評価してください:
    - 分かりやすさ(50点)
    - 正確性(30点)
    - 完全性(20点)
    """,
    threshold=75.0,
    model="gpt-4o-mini"
)

general_agent = create_simple_gen_agent(
    name="general_assistant",
    instructions="親切で丁寧な一般的なアシスタントとして回答してください。",
    model="gpt-4o-mini"
)

# 後処理
def format_response(user_input: str, ctx: Context) -> Context:
    """レスポンスをフォーマット"""
    # English: Format response
    request_type = ctx.shared_state["request_type"]

    if request_type == "coding":
        result = ctx.shared_state.get("coding_expert_result", "")
        evaluation = ctx.shared_state.get("coding_expert_evaluation", {})
    elif request_type == "explanation":
        result = ctx.shared_state.get("explanation_expert_result", "")
        evaluation = ctx.shared_state.get("explanation_expert_evaluation", {})
    else:
        result = ctx.shared_state.get("general_assistant_result", "")
        evaluation = None

    formatted = f"""
=== {request_type.upper()} レスポンス ===
{result}

{f"品質スコア: {evaluation.get('score', 'N/A')}" if evaluation else ""}
=== 終了 ===
    """.strip()

    ctx.shared_state["final_response"] = formatted
    ctx.finish()
    return ctx

# 複合Flow
flow = Flow({
    "analyze": FunctionStep("analyze", analyze_request),
    "router": ConditionStep("router", route_request, "coding", "explanation", "general"),
    "coding": coding_agent,
    "explanation": explanation_agent,
    "general": general_agent,
    "format": FunctionStep("format", format_response)
})

# 実行例
examples = [
    "Pythonでフィボナッチ数列を生成するコードを書いて",
    "機械学習とは何か詳しく説明して",
    "今日の天気はどうですか?"
]

for example in examples:
    result = await flow.run(input_data=example)
    print(f"入力: {example}")
    print(result.shared_state["final_response"])
    print("-" * 50)

状態管理とコンテキスト

Context クラスの活用

from refinire import Context

def step_with_state(user_input: str, ctx: Context) -> Context:
    """ステップ間でのデータ共有例"""
    # English: Example of data sharing between steps

    # 前のステップの結果を取得
    previous_data = ctx.shared_state.get("previous_result", None)

    # 現在のステップで処理
    current_result = process_data(user_input, previous_data)

    # 次のステップに結果を渡す
    ctx.shared_state["current_result"] = current_result

    # ユーザー入力も保持
    ctx.shared_state["original_input"] = ctx.user_input

    # メタデータの追加
    ctx.shared_state["processing_time"] = time.time()

    return ctx

エラーハンドリング

def safe_processing_step(user_input: str, ctx: Context) -> Context:
    """エラーハンドリングを含むステップ"""
    # English: Step with error handling
    try:
        result = risky_operation(user_input)
        ctx.shared_state["result"] = result
        ctx.shared_state["status"] = "success"
    except Exception as e:
        ctx.shared_state["error"] = str(e)
        ctx.shared_state["status"] = "error"
        # エラーが発生してもフローを継続

    return ctx

def error_recovery_step(user_input: str, ctx: Context) -> Context:
    """エラー回復処理"""
    # English: Error recovery processing
    if ctx.shared_state.get("status") == "error":
        # フォールバック処理
        ctx.shared_state["result"] = "デフォルトの回答を使用します"
        ctx.shared_state["status"] = "recovered"

    return ctx

パフォーマンス最適化

並列処理による高速化

並列処理を使うことで、独立したタスクを同時実行し、大幅な性能向上を実現できます。

# 順次実行(従来): 4つのタスク × 0.5秒 = 2.0秒
# 並列実行(Refinire): max(0.5秒) = 0.5秒(3.9倍高速化)

flow = Flow({
    "preprocess": FunctionStep("prep", preprocess_data),
    "parallel_tasks": {
        "parallel": [
            FunctionStep("task1", time_consuming_task1),  # 0.5秒
            FunctionStep("task2", time_consuming_task2),  # 0.5秒  
            FunctionStep("task3", time_consuming_task3),  # 0.5秒
            FunctionStep("task4", time_consuming_task4),  # 0.5秒
        ],
        "max_workers": 4,
        "next_step": "aggregate"
    },
    "aggregate": FunctionStep("agg", combine_results)
})

メモリ効率的な処理

def memory_efficient_step(user_input: str, ctx: Context) -> Context:
    """メモリ効率を考慮したステップ"""
    # English: Memory-efficient step

    # 大きなデータは適切に管理
    large_data = process_large_dataset(user_input)

    # 必要な部分のみ保持
    ctx.shared_state["summary"] = summarize(large_data)

    # 大きなデータはクリーンアップ
    del large_data

    return ctx

ベストプラクティス

1. ステップの単一責務原則

各ステップは一つの明確な責務を持つべきです。

# 良い例:責務が明確
def validate_input(user_input: str, ctx: Context) -> Context:
    """入力検証のみを行う"""
    # English: Only perform input validation
    if not user_input.strip():
        raise ValueError("入力が空です")
    ctx.shared_state["validated"] = True
    return ctx

def process_data(user_input: str, ctx: Context) -> Context:
    """データ処理のみを行う"""
    # English: Only perform data processing
    processed = user_input.lower().strip()
    ctx.shared_state["processed_data"] = processed
    return ctx

# 悪い例:複数の責務を持つ
def validate_and_process(user_input: str, ctx: Context) -> Context:
    # 検証と処理を一つのステップで行う(推奨されない)
    if not user_input.strip():
        raise ValueError("入力が空です")
    processed = user_input.lower().strip()
    ctx.shared_state["result"] = processed
    return ctx

2. 明示的なフロー終了

フローの終了は明示的に示すべきです。

def final_step(user_input: str, ctx: Context) -> Context:
    """最終ステップでは明示的に終了"""
    # English: Explicitly end in final step
    ctx.shared_state["final_result"] = "処理完了"
    ctx.finish()  # 明示的な終了
    return ctx

3. 再利用可能なコンポーネント設計

# 再利用可能な検証ステップ
def create_validation_step(validation_func, error_message):
    """検証ステップのファクトリ関数"""
    # English: Factory function for validation steps
    def validate(user_input: str, ctx: Context) -> Context:
        if not validation_func(user_input):
            raise ValueError(error_message)
        ctx.shared_state["validated"] = True
        return ctx
    return FunctionStep("validate", validate)

# 使用例
email_validator = create_validation_step(
    lambda x: "@" in x, 
    "有効なメールアドレスを入力してください"
)

phone_validator = create_validation_step(
    lambda x: x.replace("-", "").isdigit(),
    "有効な電話番号を入力してください"
)

実世界での応用例

カスタマーサポートシステム

# 顧客問い合わせ処理フロー
customer_support_flow = Flow({
    "classify": FunctionStep("classify", classify_inquiry),
    "router": ConditionStep("route", route_by_category, 
                          "technical", "billing", "general"),
    "technical": technical_support_agent,
    "billing": billing_support_agent,
    "general": general_support_agent,
    "quality_check": quality_assurance_step,
    "escalate": ConditionStep("escalate", 
                            lambda ctx: "manager" if ctx.shared_state["quality_score"] < 80 else "complete",
                            "manager", "complete"),
    "manager": manager_review_agent,
    "complete": finalize_response
})

コンテンツ生成パイプライン

# ブログ記事生成フロー
content_generation_flow = Flow({
    "research": research_agent,
    "outline": outline_generator_agent,
    "parallel_writing": {
        "parallel": [
            FunctionStep("intro", write_introduction),
            FunctionStep("body", write_body),
            FunctionStep("conclusion", write_conclusion)
        ],
        "next_step": "assemble"
    },
    "assemble": FunctionStep("assemble", combine_sections),
    "review": editorial_review_agent,
    "publish": FunctionStep("publish", publish_content)
})

データ分析パイプライン

# データ分析フロー
data_analysis_flow = Flow({
    "validate": data_validation_step,
    "clean": data_cleaning_step,
    "parallel_analysis": {
        "parallel": [
            FunctionStep("stats", statistical_analysis),
            FunctionStep("trends", trend_analysis),
            FunctionStep("patterns", pattern_recognition),
            FunctionStep("anomalies", anomaly_detection)
        ],
        "max_workers": 4,
        "next_step": "correlate"
    },
    "correlate": correlation_analysis_step,
    "visualize": visualization_step,
    "report": report_generation_agent
})

まとめ

Refinireの組み合わせ可能なフローアーキテクチャは:

  1. シンプルさ: Flow(steps=agent) で始まり、必要に応じて複雑化
  2. 柔軟性: 条件分岐、並列処理、ループなど豊富な制御構造
  3. 再利用性: コンポーネントベースの設計で高い再利用性
  4. パフォーマンス: 並列処理で3.9倍の高速化を実現
  5. 保守性: 宣言的設定と明確な状態管理

従来の複雑なワークフロー構築から、直感的で保守可能な設計へのパラダイムシフトを提供します。