Practical Lab Assignments

MEDIUM6 min readby AdminJune 20, 2026History
0.0|0 ratingsLog in to rate

20 hands-on programming challenges designed to test Python, FastAPI, and LLM orchestration skills.

#ai-engineering#course#assignments

Introduction

Welcome to the practical lab assignments. These 20 hands-on challenges are designed to reinforce Python, REST APIs, FastAPI, and LLM system engineering skills. Complete each task inside a dedicated python file.


Module 1: Introduction to AI Engineering

Assignment 1: Dynamic Heuristic Router

  • Goal: Write a routing function that scans user input tickets and assigns them to categories. If a ticket contains keywords related to Billing, route it to "BILLING". If Technical, route to "TECHNICAL". Otherwise, route to "GENERAL".
  • Template:
python
1
2
3
4
5
6
def route_ticket(text: str) -> str:
    # Your code here
    pass

# Test
print(route_ticket("Can you refund my last charge?")) # Expected: BILLING
  • Hint: Convert the input text to lowercase and check for keywords like "refund", "charge", "card" vs "slow", "error", "server".

Assignment 2: Provider Fallback Client

  • Goal: Implement a class that attempts to generate text using a primary model provider name. If the primary provider raises a connection failure, catch the exception and fall back to a secondary backup provider.
  • Template:
python
1
2
3
4
5
6
7
8
class ModelClient:
    def __init__(self, primary: str, backup: str):
        self.primary = primary
        self.backup = backup

    def generate(self, text: str) -> str:
        # Your code here
        pass
  • Hint: Use a try-except block inside the generate function to catch simulated connection exceptions.

Assignment 3: Cost and Latency Calculator

  • Goal: Write a script that accepts input token count and output token count. Calculate the total cost for two models and return a comparative dictionary showing which model is more cost-effective.
    • Model A: $0.075 per 1M input tokens, $0.30 per 1M output tokens.
    • Model B: $2.50 per 1M input tokens, $10.00 per 1M output tokens.
  • Template:
python
1
2
3
def compare_models(input_tokens: int, output_tokens: int) -> dict:
    # Your code here
    pass

Assignment 4: API Request Scheduler with Rate Limits

  • Goal: Simulate an API call queue. Given a list of 5 request payloads, process them one by one. If a rate limit event is detected (simulated by checking if the request index is divisible by 3), sleep for 1 second before retrying.
  • Template:
python
1
2
3
def process_queue(requests: list):
    # Your code here
    pass

Assignment 5: Chat Thread Logger

  • Goal: Create a script that acts as an audit logger. It must format a user message and assistant response into a single log string, append a timestamp, and write the output line to a local text file chat_audit.log.
  • Template:
python
1
2
3
def log_chat(user_msg: str, bot_msg: str):
    # Your code here
    pass

Module 2: Python for AI Engineers

Assignment 6: Deduplicating Context List Comprehension

  • Goal: Write a list comprehension that takes a list of document strings, filters out duplicates, removes any documents shorter than 10 characters, and returns the cleaned list.
  • Template:
python
1
2
3
def clean_context_docs(docs: list) -> list:
    # Your code here
    pass
  • Hint: Utilize a set to track unique entries during filtering.

Assignment 7: Dynamic User Profile Zip

  • Goal: Given two lists (one of user IDs, one of raw names), zip them together and create a dictionary lookup mapping ID to name, but filter out any users whose names contain numbers.
  • Template:
python
1
2
3
def map_users(ids: list, names: list) -> dict:
    # Your code here
    pass

Assignment 8: Retry Decorator with Backoff

  • Goal: Write a custom decorator retry_with_backoff that retries a function up to a configured number of times, doubling the delay between each attempt on failure.
  • Template:
python
1
2
3
def retry_with_backoff(retries: int = 3, initial_delay: float = 0.5):
    # Your code here
    pass

Assignment 9: Abstract Vector Store Contract

  • Goal: Create an Abstract Base Class BaseVectorStore defining abstract methods add_vector(id: str, vec: list) and query_vector(vec: list) -> list. Create a subclass MemoryVectorStore that implements these using a local dictionary.
  • Template:
python
1
2
3
4
5
from abc import ABC, abstractmethod

