Generate Synthetic Reasoning Data Agents

Learn how to generate chain-of-thought reasoning data using PraisonAI Agents.

python
from praisonaiagents import Agent

coordinator = Agent(name="CoT Coordinator", instructions="Generate and evaluate reasoning datasets.")
coordinator.start("Generate chain-of-thought examples for maths word problems")

The user starts the workflow; agents generate, evaluate, and upload chain-of-thought training data.

Diagram

Reasoning Data Generation

đź“‹ Generate Q&A

🔍 Evaluate

đź§  CoT Steps

âś… Upload Dataset

What is Chain-of-Thought Generation?

Chain-of-Thought (CoT) Generation is a process where AI agents create detailed, step-by-step reasoning paths for solving problems. This involves generating questions, evaluating them, producing detailed solution steps, and making the data available for training and analysis.

How It Works

The user starts the workflow; the generator creates Q&A pairs, the CoT agent expands each into reasoning steps, and the uploader publishes the dataset.

Diagram
HuggingFaceCoTGeneratorGeneratorUserHuggingFaceCoTGeneratorGeneratorUserstart(“Generate reasoning data”)Create Q&A pairsQ&A pairsExpand into reasoning stepsUpload datasetDataset published

Quick Start

  1. Install Package

    First, install the PraisonAI Agents package:

    bash
    pip install "praisonaiagents[llm]" datasets huggingface-hub pandas
  2. Set API Key

    Set your OpenAI API key as an environment variable in your terminal:

    bash
    export OPENAI_API_KEY="${OPENAI_API_KEY:?Set OPENAI_API_KEY in your shell}"
    export HF_TOKEN=your_huggingface_token_here
  3. Create a file

    Create a new file app.py with the basic setup:

    python
    from praisonaiagents import Agent, Task, AgentTeam
    from praisonaiagents import cot_save, cot_upload_to_huggingface
    from pydantic import BaseModel
    import os
    
    # Define Pydantic model for structured output
    class DecisionModel(BaseModel):
        response: str
        decision: str
    
    def write_csv(file_path, data):
        """Write data to CSV file."""
        if not os.path.exists(file_path):
            with open(file_path, 'w') as file:
                file.write(data + '\n')
        else:
            with open(file_path, 'a') as file:
                file.write(data + '\n')
        return f"Data appended to {file_path}"
    
    def count_questions(file_path):
        """Count lines in file."""
        with open(file_path, 'r') as file:
            return sum(1 for _ in file)
    
    # Create specialized agents
    qa_generator = Agent(
        name="Generator",
        role="Question Creator",
        goal="Create challenging math and logic questions",
        backstory="Expert in educational content creation",
        llm="gpt-4o-mini",
        tools=[write_csv, count_questions]
    )
    
    total_questions_evaluator = Agent(
        name="TotalQuestionsEvaluator",
        role="Total Questions Evaluator",
        goal="Evaluate the total number of questions in qa_pairs.csv file",
        backstory="Expert in evaluating the total number of questions in a file",
        llm="gpt-4o-mini",
        tools=[count_questions],
        output="silent"
    )
    
    cot_generator = Agent(
        name="COTGenerator",
        role="Chain of Thought Specialist",
        goal="Generate and manage chain of thought solutions for Q&A pairs",
        backstory="Expert in breaking down problems and generating detailed solution steps",
        tools=[cot_save],
        llm="gpt-4o-mini",
        output="silent"
    )
    
    upload_to_huggingface = Agent(
        name="UploadToHuggingface",
        role="Upload to Huggingface",
        goal="Upload the generated chain of thought solutions to a Huggingface dataset",
        backstory="Expert in saving data to Huggingface",
        tools=[cot_upload_to_huggingface],
        llm="gpt-4o-mini",
        output="silent"
    )
    
    # Create workflow with repeat pattern for generation
    from praisonaiagents import AgentFlow, Task, WorkflowContext, StepResult
    from praisonaiagents import repeat, loop
    
    # Step handlers using agents
    def generate_qa(ctx: WorkflowContext) -> StepResult:
        result = qa_generator.chat("""Generate question and answer in csv format: question, answer
        Generate 10 unique questions and answers. Example:
        What is the sum of numbers from 1 to 10?, 55
        Number of r's in the word strawberry, 3""")
        write_csv("qa_pairs.csv", result)
        return StepResult(output=result)
    
    def evaluate_count(ctx: WorkflowContext) -> StepResult:
        count = count_questions("qa_pairs.csv")
        return StepResult(
            output=f"count: {count}",
            variables={"question_count": count}
        )
    
    def generate_cot(ctx: WorkflowContext) -> StepResult:
        result = cot_generator.chat(f"Generate chain of thought for: {ctx.variables.get('current_item')}")
        cot_save(result)
        return StepResult(output=result)
    
    def upload_dataset(ctx: WorkflowContext) -> StepResult:
        result = upload_to_huggingface.chat("Upload cot_solutions.csv to mervinpraison/cot-dataset")
        return StepResult(output=result)
    
    # Create workflow
    workflow = AgentFlow(
        steps=[
            generate_qa,
            evaluate_count,
            loop(generate_cot, over="qa_pairs", from_csv="qa_pairs.csv"),
            upload_dataset
        ]
    )
    
    result = workflow.start("Generate reasoning data")
  4. Run the application

    Execute the Python script to start generating chain-of-thought data:

    bash
    python app.py

Features

Understanding the Workflow

Key Components
Task Types and Flow Control

Decision Tasks

Used in question generation and evaluation phases.

Decision Task Example
generate_task = Task(
    task_type="decision",
    condition={
        "more": "generate_task",
        "done": "evaluate_total_questions"
    }
)

Loop Tasks

Used in Chain-of-Thought generation phase.

Loop Task Example
generate_cot_task = Task(
    task_type="loop",
    input_file="qa_pairs.csv",
    output_pydantic=DecisionModel
)

Next Steps

Best Practices

Validate every generated step with Pydantic

Loop tasks that produce chain-of-thought data should always set output_pydantic to a model like DecisionModel. Structured validation rejects malformed reasoning before it reaches your dataset, keeping training data consistent and machine-parseable.

Evaluate before you accept

Route generated question–answer pairs through an evaluator agent ahead of the CoT generator. A cheap evaluation pass filters low-quality or ambiguous items early, so expensive reasoning generation runs only on data worth keeping.

Use decision tasks to control the loop

Decision tasks branch the workflow (continue generating vs. move on) based on the model’s response. Define clear stop conditions so the CoT generator loops enough times to build depth without running away — pair this with a target count check on your CSV.

Keep credentials in the environment

Set OPENAI_API_KEY and HF_TOKEN as environment variables rather than in code, so datasets can be regenerated and uploaded from CI without editing the script.

Related