AI Stepper
A lightweight, flexible Python framework for creating step-by-step AI workflows with full LLM prompt control.
Overview
AI Stepper is a basic sequential AI agent system designed for developers who need:
- Full control over LLM prompts and interactions
- Step-by-step workflow execution
- Strong output validation
- Simple retry mechanisms
- Clear and predictable agent behavior
If you're looking for a straightforward way to create sequential AI workflows without the complexity of full-scale agent frameworks, AI Stepper is the right choice.
Key Features
- LLM Agnostic: Works with any LLM through litellm annotations (OpenAI, Anthropic, local models, etc.)
- Wide Compatibility: Compatible with LLMs that don't support function calling.
- Full Prompt Control: Define exactly how your LLM should behave at each step
- Sequential Execution: Each step's output is automatically available as input for subsequent steps
- YAML-Driven Workflows: Define your entire workflow in a simple YAML file
- Schema Compatibility: Supports both JSON Schema and YAML annotations for input/output validation
- Strong Validation: Validate LLM outputs against predefined schemas
- Rich Logging: Built-in Markdown-formatted logging with step context
- Flexible Callbacks: Custom callback system for monitoring and debugging
Installation
pip install -U ai-stepper
Usage
1. Environment Setup
Create a .env file with your LLM configuration:
OPENAI_API_BASE=your_llm_api_base
OPENAI_API_KEY=your_llm_api_key
OPENAI_MODEL_NAME=your_model_name
2. Create a Workflow
Define your workflow steps in a YAML file (e.g., chain_of_thoughts.yaml):
direct_answer:
task: >
{query}
inputs:
query:
type: string
outputs:
final_answer:
type: string
define_problem:
task: >
Break down the problem statement {query} into its core components. Identify what needs to be solved or answered and
list these subproblems explicitly.
inputs:
query:
type: string
outputs:
subproblems:
type: array
items:
type: string
generate_subsolutions:
task: >
Solve each subproblem {subproblems} step by step. For each subproblem, provide a concise solution or analysis.
If the subproblem cannot be solved directly, explain why.
inputs:
subproblems:
type: array
items:
type: string
outputs:
subsolutions:
type: array
items:
type: object
properties:
subproblem:
type: string
solution:
type: string
combine_results:
task: >
Combine the solutions to the subproblems {subsolutions} into a coherent final answer to the original query.
Ensure the reasoning flows logically, and the answer directly addresses the query.
inputs:
subsolutions:
type: array
items:
type: object
properties:
subproblem:
type: string
solution:
type: string
outputs:
final_answer:
type: string
3. Implement the Runner
Create a Python script to run your workflow:
from ai_stepper import AI_Stepper
import os
from dotenv import load_dotenv
from rich import print
from typing import Optional
from datetime import datetime
# Load environment variables
load_dotenv(override=True)
def agent_logger(message: str, step_name: Optional[str] = None):
"""Log agent actions and responses."""
if step_name:
print(f"\n### {step_name.upper()}\n{message}\n")
else:
print(f"\n{message}\n")
def run_workflow(stepper: AI_Stepper, name: str, yaml_file: str, inputs: dict) -> None:
"""Run a single workflow and handle any errors."""
try:
print(f"\n[bold blue]Running {name} workflow...[/bold blue]")
result = stepper.run(
steps_file=yaml_file,
initial_inputs=inputs,
callback=agent_logger
)
print(f"[green]Result:[/green]", result)
except Exception as e:
print(f"[bold red]Error in {name} workflow:[/bold red] {str(e)}")
def main():
"""Main execution function."""
try:
# Initialize the AI_Stepper
stepper = AI_Stepper(
llm_base_url=os.getenv("OPENAI_API_BASE"),
llm_api_key=os.getenv("OPENAI_API_KEY"),
llm_model_name=os.getenv("OPENAI_MODEL_NAME")
)
# Define and run workflows
workflows = [
("Chain of Thoughts", "yaml/chain_of_thoughts.yaml", {
"query": "A farmer has 20 apples. He gives 5 apples to his neighbor and then splits the remaining apples equally among his 3 children. How many apples does each child get?"
}),
]
for name, yaml_file, inputs in workflows:
run_workflow(stepper, name, yaml_file, inputs)
except Exception as e:
print(f"[bold red]Critical error:[/bold red] {str(e)}")
if __name__ == "__main__":
main()
This example demonstrates a workflow that:
- Breaks down the question into subproblems
- Solves each subproblem step by step
- Combines the solutions into a final answer
The framework handles:
- Environment configuration
- YAML workflow loading
- Step execution
- Error handling
- Logging
- Output validation
For more examples, check the yaml/ directory in the repository.
Logging and Output
Markdown Logger
AI Stepper includes a built-in markdown logger utility that creates well-formatted logs of your workflow execution. The logger supports:
- Timestamped entries with timezone support
- Structured message formatting
- Code block formatting with syntax highlighting
- Token usage tracking
- JSON pretty-printing
- File output capabilities
Example usage:
from ai_stepper.utils.logger import markdown_logger
from ai_stepper.schema.callback import CallBack
# Create a callback
callback = CallBack(
sender="LLM",
step_name="analyze_sentiment",
object="output",
message="Response for sentiment analysis",
created=int(datetime.utcnow().timestamp()),
code=CodeItem(
language="json",
content={"sentiment_analysis": {"product_sentiments": [...]}}
)
)
# Log to file
markdown_logger(callback, "log.md")
Schema Validation
AI Stepper enforces strict schema validation for LLM outputs. Each step's output must conform to the schema defined in your YAML workflow:
analyze_sentiment:
task: >
Perform sentiment analysis on the feedback {feedback}.
Determine whether each theme has a positive, negative, or neutral sentiment.
inputs:
feedback:
type: array
outputs:
sentiment_analysis:
type: object
properties:
product_sentiments:
type: array
items:
type: object
properties:
product:
type: string
theme_sentiments:
type: array
items:
type: object
properties:
theme:
type: string
sentiment:
type: string
The framework will:
- Validate all outputs against their schemas
- Provide clear error messages for validation failures
- Support retry mechanisms for failed validations
- Log validation results in markdown format
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for ai-stepper 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ai_stepper-0.1.4.tar.gz | 20.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ai_stepper-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.2 kB
Release files / ai_stepper-0.1.4.tar.gz
| Download URL | ai_stepper-0.1.4.tar.gz |
|---|---|
| Size | 20.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00218d830c05589b9409d8f2de45c8fa3ac288e1eea16124c201344cd67060e1
|
|
BLAKE2b-256 checksum How to use checksums |
5aaedd179ab1fab69a24a0c2d957f104ae38f91c4043d7b43dec9d6cdf72f4c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.8
|
Release files / ai_stepper-0.1.4-py3-none-any.whl
| Download URL | ai_stepper-0.1.4-py3-none-any.whl |
|---|---|
| Size | 17.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dfba8789d2cc5f5549743a0fd97e60578af34b500175de4cb691bb57ec583d4b
|
|
BLAKE2b-256 checksum How to use checksums |
4d2215f4b38bb2a296209d2315483dfb06e1b989f7171b48a0d58c5118c49ced
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.8
|