class BaseVectorStore(ABC):
    # Define contract here
    pass

Assignment 10: Dataclass Validation with Post-Init

  • Goal: Define a dataclass PromptConfig that stores parameters max_tokens (int), temperature (float), and stop_sequences (list). Inside __post_init__, validate that temperature is between 0.0 and 1.0 inclusive, throwing an error if it is not.
  • Template:
python
1
2
3
4
5
6
7
from dataclasses import dataclass

@dataclass
class PromptConfig:
    max_tokens: int
    temperature: float
    stop_sequences: list

Assignment 11: Concurrent LLM Evaluator (Async)

  • Goal: Write an asynchronous function that uses asyncio.gather to send a prompt to three different simulated model APIs concurrently. Print the responses and verify the total execution time matches the slowest call latency.
  • Template:
python
1
2
3
4
5
import asyncio

async def fetch_model_response(model_name: str, latency: float) -> str:
    # Your code here
    pass

Assignment 12: Custom JSON Parser for LLM Tool Arguments

  • Goal: Write a function that accepts a raw JSON string from an LLM tool call. Parse the string into a dictionary. If it fails due to parsing issues, return a fallback dict containing an error parameter.
  • Template:
python
1
2
3
def parse_tool_args(raw_json: str) -> dict:
    # Your code here
    pass

Module 3: APIs and Backend Fundamentals

Assignment 13: REST URI Builder

  • Goal: Implement a function that constructs clean RESTful URI paths dynamically given resource types, parent resource IDs, and sub-resource identifiers.
  • Template:
python
1
2
3
def build_rest_uri(resource: str, parent_id: str, sub_resource: str = None) -> str:
    # Your code here
    pass

Assignment 14: HTTP Status Action Router

  • Goal: Write a function that takes an HTTP status code integer and returns a string indicating the system action: "RETRY" for 429, "AUTHENTICATE" for 401, "FAILOVER" for 5xx, and "OK" for 2xx.
  • Template:
python
1
2
3
def route_http_status(status_code: int) -> str:
    # Your code here
    pass

Assignment 15: Mock JWT Signature Validator

  • Goal: Create a script that parses a simulated JWT token string (split by dots). Verify that the signature block matches the expected hash generated using a secret key, returning a boolean confirmation.
  • Template:
python
1
2
3
def verify_jwt_signature(token: str, secret: str) -> bool:
    # Your code here
    pass

Assignment 16: FastAPI Basic Chat Server

  • Goal: Build a simple FastAPI app that has a single POST endpoint /chat. It must accept a JSON payload containing a message string and return a JSON response containing a mock model output.
  • Template:
python
1
2
3
from fastapi import FastAPI
app = FastAPI()
# Define route here

Assignment 17: FastAPI Header Verification Middleware

  • Goal: Write a FastAPI route dependency that checks if the request headers contain a key X-API-Key with the value valid-key. If the key is missing or incorrect, raise an HTTP 401 exception.
  • Template:
python
1
2
from fastapi import Header, HTTPException
# Define dependency verify_key here

Module 4: LLM Fundamentals

Assignment 18: Character Token Estimator

  • Goal: Write a utility function that counts the characters in a string and returns the estimated token count (using the 4 characters per token rule). If the word contains non-English letters, multiply the estimate by 1.5.
  • Template:
python
1
2
3
def estimate_tokens(text: str) -> int:
    # Your code here
    pass

Assignment 19: Sliding History Buffer

  • Goal: Create a conversation manager class that tracks messages in a list. When the estimated total token count of the history exceeds 50 tokens, discard the oldest messages until the total token count is within the limit.
  • Template:
python
1
2
3
4
class ChatBuffer:
    def __init__(self, limit: int = 50):
        self.limit = limit
        self.messages = []

Assignment 20: Pydantic Structured Output Validation

  • Goal: Define a Pydantic model TaskOutput that validates fields task_name (str), success (bool), and execution_seconds (float). Write a parser function that reads a raw JSON string and returns the validated model, or logs the validation errors if it fails.
  • Template:
python
1
2
from pydantic import BaseModel
# Define and implement here

Discussion

Join the discussion! Sign in to leave comments and ask questions.

Loading discussion...