Back to Courses

Complete AI Mastery Course

Published

A comprehensive 10-module journey from AI foundations to advanced agentic systems and entrepreneurship. Master prompt engineering, automation, coding with AI, and build a future-proof career.

Progress

0%

Pricing & Access

Students pay this to access the course. Leave "Paid course" off for free/enrolled-only access.

CPD Accreditation

Required for CPD — what a learner can do after the course. One outcome per line.

CPD hours (auto-computed)

0 CPD Hours

CPD status

Not submitted

Submitting sends this course for CPD verification. Once approved and the fee is paid, the CPD logo appears on this course's certificates.

Interactive

Project 2: Creating an AI-Powered Content Generator

Build an AI-powered content generator by choosing an LLM API, engineering effective prompts, and handling responses in Python, with optional fine-tuning, a UI, and cloud deployment.

{"contentFormat":"slides.v1","completion":{"requireAllSlides":true,"requireQuiz":true},"slides":[{"kind":"title","eyebrow":"Module 8: Portfolio Projects","title":"Project 2: Creating an AI-Powered Content Generator","body":"Build a real-world content generator using LLMs. You'll learn prompt engineering, API integration, error handling, and ethical considerations. By the end, you'll have a deployable tool for your portfolio.","outcomes":["Set up an LLM API client (OpenAI, Anthropic, or Google) with secure key management","Design and test prompts for different content types (blog posts, social media, ads)","Implement robust error handling and rate limit management","Add content moderation and ethical safeguards","Build a simple web interface (Streamlit) and deploy to the cloud"],"narration":"Welcome to Project 2: Creating an AI-Powered Content Generator. In this capstone, you'll build a complete content generation tool using state-of-the-art LLMs. We'll cover everything from API setup to ethical deployment."},{"kind":"content","heading":"Project Overview & Architecture","body":"You will build a content generator that can produce blog posts, social media captions, and ad copy. The system will use any current LLM API (OpenAI, Anthropic, or Google) with a Streamlit frontend. Pick a current low-cost text model from your provider and verify its exact model ID and pricing on the provider's model page before running the code. Key components:\n\n- API Client: Securely connects to the LLM service.\n- Prompt Templates: Pre-defined prompts for each content type.\n- Error Handler: Retries on rate limits, logs failures.\n- Moderation Layer: Checks input and output for harmful content.\n- UI: Streamlit app for easy interaction.\n\nArchitecture Diagram (text):\n\n

\nUser Input → Streamlit UI → Prompt Builder → API Client (with retry) → LLM API\n                                                      ↓\n                                              Moderation Check → Output\n
\n\nWe'll use Python 3.11+, openai v1.x, anthropic v0.x, google-generativeai, streamlit, and python-dotenv.","callout":{"variant":"tip","title":"Choose Your LLM","text":"Model names and prices change fast. The models named in this lesson are illustrative examples, not a current recommended list — always check your provider's model page for the current low-cost model ID and pricing before running the code. Most providers offer free tiers or new-user credits."},"narration":"Let's start with the architecture. Your content generator will have a Streamlit frontend, a prompt builder, an API client with retry logic, and a moderation layer. We'll use Python and the latest SDKs."},{"kind":"content","heading":"Step 1: Environment Setup & API Authentication","body":"Create a project folder and set up a virtual environment:\n\n
bash\nmkdir ai-content-generator\ncd ai-content-generator\npython -m venv venv\nsource venv/bin/activate  # On Windows: venv\\Scripts\\activate\n
\n\nInstall dependencies:\n\n
bash\npip install openai anthropic google-generativeai streamlit python-dotenv\n
\n\nCreate a .env file to store your API keys (never commit this file):\n\n
\nOPENAI_API_KEY=sk-...\nANTHROPIC_API_KEY=sk-ant-...\nGOOGLE_API_KEY=AIza...\n
\n\nLoad the keys in your code:\n\n
python\nimport os\nfrom dotenv import load_dotenv\n\nload_dotenv()\n\nopenai_api_key = os.getenv(\"OPENAI_API_KEY\")\nanthropic_api_key = os.getenv(\"ANTHROPIC_API_KEY\")\ngoogle_api_key = os.getenv(\"GOOGLE_API_KEY\")\n
\n\nSecurity Note: Always use environment variables. Never hardcode keys.","callout":{"variant":"warning","title":"API Key Security","text":"Add .env to your .gitignore. If you accidentally expose a key, revoke it immediately on the provider's dashboard."},"narration":"First, set up your environment. Create a virtual environment, install the SDKs, and store your API keys in a .env file. Never commit keys to version control."},{"kind":"content","heading":"Step 2: Building the API Client with Error Handling","body":"Create api_client.py with a class that handles multiple providers and includes retry logic for rate limits and transient errors.\n\n
python\nimport os\nimport time\nimport logging\nfrom openai import OpenAI\nfrom anthropic import Anthropic\nimport google.generativeai as genai\n\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(__name__)\n\nclass ContentGenerator:\n    def __init__(self, provider=\"openai\", model=None):\n        self.provider = provider\n        if provider == \"openai\":\n            self.client = OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))\n            self.model = model or \"gpt-4o-mini\"\n        elif provider == \"anthropic\":\n            self.client = Anthropic(api_key=os.getenv(\"ANTHROPIC_API_KEY\"))\n            self.model = model or \"claude-3-5-sonnet-20241022\"\n        elif provider == \"google\":\n            genai.configure(api_key=os.getenv(\"GOOGLE_API_KEY\"))\n            self.model = model or \"gemini-1.5-pro\"\n        else:\n            raise ValueError(\"Unsupported provider\")\n\n    def generate(self, prompt, max_retries=3, max_tokens=1000, temperature=0.7):\n        for attempt in range(max_retries):\n            try:\n                if self.provider == \"openai\":\n                    response = self.client.chat.completions.create(\n                        model=self.model,\n                        messages=[{\"role\": \"user\", \"content\": prompt}],\n                        max_tokens=max_tokens,\n                        temperature=temperature\n                    )\n                    return response.choices[0].message.content.strip()\n                elif self.provider == \"anthropic\":\n                    response = self.client.messages.create(\n                        model=self.model,\n                        max_tokens=max_tokens,\n                        temperature=temperature,\n                        messages=[{\"role\": \"user\", \"content\": prompt}]\n                    )\n                    return response.content[0].text.strip()\n                elif self.provider == \"google\":\n                    model = genai.GenerativeModel(self.model)\n                    response = model.generate_content(prompt)\n                    return response.text.strip()\n            except Exception as e:\n                logger.warning(f\"Attempt {attempt+1} failed: {e}\")\n                if \"rate\" in str(e).lower():\n                    time.sleep(2  attempt)  # Exponential backoff\n                else:\n                    raise\n        raise RuntimeError(\"Max retries exceeded\")\n
\n\nKey Points:\n- Exponential backoff on rate limits.\n- Logs errors for debugging.\n- Supports three major providers.","callout":{"variant":"exercise","title":"Test Your Client","text":"Write a quick test script that calls generate(\"Hello, world!\") with each provider. Verify you get a response and that retries work by temporarily using an invalid key."},"narration":"Now build the API client. This class supports OpenAI, Anthropic, and Google, with retry logic and exponential backoff for rate limits. Test it with a simple prompt."},{"kind":"content","heading":"Step 3: Prompt Engineering & Content Templates","body":"Create prompts.py with templates for different content types. Use clear instructions, constraints, and optional examples.\n\n
python\n# prompts.py\n\ndef blog_post_prompt(topic, tone=\"professional\", word_count=300):\n    return f\"\"\"Write a {tone} blog post about {topic}. Use markdown formatting with headings and bullet points.\nThe post should be approximately {word_count} words. Include an introduction, main body, and conclusion.\nAvoid jargon unless defined. Target audience: general readers interested in technology.\"\"\"\n\ndef social_media_prompt(topic, platform=\"Twitter\", tone=\"engaging\"):\n    return f\"\"\"Create a {platform} post about {topic}. Tone: {tone}. \n- For Twitter: max 280 characters, include 2-3 relevant hashtags.\n- For LinkedIn: 150-200 words, professional tone, include a call to action.\n- For Instagram: caption up to 2200 characters, include emojis and hashtags.\"\"\"\n\ndef ad_copy_prompt(product, audience, goal=\"conversion\"):\n    return f\"\"\"Write ad copy for {product}. Target audience: {audience}. Goal: {goal}.\nProvide three variants: one short (under 50 words), one medium (100-150 words), one long (200-300 words).\nInclude a strong headline and call to action.\"\"\"\n
\n\n
Best Practices:\n- Be specific about format, tone, length.\n- Provide examples if possible (few-shot prompting).\n- Use system messages for role-setting (e.g., \"You are an expert copywriter\").","callout":{"variant":"tip","title":"Iterate on Prompts","text":"Test each template with different topics. Adjust wording if output is off-topic or too generic. Save successful prompts as defaults."},"narration":"Prompt engineering is key. Create templates for blog posts, social media, and ad copy. Be specific about format, tone, and length. Test and iterate."},{"kind":"content","heading":"Step 4: Content Moderation & Ethical Safeguards","body":"Add a moderation layer to check both user input and generated output. Use the LLM's built-in moderation or a dedicated API.\n\nInput Moderation: Reject prompts that ask for harmful content.\n\nOutput Moderation: Check generated text for toxicity, plagiarism, or bias.\n\nExample using OpenAI's moderation endpoint:\n\n
python\ndef moderate_content(text, client):\n    try:\n        response = client.moderations.create(input=text)\n        if response.results[0].flagged:\n            return False, response.results[0].categories\n        return True, None\n    except Exception as e:\n        logger.error(f\"Moderation error: {e}\")\n        return True, None  # Fail open or closed? Decide based on risk.\n
\n\n
Ethical Guidelines:\n- Always disclose AI-generated content to users.\n- Avoid generating misleading or harmful content.\n- Respect copyright: do not reproduce copyrighted material verbatim.\n- Monitor for bias (e.g., gender, race) and adjust prompts.\n\nPlagiarism Check: Use a simple hash comparison or external API (e.g., Copyscape) for high-stakes content.","callout":{"variant":"warning","title":"Ethical Responsibility","text":"As of 2026, many jurisdictions require labeling AI-generated content. Always include a disclaimer. Use moderation to prevent misuse."},"narration":"Ethics matter. Add moderation to reject harmful inputs and flag problematic outputs. Always disclose AI generation. This protects users and builds trust."},{"kind":"content","heading":"Step 5: Building the Streamlit User Interface","body":"Create app.py with a simple UI for selecting content type, provider, and parameters.\n\n
python\nimport streamlit as st\nfrom api_client import ContentGenerator\nfrom prompts import blog_post_prompt, social_media_prompt, ad_copy_prompt\nfrom moderation import moderate_content\n\nst.set_page_config(page_title=\"AI Content Generator\", layout=\"wide\")\nst.title(\"AI-Powered Content Generator\")\n\n# Sidebar configuration\nwith st.sidebar:\n    st.header(\"Settings\")\n    provider = st.selectbox(\"LLM Provider\", [\"openai\", \"anthropic\", \"google\"])\n    content_type = st.selectbox(\"Content Type\", [\"Blog Post\", \"Social Media\", \"Ad Copy\"])\n    tone = st.selectbox(\"Tone\", [\"professional\", \"casual\", \"engaging\", \"humorous\"])\n    word_count = st.slider(\"Approximate Word Count\", 50, 1000, 300)\n    temperature = st.slider(\"Creativity (Temperature)\", 0.0, 1.0, 0.7)\n\n# Main area\ntopic = st.text_area(\"Enter your topic or product description\", height=150)\n\nif st.button(\"Generate Content\"):\n    if not topic.strip():\n        st.error(\"Please enter a topic.\")\n    else:\n        # Moderation check on input\n        client = ContentGenerator(provider=provider)\n        safe, categories = moderate_content(topic, client)\n        if not safe:\n            st.error(f\"Input flagged for: {categories}. Please revise.\")\n            st.stop()\n\n        # Build prompt\n        if content_type == \"Blog Post\":\n            prompt = blog_post_prompt(topic, tone, word_count)\n        elif content_type == \"Social Media\":\n            prompt = social_media_prompt(topic, platform=\"Twitter\", tone=tone)\n        else:\n            prompt = ad_copy_prompt(topic, audience=\"general\", goal=\"conversion\")\n\n        with st.spinner(\"Generating...\"):\n            try:\n                content = client.generate(prompt, max_tokens=word_count2, temperature=temperature)\n                # Output moderation\n                safe_out, _ = moderate_content(content, client)\n                if not safe_out:\n                    st.warning(\"Generated content may contain sensitive material. Review before use.\")\n                st.markdown(content)\n                st.download_button(\"Download as Markdown\", content, file_name=\"generated_content.md\")\n            except Exception as e:\n                st.error(f\"Generation failed: {e}\")\n
\n\nRun with: streamlit run app.py","callout":{"variant":"exercise","title":"Enhance the UI","text":"Add a history feature that saves previous generations to a session list. Allow users to compare outputs from different providers."},"narration":"Now build the Streamlit UI. Users can select provider, content type, tone, and word count. The app moderates input, generates content, and allows download."},{"kind":"content","heading":"Step 6: Testing, Refinement & Deployment","body":"
Testing Checklist:\n- [ ] Test with various topics (e.g., \"renewable energy in Kenya\", \"street food in Mexico City\", \"e-commerce trends in India\").\n- [ ] Test each content type and tone.\n- [ ] Test error handling: invalid API key, rate limit (send many requests quickly), network timeout.\n- [ ] Test moderation: try a prompt that asks for harmful content.\n- [ ] Test with different providers to compare quality and cost.\n\nRefinement Tips:\n- Adjust temperature: lower (0.2-0.5) for factual, higher (0.7-1.0) for creative.\n- Use system messages to set role (e.g., \"You are a marketing expert\").\n- Add few-shot examples in prompts for better consistency.\n\nDeployment Options:\n- Streamlit Community Cloud: Free, easy. Push your code to GitHub and connect.\n- Hugging Face Spaces: Free tier with GPU support.\n- Render / Railway: Paid but more control.\n\nWhat Good Looks Like*:\n- The app runs without errors.\n- Generated content is coherent, relevant, and matches the requested tone/length.\n- Moderation catches harmful inputs.\n- Error messages are user-friendly.\n- Code is clean, documented, and uses environment variables.","callout":{"variant":"insight","title":"Real-World Example","text":"A student in Brazil built a similar tool to generate social media content for local businesses. They used GPT-4o-mini and deployed on Streamlit Cloud. The tool reduced content creation time by 60%."},"narration":"Test thoroughly with diverse topics and edge cases. Refine prompts and parameters. Deploy to Streamlit Cloud or Hugging Face Spaces. A polished project shows you can ship."},{"kind":"quiz","heading":"Knowledge Check","questions":[{"question":"Which of the following is the correct way to instantiate the OpenAI client in the v1.x SDK?","options":["import openai; openai.api_key = '...'; response = openai.Completion.create(...)","from openai import OpenAI; client = OpenAI(api_key=os.getenv('OPENAI_API_KEY')); response = client.chat.completions.create(...)","from openai import Client; client = Client('...'); response = client.generate(...)","import openai; client = openai.Client(api_key='...'); response = client.complete(...)"],"questionId":"cmrf73kc9002ypd27qbv768nc"},{"question":"Why is it important to include a moderation layer in an AI content generator?","options":["To reduce API costs by filtering short inputs","To prevent the generation of harmful or biased content and comply with ethical guidelines","To improve the speed of content generation","To automatically format the output as HTML"],"questionId":"cmrf73kc9002zpd27eg9jf1w9"},{"question":"What is the purpose of exponential backoff in API error handling?","options":["To increase the number of retries exponentially","To decrease the waiting time between retries","To avoid overwhelming the server by increasing delay after each failed attempt","To log errors with increasing verbosity"],"questionId":"cmrf73kc90030pd27ft8ep4x1"}],"quizId":"qz_cmk7ln9zg003hg4p8roqs11zp"},{"kind":"summary","heading":"Project Recap & Next Steps","takeaways":["You built a multi-provider AI content generator with prompt templates for blog posts, social media, and ad copy.","You implemented secure API key management, error handling with retries, and content moderation.","You created a Streamlit UI and learned how to deploy it to the cloud.","You considered ethical implications: disclosure, moderation, and bias mitigation.","This project is a strong portfolio piece demonstrating full-stack AI engineering skills."],"narration":"Congratulations! You've built a complete AI-powered content generator. You now have a deployable app that showcases prompt engineering, API integration, error handling, and ethical safeguards. Add it to your portfolio and keep iterating."}]}