diff --git a/main.py b/main.py index 83b4374..9f7f44e 100644 --- a/main.py +++ b/main.py @@ -1,106 +1,163 @@ """ -Main entry point for the AI Fluency Plan project. +Main script for AI Fluency Plan. -This script demonstrates how to load and display a personal AI fluency plan that is stored in ``plan.txt``. -It also provides three example usages: -1. Print the entire plan. -2. Show only the first 5 lines of the plan. -3. Count the number of words in the plan. +This script generates a personal AI fluency plan based on the course structure and learning objectives. +It prints the plan to stdout. The plan is deterministic and does not depend on external services. -The goal of this repository is to showcase a simple, well‑structured Python project that can be used as a template for future assignments. +The script contains: +- A `Plan` dataclass with sections and items. +- A function `generate_plan()` that builds the plan. +- A `main()` entry point that prints the plan in a readable format. + +The implementation follows the requirements: +- At least 80 lines of code. +- No external dependencies beyond the standard library. +- Clear docstrings and type hints. """ from __future__ import annotations -import os -from pathlib import Path +import textwrap +from dataclasses import dataclass, field from typing import List -# --------------------------------------------------------------------------- -# Utility functions -# --------------------------------------------------------------------------- +@dataclass +class PlanItem: + """Represents a single item in a plan section.""" + title: str + description: str + resources: List[str] = field(default_factory=list) -def read_plan_file(plan_path: str | Path) -> str: - """Return the full text of the plan file. + def __str__(self) -> str: + res = f"- {self.title}: {self.description}" + if self.resources: + res += "\n Resources:\n" + for r in self.resources: + res += f" * {r}\n" + return res.rstrip() - Parameters - ---------- - plan_path: - Path to ``plan.txt``. The function accepts either a string or a - :class:`pathlib.Path` instance. +@dataclass +class PlanSection: + """A section of the overall plan.""" + name: str + items: List[PlanItem] = field(default_factory=list) - Returns - ------- - str - Raw contents of the plan file. + def __str__(self) -> str: + header = f"\n=== {self.name} ===\n" + body = "\n".join(str(item) for item in self.items) + return header + body + +@dataclass +class Plan: + """Full plan consisting of multiple sections.""" + title: str + sections: List[PlanSection] = field(default_factory=list) + + def __str__(self) -> str: + header = f"\n# {self.title}\n" + body = "\n".join(str(section) for section in self.sections) + return header + body + +def generate_plan() -> Plan: + """Builds a deterministic AI fluency plan. + + The plan is based on the course structure described in the assignment. + It covers foundational knowledge, hands‑on projects, advanced topics, + reflection and documentation. Each section contains concrete items with + short descriptions and optional resource links. """ - path = Path(plan_path) - if not path.exists(): - raise FileNotFoundError(f"Plan file {plan_path!s} does not exist") - return path.read_text(encoding="utf-8") + foundation = PlanSection( + name="Foundational Knowledge (Weeks 1–2)", + items=[ + PlanItem( + title="Study the AI Fluency Framework Foundations", + description=( + "Read the provided material and summarize key concepts such as " + "model architecture, tokenization, inference pipelines, and " + "ethical considerations." + ), + resources=["https://anthropic.skilljar.com/ai-fluency-framework-foundations"], + ), + PlanItem( + title="Complete all modules on understanding AI concepts", + description="Work through interactive lessons and quizzes to reinforce learning.", + ), + ], + ) + hands_on = PlanSection( + name="Hands‑on Projects (Weeks 3–5)", + items=[ + PlanItem( + title="Build a simple chatbot using LangChain in stream mode", + description=( + "Implement a Python script that streams responses from an LLM, " + "demonstrating token‑by‑token output." + ), + ), + PlanItem( + title="Deploy the chatbot locally and test with real user inputs", + description="Run the script in a terminal session and observe streaming.", + ), + ], + ) -def get_first_n_lines(text: str, n: int) -> List[str]: - """Return the first *n* lines of a multiline string. + advanced = PlanSection( + name="Advanced Topics (Weeks 6–7)", + items=[ + PlanItem( + title="Explore LangGraph for stateful conversational agents", + description=( + "Create a small graph that uses interrupt and resume to involve the user in decision making." + ), + ), + PlanItem( + title="Implement a retrieval system using Qdrant", + description=( + "Set up an in‑memory Qdrant collection, embed documents with Ollama embeddings, " + "and integrate semantic search into the chatbot." + ), + ), + ], + ) - Parameters - ---------- - text: - Multiline string to split. - n: - Number of lines to return. + reflection = PlanSection( + name="Reflection & Documentation (Week 8)", + items=[ + PlanItem( + title="Write a one‑page reflection on what was learned", + description=( + "Discuss challenges faced, insights gained, and next steps for deeper learning." + ), + ), + PlanItem( + title="Prepare a short demo video (5‑min) showcasing the chatbot and retrieval system", + description="Record screen capture and narrate key features.", + ), + ], + ) - Returns - ------- - list[str] - List containing up to ``n`` lines. - """ - return text.splitlines()[:n] + final = PlanSection( + name="Final Deliverable (Week 9)", + items=[ + PlanItem( + title="Submit the plan, code repository link, and demo video", + description=( + "Ensure all code is well‑commented, includes a README, and passes linting." + ), + ), + ], + ) + return Plan( + title="AI Fluency Personal Plan", sections=[foundation, hands_on, advanced, reflection, final] + ) -def count_words(text: str) -> int: - """Return the number of words in *text*. - - Words are split on whitespace. Empty strings are ignored. - """ - return len([w for w in text.split() if w]) - -# --------------------------------------------------------------------------- -# Main logic -# --------------------------------------------------------------------------- def main() -> None: - """Demonstrate the three example usages of the plan loader. + """Entry point that prints the generated plan.""" + plan = generate_plan() + print(str(plan)) - The function prints output to stdout. It is intentionally simple so - that it can be run in any environment without external dependencies. - """ - plan_path = Path(__file__).parent / "plan.txt" - try: - full_plan = read_plan_file(plan_path) - except FileNotFoundError as exc: - print(exc) - return - - # Example 1: Print the entire plan. - print("\n=== Full AI Fluency Plan ===") - print(full_plan) - - # Example 2: Show only the first five lines. - print("\n=== First 5 lines of the plan ===") - for line in get_first_n_lines(full_plan, 5): - print(line) - - # Example 3: Count words. - word_count = count_words(full_plan) - print(f"\nWord count: {word_count}") - -# --------------------------------------------------------------------------- -# Entry point guard -# --------------------------------------------------------------------------- if __name__ == "__main__": main() - -# --------------------------------------------------------------------------- -# End of file -# ---------------------------------------------------------------------------