Back to Blog
3 min read

Building a Personal AI Assistant with Semantic Kernel

Holiday season is perfect for personal projects. Let’s build a capable personal AI assistant using Semantic Kernel that can manage tasks, answer questions, and integrate with your tools.

Architecture Overview

User Input -> Semantic Kernel -> Plugin Selection -> Tool Execution -> Response
                   |
            Memory Store (conversation history)
                   |
            Planner (multi-step tasks)

Project Setup

pip install semantic-kernel openai python-dotenv

Core Assistant Implementation

import os
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.contents import ChatHistory
from semantic_kernel.functions import kernel_function

# Initialize kernel
kernel = Kernel()
kernel.add_service(AzureChatCompletion(
    deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT"),
    endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
    api_key=os.getenv("AZURE_OPENAI_KEY")
))

# Chat history for context
chat_history = ChatHistory()
chat_history.add_system_message("""You are a helpful personal assistant. You can:
- Manage tasks and reminders
- Answer questions
- Help with calculations
- Search your knowledge base
Be concise but friendly.""")

Creating Plugins

class TaskPlugin:
    def __init__(self):
        self.tasks = []

    @kernel_function(description="Add a new task to the list")
    def add_task(self, task: str, priority: str = "medium") -> str:
        self.tasks.append({"task": task, "priority": priority, "done": False})
        return f"Added task: {task} (priority: {priority})"

    @kernel_function(description="List all pending tasks")
    def list_tasks(self) -> str:
        pending = [t for t in self.tasks if not t["done"]]
        if not pending:
            return "No pending tasks!"

        result = "Your tasks:\n"
        for i, t in enumerate(pending, 1):
            result += f"{i}. [{t['priority']}] {t['task']}\n"
        return result

    @kernel_function(description="Mark a task as complete")
    def complete_task(self, task_number: int) -> str:
        pending = [t for t in self.tasks if not t["done"]]
        if 0 < task_number <= len(pending):
            pending[task_number - 1]["done"] = True
            return f"Completed: {pending[task_number - 1]['task']}"
        return "Task not found"

class CalculatorPlugin:
    @kernel_function(description="Perform a calculation")
    def calculate(self, expression: str) -> str:
        try:
            # Safe evaluation of math expressions
            allowed = set("0123456789+-*/.() ")
            if all(c in allowed for c in expression):
                result = eval(expression)
                return f"{expression} = {result}"
            return "Invalid expression"
        except Exception as e:
            return f"Error: {str(e)}"

# Register plugins
kernel.add_plugin(TaskPlugin(), "tasks")
kernel.add_plugin(CalculatorPlugin(), "calculator")

Interactive Chat Loop

from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import OpenAIChatPromptExecutionSettings

async def chat():
    settings = OpenAIChatPromptExecutionSettings(
        function_choice_behavior=FunctionChoiceBehavior.Auto()
    )

    print("Personal Assistant Ready! Type 'quit' to exit.\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() == 'quit':
            break

        chat_history.add_user_message(user_input)

        response = await kernel.invoke_prompt(
            prompt="{{$chat_history}}",
            arguments={"chat_history": chat_history},
            settings=settings
        )

        assistant_message = str(response)
        chat_history.add_assistant_message(assistant_message)
        print(f"Assistant: {assistant_message}\n")

# Run
import asyncio
asyncio.run(chat())

Example Conversation

You: Add a task to buy groceries with high priority
Assistant: Added task: buy groceries (priority: high)

You: What's on my list?
Assistant: Your tasks:
1. [high] buy groceries

You: What's 15% tip on $85.50?
Assistant: 85.50 * 0.15 = 12.825
A 15% tip on $85.50 would be $12.83

This foundation can be extended with calendar integration, email access, and more plugins. Perfect for a holiday coding project!

Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.