AI Artistic Coach — Technical Code

Hybrid local/BYOK/owner fallback code for the artistic teacher.

The full code is included in the client ZIP and in the platform folder under agents/artistic_coach/.
from __future__ import annotations

import json
from pathlib import Path

from .base_tutor_agent import BaseTutorAgent


class ArtisticTutorAgent(BaseTutorAgent):
    """AI Artistic Coach: drawing, painting, sculpture, digital art and AI-assisted creation."""

    def __init__(self, kb_path: str | None = None):
        if kb_path is None:
            kb_path = str(Path(__file__).resolve().parents[2] / "assets" / "knowledge" / "artistic_coach_kb.json")
        super().__init__(kb_path=kb_path, default_model="llama3.1")

    def suggest_program(self, level: str, goal: str) -> dict:
        programs = self.knowledge_base.get("programs", {})
        selected_name = None
        for name in programs:
            if level.lower() in name.lower() or goal.lower() in name.lower():
                selected_name = name
                break
        selected_name = selected_name or next(iter(programs.keys()), "Beginner — Learn to See")
        return {
            "selected_program": selected_name,
            "goal": goal,
            "steps": programs.get(selected_name, []),
            "method": ["lesson", "demonstration", "exercise", "student question", "correction", "revision plan"],
        }

    def create_lesson(self, topic: str, level: str = "beginner") -> str:
        prompt = (
            f"Create an art lesson for level {level} about: {topic}. "
            "Include objective, materials, step-by-step method, common mistakes, one exercise and correction grid."
        )
        return self.ask_llm(prompt, module_id="art_lesson").answer

    def critique_artwork(self, artwork_description: str) -> str:
        prompt = (
            "Critique this artwork constructively. Focus on composition, values, colors, focal point, style and one priority correction.\n"
            f"Artwork description: {artwork_description}"
        )
        return self.ask_llm(prompt, module_id="artwork_critique").answer

    def ai_prompt_for_reference(self, idea: str, medium: str = "digital painting") -> str:
        return (
            "Creative reference prompt:\n"
            f"{idea}, {medium}, original composition, strong lighting, balanced color palette, detailed but not copied from any living artist.\n\n"
            "Ethical note: use AI images as references or ideation boards, then create your own original artwork."
        )

    def sculpture_plan(self, subject: str) -> dict:
        return {
            "subject": subject,
            "materials": ["clay or polymer clay", "simple armature", "sculpting tools", "reference images", "calipers optional"],
            "steps": [
                "Block the main masses.",
                "Check silhouette and symmetry.",
                "Define planes before details.",
                "Refine proportions.",
                "Add texture and final expression.",
                "Photograph the sculpture from 4 angles."
            ],
            "correction_checklist": ["silhouette", "balance", "proportions", "planes", "surface finish"]
        }


if __name__ == "__main__":
    agent = ArtisticTutorAgent()
    print(agent.suggest_program("beginner", "drawing"))
    print(agent.ai_prompt_for_reference("Parisian art studio with a classical sculpture bust"))