Sitemap

Building a Local AI Task Planner with ClientAI and Ollama

4 min readDec 17, 2024

--

ClientAI

In this tutorial, we’ll build an AI-powered task planner using ClientAI and Ollama. Our planner will break down goals into actionable tasks, create realistic timelines, and manage resources — all of this running in your own machine.

Our task planner will be capable of:

  • Breaking down goals into specific, actionable tasks
  • Creating realistic timelines with error handling
  • Managing and allocating resources effectively
  • Providing structured, formatted plans

For ClientAI’s docs see here and for Github Repo, here.

Setting Up Our Environment

First, create a new directory for your project:

mkdir local_task_planner
cd local_task_planner

Install ClientAI with Ollama support:

pip install clientai[ollama]

Make sure you have Ollama installed on your system. You can get it from Ollama’s website.

Create our main Python file:

touch task_planner.py

Let’s start with our core imports:

from datetime import datetime, timedelta
from typing import Dict, List
import logging

from clientai import ClientAI
from clientai.agent import create_agent, tool
from clientai.ollama import OllamaManager

logger = logging.getLogger(__name__)Each component plays a crucial role:
  • datetime: Helps us manage task timelines and scheduling
  • ClientAI: Provides our AI framework
  • OllamaManager: Manages our local AI model
  • Various utility modules for type hints and logging

Building the Task Planner Core

First, let’s create our TaskPlanner class that will manage the AI interaction:

class TaskPlanner:
"""A local task planning system using Ollama."""

def __init__(self):
"""Initialize the task planner with Ollama."""
self.manager = OllamaManager()
self.client = None
self.planner = None

def start(self):
"""Start the Ollama server and initialize the client."""
self.manager.start()
self.client = ClientAI("ollama", host="http://localhost:11434")

self.planner = create_agent(
client=self.client,
role="task planner",
system_prompt="""You are a practical task planner. Break down goals into
specific, actionable tasks with realistic time estimates and resource needs.
Use the tools provided to validate timelines and format plans properly.""",
model="llama3",
step="think",
tools=[validate_timeline, format_plan],
tool_confidence=0.8,
stream=True,
)

This class serves as our foundation. It manages the Ollama server lifecycle, creates and configures our AI client and sets up our planning agent with specific capabilities.

Creating Our Planning Tools

Now let’s build the tools our AI will use. First, the timeline validator:

@tool(name="validate_timeline")
def validate_timeline(tasks: Dict[str, int]) -> Dict[str, dict]:
"""
Validate time estimates and create a realistic timeline.

Args:
tasks: Dictionary of task names and estimated hours

Returns:
Dictionary with start dates and deadlines
"""
try:
current_date = datetime.now()
timeline = {}
accumulated_hours = 0

for task, hours in tasks.items():
try:
hours_int = int(float(str(hours)))

if hours_int <= 0:
logger.warning(f"Skipping task {task}: Invalid hours value {hours}")
continue

days_needed = hours_int / 6
start_date = current_date + timedelta(hours=accumulated_hours)
end_date = start_date + timedelta(days=days_needed)

timeline[task] = {
"start": start_date.strftime("%Y-%m-%d"),
"end": end_date.strftime("%Y-%m-%d"),
"hours": hours_int,
}

accumulated_hours += hours_int

except (ValueError, TypeError) as e:
logger.warning(f"Skipping task {task}: Invalid hours value {hours} - {e}")
continue

return timeline
except Exception as e:
logger.error(f"Error validating timeline: {str(e)}")
return {}

This validator converts time estimates to working days, handles invalid inputs gracefully, creates realistic sequential scheduling and provides detailed logging for debugging.

Next, let’s create our plan formatter:

@tool(name="format_plan")
def format_plan(
tasks: List[str],
timeline: Dict[str, dict],
resources: List[str]
) -> str:
"""
Format the plan in a clear, structured way.

Args:
tasks: List of tasks
timeline: Timeline from validate_timeline
resources: List of required resources

Returns:
Formatted plan as a string
"""
try:
plan = "== Project Plan ==\n\n"

plan += "Tasks and Timeline:\n"
for i, task in enumerate(tasks, 1):
if task in timeline:
t = timeline[task]
plan += f"\n{i}. {task}\n"
plan += f" Start: {t['start']}\n"
plan += f" End: {t['end']}\n"
plan += f" Estimated Hours: {t['hours']}\n"

plan += "\nRequired Resources:\n"
for resource in resources:
plan += f"- {resource}\n"

return plan
except Exception as e:
logger.error(f"Error formatting plan: {str(e)}")
return "Error: Unable to format plan"

Here we want to create a consistent, readable output with proper task numbering and organized timeline.

Building the Interface

Let’s create a user-friendly interface for our planner:

def get_plan(self, goal: str) -> str:
"""
Generate a plan for the given goal.

Args:
goal: The goal to plan for

Returns:
A formatted plan string
"""
if not self.planner:
raise RuntimeError("Planner not initialized. Call start() first.")

return self.planner.run(goal)

def main():
planner = TaskPlanner()

try:
print("Task Planner (Local AI)")
print("Enter your goal, and I'll create a practical, timeline-based plan.")
print("Type 'quit' to exit.")

planner.start()

while True:
print("\n" + "=" * 50 + "\n")
goal = input("Enter your goal: ")

if goal.lower() == "quit":
break

try:
plan = planner.get_plan(goal)
print("\nYour Plan:\n")
for chunk in plan:
print(chunk, end="", flush=True)
except Exception as e:
print(f"Error: {str(e)}")

finally:
planner.stop()

if __name__ == "__main__":
main()

Our interface provides:

  • Clear user instructions
  • Real-time plan generation with streaming
  • Proper error handling
  • Clean shutdown management

Example Usage

Here’s what you’ll see when you run the planner:

Task Planner (Local AI)
Enter your goal, and I'll create a practical, timeline-based plan.
Type 'quit' to exit.

==================================================

Enter your goal: Create a personal portfolio website

Your Plan:

== Project Plan ==

Tasks and Timeline:
1. Requirements Analysis and Planning
Start: 2024-12-08
End: 2024-12-09
Estimated Hours: 6

2. Design and Wireframing
Start: 2024-12-09
End: 2024-12-11
Estimated Hours: 12

3. Content Creation
Start: 2024-12-11
End: 2024-12-12
Estimated Hours: 8

4. Development
Start: 2024-12-12
End: 2024-12-15
Estimated Hours: 20

Required Resources:
- Design software (e.g., Figma)
- Text editor or IDE
- Web hosting service
- Version control system

Future Improvements

Consider these enhancements for your own task planner:

  • Add dependency tracking between tasks
  • Include cost calculations for resources
  • Save plans to files or project management tools
  • Track progress against the original plan
  • Add validation for resource availability
  • Implement parallel task scheduling
  • Add support for recurring tasks
  • Include priority levels for tasks

To see more about ClientAI, go to the docs.

Connect With Me

If you have any questions about this tutorial or want to share your improvements to the task planner, feel free to reach out:

--

--

Igor Benav
Igor Benav

Written by Igor Benav

Working with Data, Failing Startups.

No responses yet