| # Learning Path: Building AI-Powered CLI Tools with Python |
|
|
| A structured learning path for developers with basic Python knowledge who want to build AI-powered CLI tools using modern development practices. |
|
|
| ## π― Prerequisites |
|
|
| **What You Should Know:** |
| - Basic Python syntax (variables, functions, loops, conditionals) |
| - How to run Python scripts from the command line |
| - Basic understanding of files and directories |
| - Familiarity with text editors or IDEs |
|
|
| **What You'll Learn:** |
| - Building professional CLI applications |
| - Integrating AI/LLM capabilities |
| - Modern Python package management with pixi |
| - AI-assisted development with GitHub Copilot |
| - Package publishing and distribution |
|
|
| --- |
|
|
| ## π Learning Phases |
|
|
| ### Phase 1: Foundation Setup (Week 1) |
|
|
| #### 1.1 Development Environment Setup |
|
|
| **Install Required Tools:** |
|
|
| ```bash |
| # Install pixi (cross-platform package manager) |
| curl -fsSL https://pixi.sh/install.sh | bash |
| |
| # Verify installation |
| pixi --version |
| |
| # Install Git (if not already installed) |
| # Linux: sudo apt install git |
| # macOS: brew install git |
| # Windows: Download from git-scm.com |
| ``` |
|
|
| **Set Up GitHub Copilot:** |
| 1. Install VS Code or your preferred IDE |
| 2. Install GitHub Copilot extension |
| 3. Sign in with your GitHub account (requires Copilot subscription) |
| 4. Complete the Copilot quickstart tutorial |
|
|
| **Resources:** |
| - [Pixi Documentation](https://pixi.sh/latest/) |
| - [GitHub Copilot Getting Started](https://docs.github.com/en/copilot/getting-started-with-github-copilot) |
| - [VS Code Python Setup](https://code.visualstudio.com/docs/python/python-tutorial) |
|
|
| #### 1.2 Understanding Modern Python Project Structure |
|
|
| **Learn About:** |
| - Project organization (src layout vs flat layout) |
| - Virtual environments and dependency isolation |
| - Configuration files (`pyproject.toml`, `pixi.toml`) |
| - Version control with Git |
|
|
| **Hands-On Exercise:** |
| Create a simple "Hello World" project with pixi: |
|
|
| ```bash |
| # Create new project |
| pixi init my-first-cli |
| cd my-first-cli |
| |
| # Add Python dependency |
| pixi add python |
| |
| # Create a simple script |
| mkdir src |
| echo 'print("Hello from pixi!")' > src/hello.py |
| |
| # Run it |
| pixi run python src/hello.py |
| ``` |
|
|
| **Use Copilot to:** |
| - Generate a `.gitignore` file for Python projects |
| - Create a basic `README.md` template |
| - Write docstrings for your functions |
|
|
| --- |
|
|
| ### Phase 2: CLI Development Fundamentals (Week 2-3) |
|
|
| #### 2.1 Building Your First CLI with Typer |
|
|
| **Learning Objectives:** |
| - Understand command-line argument parsing with type hints |
| - Create commands, options, and flags using Python types |
| - Handle user input and validation |
| - Display formatted output with Rich integration |
|
|
| **Project: Simple File Organizer CLI** |
|
|
| > **Note**: This is a simplified version for learning CLI basics. For a comprehensive, production-ready example that integrates Docker AI, MCP servers, and multi-agent systems, see the [FileOrganizer project](projects/FileOrganizer.md) in Phase 7. |
|
|
| ```bash |
| # Initialize project with pixi |
| pixi init file-organizer-cli |
| cd file-organizer-cli |
| |
| # Add dependencies |
| pixi add python typer rich |
| |
| # Create project structure |
| mkdir -p src/file_organizer |
| touch src/file_organizer/__init__.py |
| touch src/file_organizer/cli.py |
| ``` |
|
|
| **Example CLI Structure (use Copilot to help generate):** |
|
|
| ```python |
| # src/file_organizer/cli.py |
| import typer |
| from pathlib import Path |
| from rich.console import Console |
| from typing import Optional |
| |
| app = typer.Typer(help="File organizer CLI tool") |
| console = Console() |
| |
| @app.command() |
| def organize( |
| directory: Path = typer.Argument(..., help="Directory to organize", exists=True), |
| dry_run: bool = typer.Option(False, "--dry-run", help="Preview changes without executing"), |
| verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed output") |
| ): |
| """Organize files in DIRECTORY by extension.""" |
| if verbose: |
| console.print(f"[blue]Organizing files in: {directory}[/blue]") |
| |
| # Use Copilot to generate the organization logic |
| if dry_run: |
| console.print("[yellow]DRY RUN - No changes will be made[/yellow]") |
| |
| pass |
| |
| @app.command() |
| def stats(directory: Path = typer.Argument(..., exists=True)): |
| """Show statistics about files in DIRECTORY.""" |
| # Use Copilot to generate statistics logic |
| pass |
| |
| if __name__ == '__main__': |
| app() |
| ``` |
|
|
| **Copilot Prompts to Try:** |
| - "Create a function to organize files by extension using pathlib" |
| - "Add error handling for file operations with try-except" |
| - "Generate help text and docstrings for CLI commands" |
| - "Add progress bar using rich library for file processing" |
|
|
| **Resources:** |
| - [Typer Documentation](https://typer.tiangolo.com/) |
| - [Typer Tutorial](https://typer.tiangolo.com/tutorial/) |
| - [Rich Documentation](https://rich.readthedocs.io/) |
|
|
| #### 2.2 Configuration and Settings Management |
|
|
| **Learn About:** |
| - Reading configuration files (YAML, TOML, JSON) |
| - Environment variables |
| - User preferences and defaults |
| - Configuration validation with Pydantic |
|
|
| **Add to Your Project:** |
|
|
| ```bash |
| # Add configuration dependencies |
| pixi add pydantic pyyaml python-dotenv |
| ``` |
|
|
| **Use Copilot to Generate:** |
| - Configuration schema with Pydantic |
| - Config file loader functions |
| - Environment variable handling |
|
|
| --- |
|
|
| ### Phase 3: AI Integration Basics (Week 4-5) |
|
|
| #### 3.1 Understanding HuggingFace and LLM APIs |
|
|
| **Learning Objectives:** |
| - API authentication and token management |
| - Using HuggingFace Inference API and local models |
| - Making API requests with transformers and huggingface_hub |
| - Handling streaming responses |
| - Error handling and rate limiting |
| |
| **Project: Add AI Capabilities to Your CLI** |
| |
| ```bash |
| # Add AI dependencies |
| pixi add transformers huggingface-hub python-dotenv |
| |
| # For local inference (optional) |
| pixi add torch |
| |
| # Create .env file for API keys |
| echo "HUGGINGFACE_TOKEN=your-token-here" > .env |
| echo ".env" >> .gitignore |
| ``` |
| |
| **Simple AI Integration Example:** |
| |
| ```python |
| # src/file_organizer/ai_helper.py |
| from huggingface_hub import InferenceClient |
| import os |
| from dotenv import load_dotenv |
|
|
| load_dotenv() |
| |
| def suggest_organization_strategy(file_list: list[str]) -> str: |
| """Use AI to suggest file organization strategy.""" |
| client = InferenceClient(token=os.getenv("HUGGINGFACE_TOKEN")) |
| |
| prompt = f"""Given these files: {', '.join(file_list)} |
| |
| Suggest an intelligent organization strategy. Group related files and explain your reasoning. |
| Respond in JSON format.""" |
| |
| # Use a free model like Mistral or Llama |
| response = client.text_generation( |
| prompt, |
| model="mistralai/Mistral-7B-Instruct-v0.2", |
| max_new_tokens=500, |
| temperature=0.7 |
| ) |
| |
| return response |
| |
| # Alternative: Using local models with transformers |
| from transformers import pipeline |
|
|
| def analyze_file_content_local(content: str) -> str: |
| """Analyze file content using a local model.""" |
| # Use Copilot to complete this function |
| # Prompt: "Create a function that uses a local HuggingFace model |
| # to analyze and categorize file content" |
| |
| classifier = pipeline( |
| "text-classification", |
| model="distilbert-base-uncased-finetuned-sst-2-english" |
| ) |
| |
| result = classifier(content[:512]) # Truncate for model limits |
| return result |
| ``` |
| |
| **Copilot Exercises:** |
| - "Create a function to summarize file contents using HuggingFace models" |
| - "Add retry logic for API failures with exponential backoff" |
| - "Implement streaming response handler for long-form generation" |
| - "Create a model selector that chooses between local and API inference" |
| |
| **Resources:** |
| - [HuggingFace Hub Documentation](https://huggingface.co/docs/huggingface_hub/) |
| - [Transformers Documentation](https://huggingface.co/docs/transformers/) |
| - [HuggingFace Inference API](https://huggingface.co/docs/api-inference/) |
| - [Free Models on HuggingFace](https://huggingface.co/models) |
| |
| **Popular Models to Try:** |
| - **Text Generation**: `mistralai/Mistral-7B-Instruct-v0.2`, `meta-llama/Llama-2-7b-chat-hf` |
| - **Summarization**: `facebook/bart-large-cnn`, `google/pegasus-xsum` |
| - **Classification**: `distilbert-base-uncased`, `roberta-base` |
| - **Embeddings**: `sentence-transformers/all-MiniLM-L6-v2` |
| |
| **Local vs API Inference:** |
| |
| ```python |
| # src/file_organizer/inference.py |
| from typing import Literal |
| import os |
|
|
| class AIHelper: |
| """Flexible AI helper supporting both local and API inference.""" |
| |
| def __init__(self, mode: Literal["local", "api"] = "api"): |
| self.mode = mode |
| |
| if mode == "api": |
| from huggingface_hub import InferenceClient |
| self.client = InferenceClient(token=os.getenv("HUGGINGFACE_TOKEN")) |
| else: |
| from transformers import pipeline |
| # Load model once at initialization |
| self.pipeline = pipeline( |
| "text-generation", |
| model="distilgpt2", # Smaller model for local use |
| device=-1 # CPU, use 0 for GPU |
| ) |
| |
| def generate(self, prompt: str) -> str: |
| """Generate text using configured mode.""" |
| if self.mode == "api": |
| return self.client.text_generation( |
| prompt, |
| model="mistralai/Mistral-7B-Instruct-v0.2", |
| max_new_tokens=500 |
| ) |
| else: |
| result = self.pipeline(prompt, max_new_tokens=100) |
| return result[0]['generated_text'] |
| |
| # Usage in CLI |
| # Use Copilot: "Add a --local flag to switch between API and local inference" |
| ``` |
| |
| **When to Use Each:** |
| - **API Inference**: Better quality, larger models, no local resources needed, requires internet |
| - **Local Inference**: Privacy, offline use, no API costs, but requires more RAM/GPU |
| - **vLLM Server**: Best of both worlds - local privacy with high performance and OpenAI-compatible API |
| |
| **Advanced: Serving Local Models with vLLM** |
| |
| vLLM is a high-performance inference engine that can serve local models with significantly better throughput and lower latency than standard transformers. |
| |
| ```bash |
| # Install vLLM (requires GPU for best performance) |
| pixi add vllm |
|
|
| # Or install with specific CUDA version |
| pixi add "vllm[cuda12]" |
| ``` |
| |
| **Starting a vLLM Server:** |
| |
| ```bash |
| # Start vLLM server with a model |
| # This creates an OpenAI-compatible API endpoint |
| vllm serve mistralai/Mistral-7B-Instruct-v0.2 \ |
| --host 0.0.0.0 \ |
| --port 8000 \ |
| --max-model-len 4096 |
| |
| # For smaller GPUs, use quantized models |
| vllm serve TheBloke/Mistral-7B-Instruct-v0.2-GPTQ \ |
| --quantization gptq \ |
| --dtype half |
| ``` |
| |
| **Using vLLM Server in Your CLI:** |
|
|
| ```python |
| # src/file_organizer/vllm_client.py |
| from openai import OpenAI |
| from typing import Optional |
| |
| class vLLMClient: |
| """Client for vLLM server with OpenAI-compatible API.""" |
| |
| def __init__(self, base_url: str = "http://localhost:8000/v1"): |
| # vLLM provides OpenAI-compatible endpoints |
| self.client = OpenAI( |
| base_url=base_url, |
| api_key="not-needed" # vLLM doesn't require API key |
| ) |
| |
| def generate( |
| self, |
| prompt: str, |
| model: str = "mistralai/Mistral-7B-Instruct-v0.2", |
| max_tokens: int = 500, |
| temperature: float = 0.7 |
| ) -> str: |
| """Generate text using vLLM server.""" |
| response = self.client.completions.create( |
| model=model, |
| prompt=prompt, |
| max_tokens=max_tokens, |
| temperature=temperature |
| ) |
| return response.choices[0].text |
| |
| def chat_generate( |
| self, |
| messages: list[dict], |
| model: str = "mistralai/Mistral-7B-Instruct-v0.2", |
| max_tokens: int = 500 |
| ) -> str: |
| """Generate using chat completion format.""" |
| response = self.client.chat.completions.create( |
| model=model, |
| messages=messages, |
| max_tokens=max_tokens |
| ) |
| return response.choices[0].message.content |
| |
| # Usage in your CLI |
| def suggest_organization_with_vllm(file_list: list[str]) -> str: |
| """Use local vLLM server for suggestions.""" |
| client = vLLMClient() |
| |
| messages = [ |
| {"role": "system", "content": "You are a file organization assistant."}, |
| {"role": "user", "content": f"Organize these files: {', '.join(file_list)}"} |
| ] |
| |
| return client.chat_generate(messages) |
| ``` |
|
|
| **Complete Inference Strategy:** |
|
|
| ```python |
| # src/file_organizer/ai_strategy.py |
| from typing import Literal |
| import os |
| from enum import Enum |
| |
| class InferenceMode(str, Enum): |
| """Available inference modes.""" |
| API = "api" # HuggingFace Inference API |
| LOCAL = "local" # Direct transformers |
| VLLM = "vllm" # vLLM server |
| AUTO = "auto" # Auto-detect best option |
| |
| class UnifiedAIClient: |
| """Unified client supporting multiple inference backends.""" |
| |
| def __init__(self, mode: InferenceMode = InferenceMode.AUTO): |
| self.mode = self._resolve_mode(mode) |
| self._setup_client() |
| |
| def _resolve_mode(self, mode: InferenceMode) -> InferenceMode: |
| """Auto-detect best available mode.""" |
| if mode != InferenceMode.AUTO: |
| return mode |
| |
| # Check if vLLM server is running |
| try: |
| import requests |
| requests.get("http://localhost:8000/health", timeout=1) |
| return InferenceMode.VLLM |
| except: |
| pass |
| |
| # Check if HuggingFace token is available |
| if os.getenv("HUGGINGFACE_TOKEN"): |
| return InferenceMode.API |
| |
| # Fall back to local |
| return InferenceMode.LOCAL |
| |
| def _setup_client(self): |
| """Initialize the appropriate client.""" |
| if self.mode == InferenceMode.VLLM: |
| from openai import OpenAI |
| self.client = OpenAI( |
| base_url="http://localhost:8000/v1", |
| api_key="not-needed" |
| ) |
| elif self.mode == InferenceMode.API: |
| from huggingface_hub import InferenceClient |
| self.client = InferenceClient(token=os.getenv("HUGGINGFACE_TOKEN")) |
| else: # LOCAL |
| from transformers import pipeline |
| self.client = pipeline("text-generation", model="distilgpt2") |
| |
| def generate(self, prompt: str, **kwargs) -> str: |
| """Generate text using configured backend.""" |
| if self.mode == InferenceMode.VLLM: |
| response = self.client.completions.create( |
| model="mistralai/Mistral-7B-Instruct-v0.2", |
| prompt=prompt, |
| max_tokens=kwargs.get("max_tokens", 500) |
| ) |
| return response.choices[0].text |
| |
| elif self.mode == InferenceMode.API: |
| return self.client.text_generation( |
| prompt, |
| model="mistralai/Mistral-7B-Instruct-v0.2", |
| max_new_tokens=kwargs.get("max_tokens", 500) |
| ) |
| |
| else: # LOCAL |
| result = self.client(prompt, max_new_tokens=kwargs.get("max_tokens", 100)) |
| return result[0]['generated_text'] |
| |
| # Use in CLI with Typer |
| import typer |
| |
| @app.command() |
| def organize( |
| directory: Path, |
| inference_mode: InferenceMode = typer.Option( |
| InferenceMode.AUTO, |
| "--mode", |
| help="Inference mode: api, local, vllm, or auto" |
| ) |
| ): |
| """Organize files using AI.""" |
| ai_client = UnifiedAIClient(mode=inference_mode) |
| # Use ai_client.generate() for suggestions |
| ``` |
|
|
| **vLLM Performance Tips:** |
|
|
| 1. **GPU Memory**: Use `--gpu-memory-utilization 0.9` to maximize GPU usage |
| 2. **Batch Size**: vLLM automatically batches requests for better throughput |
| 3. **Quantization**: Use GPTQ or AWQ quantized models for lower memory usage |
| 4. **Tensor Parallelism**: For multi-GPU: `--tensor-parallel-size 2` |
|
|
| **Docker Compose for vLLM (Optional):** |
|
|
| ```yaml |
| # docker-compose.vllm.yml |
| version: '3.8' |
| |
| services: |
| vllm: |
| image: vllm/vllm-openai:latest |
| ports: |
| - "8000:8000" |
| environment: |
| - MODEL=mistralai/Mistral-7B-Instruct-v0.2 |
| - MAX_MODEL_LEN=4096 |
| deploy: |
| resources: |
| reservations: |
| devices: |
| - driver: nvidia |
| count: 1 |
| capabilities: [gpu] |
| command: > |
| --host 0.0.0.0 |
| --port 8000 |
| --model ${MODEL} |
| --max-model-len ${MAX_MODEL_LEN} |
| ``` |
|
|
| **Comparison:** |
|
|
| | Feature | HF API | Transformers | vLLM | |
| |---------|--------|--------------|------| |
| | Setup | Easy | Easy | Medium | |
| | Speed | Fast | Slow | Very Fast | |
| | Cost | Pay per use | Free | Free (local) | |
| | GPU Required | No | Optional | Recommended | |
| | Offline | No | Yes | Yes | |
| | Batch Processing | Limited | Poor | Excellent | |
| | Memory Efficient | N/A | No | Yes | |
| | OpenAI Compatible | No | No | Yes | |
|
|
| **Recommended Workflow:** |
| 1. **Development**: Use HuggingFace API for quick prototyping |
| 2. **Testing**: Use vLLM locally for faster iteration |
| 3. **Production**: Deploy vLLM server for best performance and privacy |
|
|
| #### 3.2 Docker-Based Model Deployment |
|
|
| Docker provides a modern, standardized way to deploy local LLM models with minimal configuration using Docker Compose v2.38+. |
|
|
| **Why Use Docker for AI Models?** |
| - **Consistent environments**: Same setup across development, testing, and production |
| - **Easy deployment**: One command to start models and services |
| - **Resource isolation**: Models run in containers with defined resource limits |
| - **Portability**: Works locally with Docker Model Runner or on cloud providers |
| - **Version control**: Pin specific model versions with OCI artifacts |
|
|
| **Prerequisites:** |
|
|
| ```bash |
| # Ensure Docker Compose v2.38 or later |
| docker compose version |
| |
| # Enable Docker Model Runner in Docker Desktop settings |
| # Or install separately: https://docs.docker.com/ai/model-runner/ |
| ``` |
|
|
| **Basic Model Deployment with Docker Compose:** |
|
|
| Create a `docker-compose.yml` for your CLI project: |
|
|
| ```yaml |
| # docker-compose.yml |
| services: |
| # Your CLI application |
| file-organizer: |
| build: . |
| models: |
| - llm # Reference to the model defined below |
| environment: |
| # Auto-injected by Docker: |
| # LLM_URL - endpoint to access the model |
| # LLM_MODEL - model identifier |
| volumes: |
| - ./data:/app/data |
| |
| models: |
| llm: |
| model: ai/smollm2 # Model from Docker Hub |
| context_size: 4096 |
| runtime_flags: |
| - "--verbose" |
| - "--log-colors" |
| ``` |
|
|
| **Using Models in Your Python CLI:** |
|
|
| ```python |
| # src/file_organizer/docker_ai.py |
| import os |
| from openai import OpenAI |
| |
| class DockerModelClient: |
| """Client for Docker-deployed models with OpenAI-compatible API.""" |
| |
| def __init__(self): |
| # Docker automatically injects these environment variables |
| model_url = os.getenv("LLM_URL") |
| model_name = os.getenv("LLM_MODEL") |
| |
| if not model_url: |
| raise ValueError("LLM_URL not set. Are you running with Docker Compose?") |
| |
| # Docker models provide OpenAI-compatible endpoints |
| self.client = OpenAI( |
| base_url=model_url, |
| api_key="not-needed" # Docker models don't require API keys |
| ) |
| self.model_name = model_name |
| |
| def generate(self, prompt: str, max_tokens: int = 500) -> str: |
| """Generate text using Docker-deployed model.""" |
| response = self.client.completions.create( |
| model=self.model_name, |
| prompt=prompt, |
| max_tokens=max_tokens, |
| temperature=0.7 |
| ) |
| return response.choices[0].text |
| |
| def chat_generate(self, messages: list[dict], max_tokens: int = 500) -> str: |
| """Generate using chat completion format.""" |
| response = self.client.chat.completions.create( |
| model=self.model_name, |
| messages=messages, |
| max_tokens=max_tokens |
| ) |
| return response.choices[0].message.content |
| |
| # Usage in your CLI |
| import typer |
| |
| @app.command() |
| def organize(directory: Path): |
| """Organize files using Docker-deployed AI model.""" |
| try: |
| ai_client = DockerModelClient() |
| # Use the model for suggestions |
| suggestion = ai_client.generate(f"Organize these files: {list(directory.iterdir())}") |
| console.print(suggestion) |
| except ValueError as e: |
| console.print(f"[red]Error: {e}[/red]") |
| console.print("[yellow]Run with: docker compose up[/yellow]") |
| ``` |
|
|
| **Multi-Model Setup:** |
|
|
| Deploy multiple models for different tasks: |
|
|
| ```yaml |
| services: |
| file-organizer: |
| build: . |
| models: |
| chat-model: |
| endpoint_var: CHAT_MODEL_URL |
| model_var: CHAT_MODEL_NAME |
| embeddings: |
| endpoint_var: EMBEDDING_URL |
| model_var: EMBEDDING_NAME |
| |
| models: |
| chat-model: |
| model: ai/smollm2 |
| context_size: 4096 |
| runtime_flags: |
| - "--temp" |
| - "0.7" |
| |
| embeddings: |
| model: ai/all-minilm |
| context_size: 512 |
| ``` |
|
|
| **Model Configuration Presets:** |
|
|
| ```yaml |
| # Development mode - verbose logging |
| models: |
| dev_model: |
| model: ai/smollm2 |
| context_size: 4096 |
| runtime_flags: |
| - "--verbose" |
| - "--verbose-prompt" |
| - "--log-timestamps" |
| - "--log-colors" |
| |
| # Production mode - deterministic output |
| models: |
| prod_model: |
| model: ai/smollm2 |
| context_size: 4096 |
| runtime_flags: |
| - "--temp" |
| - "0.1" # Low temperature for consistency |
| - "--top-k" |
| - "1" |
| |
| # Creative mode - high randomness |
| models: |
| creative_model: |
| model: ai/smollm2 |
| context_size: 4096 |
| runtime_flags: |
| - "--temp" |
| - "1.0" |
| - "--top-p" |
| - "0.9" |
| ``` |
|
|
| **Running Your Dockerized CLI:** |
|
|
| ```bash |
| # Start models and services |
| docker compose up -d |
| |
| # Check model status |
| docker compose ps |
| |
| # View model logs |
| docker compose logs llm |
| |
| # Run your CLI (models are available via environment variables) |
| docker compose exec file-organizer python -m file_organizer organize ./data |
| |
| # Stop everything |
| docker compose down |
| ``` |
|
|
| **Complete Example Dockerfile:** |
|
|
| ```dockerfile |
| # Dockerfile |
| FROM python:3.11-slim |
| |
| WORKDIR /app |
| |
| # Install dependencies |
| COPY pyproject.toml . |
| RUN pip install -e . |
| |
| # Copy application code |
| COPY src/ ./src/ |
| |
| # The CLI will use environment variables injected by Docker Compose |
| CMD ["python", "-m", "file_organizer.cli"] |
| ``` |
|
|
| **Benefits of Docker Deployment:** |
|
|
| | Feature | Docker Compose | Manual Setup | |
| |---------|----------------|-------------| |
| | Setup Time | Minutes | Hours | |
| | Consistency | β
Same everywhere | β Varies by system | |
| | Resource Control | β
Built-in limits | β οΈ Manual config | |
| | Multi-model | β
Easy | β Complex | |
| | Cloud Portability | β
Same config | β Rewrite needed | |
| | Version Control | β
Git-friendly | β οΈ Documentation | |
|
|
| **Cloud Deployment:** |
|
|
| The same `docker-compose.yml` works on cloud providers with extensions: |
|
|
| ```yaml |
| models: |
| llm: |
| model: ai/smollm2 |
| context_size: 4096 |
| # Cloud-specific options (provider-dependent) |
| x-cloud-options: |
| - "cloud.instance-type=gpu-small" |
| - "cloud.region=us-west-2" |
| - "cloud.auto-scaling=true" |
| ``` |
|
|
| **Resources:** |
| - [Docker AI Documentation](https://docs.docker.com/ai/) |
| - [Docker Compose Models Reference](https://docs.docker.com/ai/compose/models-and-compose/) |
| - [Docker Model Runner](https://docs.docker.com/ai/model-runner/) |
| - [Available Models on Docker Hub](https://hub.docker.com/search?q=ai%2F) |
|
|
| #### 3.3 Docker MCP Toolkit: Secure Tool Integration |
|
|
| The Model Context Protocol (MCP) provides a standardized way for AI agents to interact with external tools and data sources. Docker's MCP Toolkit makes this secure and easy. |
|
|
| **What is MCP?** |
|
|
| MCP is an open protocol that allows AI models to: |
| - Execute code in isolated environments |
| - Access databases and APIs securely |
| - Use external tools (web search, calculators, etc.) |
| - Retrieve real-world data |
|
|
| **Why Docker MCP?** |
|
|
| 1. **Security**: Tools run in isolated containers |
| 2. **Trust**: Curated catalog with publisher verification |
| 3. **Simplicity**: One-click deployment from Docker Desktop |
| 4. **Dynamic Discovery**: Agents find and add tools as needed |
|
|
| **Docker MCP Components:** |
|
|
| ```yaml |
| # docker-compose.yml with MCP Gateway |
| services: |
| # Your AI-powered CLI |
| file-organizer: |
| build: . |
| models: |
| - llm |
| environment: |
| - MCP_GATEWAY_URL=http://mcp-gateway:3000 |
| depends_on: |
| - mcp-gateway |
| |
| # MCP Gateway - manages MCP servers |
| mcp-gateway: |
| image: docker/mcp-gateway:latest |
| ports: |
| - "3000:3000" |
| volumes: |
| - mcp-data:/data |
| environment: |
| - MCP_CATALOG_URL=https://hub.docker.com/mcp |
| |
| models: |
| llm: |
| model: ai/smollm2 |
| context_size: 4096 |
| |
| volumes: |
| mcp-data: |
| ``` |
|
|
| **Using MCP in Your CLI:** |
|
|
| ```python |
| # src/file_organizer/mcp_client.py |
| import os |
| import requests |
| from typing import Any |
| |
| class MCPClient: |
| """Client for Docker MCP Gateway.""" |
| |
| def __init__(self): |
| self.gateway_url = os.getenv("MCP_GATEWAY_URL", "http://localhost:3000") |
| |
| def find_servers(self, query: str) -> list[dict]: |
| """Find MCP servers by name or description.""" |
| response = requests.post( |
| f"{self.gateway_url}/mcp-find", |
| json={"query": query} |
| ) |
| return response.json()["servers"] |
| |
| def add_server(self, server_name: str) -> dict: |
| """Add an MCP server to the current session.""" |
| response = requests.post( |
| f"{self.gateway_url}/mcp-add", |
| json={"server": server_name} |
| ) |
| return response.json() |
| |
| def call_tool(self, server: str, tool: str, params: dict) -> Any: |
| """Call a tool from an MCP server.""" |
| response = requests.post( |
| f"{self.gateway_url}/mcp-call", |
| json={ |
| "server": server, |
| "tool": tool, |
| "parameters": params |
| } |
| ) |
| return response.json()["result"] |
| |
| # Example: Web search integration |
| @app.command() |
| def research(topic: str): |
| """Research a topic using web search MCP.""" |
| mcp = MCPClient() |
| |
| # Find web search servers |
| servers = mcp.find_servers("web search") |
| console.print(f"Found {len(servers)} search servers") |
| |
| # Add DuckDuckGo MCP |
| mcp.add_server("duckduckgo-mcp") |
| |
| # Use the search tool |
| results = mcp.call_tool( |
| server="duckduckgo-mcp", |
| tool="search", |
| params={"query": topic, "max_results": 5} |
| ) |
| |
| # Display results |
| for result in results: |
| console.print(f"[bold]{result['title']}[/bold]") |
| console.print(f" {result['url']}") |
| console.print(f" {result['snippet']}\n") |
| ``` |
|
|
| **Dynamic MCP Discovery:** |
|
|
| Let AI agents discover and use tools automatically: |
|
|
| ```python |
| # src/file_organizer/ai_agent.py |
| from openai import OpenAI |
| import json |
| |
| class AIAgentWithMCP: |
| """AI agent that can discover and use MCP tools.""" |
| |
| def __init__(self): |
| self.llm = OpenAI(base_url=os.getenv("LLM_URL"), api_key="not-needed") |
| self.mcp = MCPClient() |
| self.available_tools = [] |
| |
| def discover_tools(self, task_description: str): |
| """Ask LLM what tools are needed for a task.""" |
| prompt = f"""Task: {task_description} |
| |
| What MCP tools would be helpful? Respond with JSON: |
| {{"tools": ["tool-name-1", "tool-name-2"]}} |
| """ |
| |
| response = self.llm.completions.create( |
| model=os.getenv("LLM_MODEL"), |
| prompt=prompt, |
| max_tokens=200 |
| ) |
| |
| tools_needed = json.loads(response.choices[0].text) |
| |
| # Add each tool |
| for tool in tools_needed["tools"]: |
| servers = self.mcp.find_servers(tool) |
| if servers: |
| self.mcp.add_server(servers[0]["name"]) |
| self.available_tools.append(servers[0]) |
| |
| def execute_task(self, task: str): |
| """Execute a task using available tools.""" |
| # First, discover what tools we need |
| self.discover_tools(task) |
| |
| # Then execute with those tools |
| # (Implementation depends on your specific use case) |
| pass |
| |
| # Usage |
| @app.command() |
| def smart_organize(directory: Path, strategy: str): |
| """Organize files using AI with dynamic tool discovery.""" |
| agent = AIAgentWithMCP() |
| |
| task = f"Organize files in {directory} using strategy: {strategy}" |
| agent.execute_task(task) |
| ``` |
|
|
| **Available MCP Servers:** |
|
|
| The [Docker MCP Catalog](https://hub.docker.com/mcp) includes 270+ servers: |
|
|
| - **Web Search**: DuckDuckGo, Brave Search |
| - **Databases**: PostgreSQL, MongoDB, Elasticsearch |
| - **APIs**: Stripe, GitHub, Slack |
| - **Monitoring**: Grafana, Prometheus |
| - **File Systems**: Local files, S3, Google Drive |
| - **Development**: Git, Docker, Kubernetes |
|
|
| **Security Features:** |
|
|
| 1. **Container Isolation**: Each MCP server runs in its own container |
| 2. **Commit Pinning**: Servers tied to specific Git commits |
| 3. **Publisher Trust Levels**: Official, verified, and community servers |
| 4. **AI-Audited Updates**: Automated code review for changes |
| 5. **Resource Limits**: CPU and memory constraints per server |
|
|
| **Complete Example with MCP:** |
|
|
| ```yaml |
| # docker-compose.yml - Full AI CLI with MCP |
| services: |
| file-organizer: |
| build: . |
| models: |
| - llm |
| environment: |
| - MCP_GATEWAY_URL=http://mcp-gateway:3000 |
| - ENABLE_DYNAMIC_MCPS=true |
| depends_on: |
| - mcp-gateway |
| volumes: |
| - ./data:/app/data |
| |
| mcp-gateway: |
| image: docker/mcp-gateway:latest |
| ports: |
| - "3000:3000" |
| volumes: |
| - mcp-data:/data |
| - ./mcp-config.yml:/config/catalog.yml |
| |
| models: |
| llm: |
| model: ai/smollm2 |
| context_size: 4096 |
| runtime_flags: |
| - "--temp" |
| - "0.7" |
| |
| volumes: |
| mcp-data: |
| ``` |
|
|
| **MCP Best Practices:** |
|
|
| 1. **Start with trusted servers**: Use official and verified publishers |
| 2. **Enable only needed tools**: Reduce attack surface |
| 3. **Monitor MCP usage**: Track which tools are called |
| 4. **Set resource limits**: Prevent runaway processes |
| 5. **Review permissions**: Understand what each MCP can access |
|
|
| **Resources:** |
| - [Docker MCP Gateway (GitHub)](https://github.com/docker/mcp-gateway/) |
| - [Docker MCP Catalog](https://hub.docker.com/mcp) |
| - [MCP Registry](https://github.com/docker/mcp-registry) |
| - [Dynamic MCPs Blog](https://www.docker.com/blog/dynamic-mcps-stop-hardcoding-your-agents-world/) |
| - [MCP Security Blog](https://www.docker.com/blog/enhancing-mcp-trust-with-the-docker-mcp-catalog/) |
|
|
| #### 3.4 Prompt Engineering for CLI Tools |
|
|
| **Learn About:** |
| - Crafting effective prompts for different model types |
| - Understanding model-specific prompt formats (Mistral, Llama, etc.) |
| - System vs user messages (for chat models) |
| - Few-shot learning examples |
| - Prompt templates and variables |
|
|
| **Hands-On:** |
| Create a prompt template system: |
|
|
| ```python |
| # src/file_organizer/prompts.py |
| |
| # For instruction-tuned models like Mistral |
| MISTRAL_ORGANIZATION_PROMPT = """[INST] You are a helpful file organization assistant. |
| |
| Given the following list of files: |
| {file_list} |
| |
| Suggest an intelligent organization strategy that: |
| 1. Groups related files together |
| 2. Creates meaningful folder names |
| 3. Explains the reasoning |
| |
| Respond in JSON format with this structure: |
| {{ |
| "strategy": "description", |
| "folders": [ |
| {{"name": "folder_name", "files": ["file1", "file2"], "reason": "why"}} |
| ] |
| }} [/INST]""" |
| |
| # For Llama-2 chat models |
| LLAMA_SYSTEM_PROMPT = """You are a helpful file organization assistant. |
| Always respond in valid JSON format.""" |
| |
| def format_llama_prompt(user_message: str) -> str: |
| """Format prompt for Llama-2 chat models.""" |
| return f"""<s>[INST] <<SYS>> |
| {LLAMA_SYSTEM_PROMPT} |
| <</SYS>> |
| |
| {user_message} [/INST]""" |
| |
| # For general models without special formatting |
| GENERIC_PROMPT_TEMPLATE = """Task: Organize the following files intelligently. |
| |
| Files: {file_list} |
| |
| Instructions: |
| - Group related files together |
| - Suggest meaningful folder names |
| - Explain your reasoning |
| - Output as JSON |
| |
| Response:""" |
| |
| # Use Copilot to generate more prompt templates for different tasks |
| ``` |
|
|
| **Model-Specific Considerations:** |
|
|
| ```python |
| # src/file_organizer/model_config.py |
| |
| MODEL_CONFIGS = { |
| "mistralai/Mistral-7B-Instruct-v0.2": { |
| "max_tokens": 8192, |
| "prompt_format": "mistral", |
| "temperature": 0.7, |
| "use_case": "general instruction following" |
| }, |
| "meta-llama/Llama-2-7b-chat-hf": { |
| "max_tokens": 4096, |
| "prompt_format": "llama2", |
| "temperature": 0.7, |
| "use_case": "conversational tasks" |
| }, |
| "facebook/bart-large-cnn": { |
| "max_tokens": 1024, |
| "prompt_format": "none", |
| "use_case": "summarization only" |
| } |
| } |
| |
| def get_model_config(model_name: str) -> dict: |
| """Get configuration for a specific model.""" |
| return MODEL_CONFIGS.get(model_name, {}) |
| ``` |
|
|
| **Copilot Prompts:** |
| - "Create a function to format prompts based on model type" |
| - "Generate few-shot examples for file categorization" |
| - "Build a prompt validator that checks token limits" |
| - "Create a prompt optimization function that reduces token usage" |
|
|
| --- |
|
|
| ### Phase 4: Advanced CLI Features (Week 6-7) |
|
|
| #### 4.1 Interactive CLI Elements |
|
|
| **Add Dependencies:** |
|
|
| ```bash |
| pixi add questionary rich typer |
| ``` |
|
|
| **Learn to Build:** |
| - Interactive prompts and menus |
| - Progress bars and spinners |
| - Tables and formatted output |
| - Color-coded messages |
|
|
| **Example with Copilot:** |
|
|
| ```python |
| # Ask Copilot: "Create an interactive menu using questionary |
| # to select file organization options" |
| |
| import questionary |
| from rich.progress import track |
| |
| def interactive_organize(): |
| # Copilot will help generate this |
| pass |
| ``` |
|
|
| #### 4.2 Batch Processing and Async Operations |
|
|
| **Learn About:** |
| - Processing multiple files efficiently |
| - Async/await for concurrent API calls |
| - Rate limiting and throttling |
| - Progress tracking for long operations |
|
|
| ```bash |
| # Add async dependencies |
| pixi add aiohttp asyncio |
| ``` |
|
|
| **Copilot Exercise:** |
| - "Create an async function to process multiple files with OpenAI API" |
| - "Add rate limiting to prevent API quota exhaustion" |
| - "Implement a queue system for batch processing" |
|
|
| --- |
|
|
| ### Phase 5: Testing and Quality (Week 8) |
|
|
| #### 5.1 Writing Tests |
|
|
| **Add Testing Dependencies:** |
|
|
| ```bash |
| pixi add pytest pytest-cov pytest-asyncio pytest-mock |
| ``` |
|
|
| **Learn to Test:** |
| - Unit tests for individual functions |
| - Integration tests for CLI commands |
| - Mocking API calls |
| - Test coverage reporting |
|
|
| **Example Test Structure:** |
|
|
| ```python |
| # tests/test_cli.py |
| import pytest |
| from typer.testing import CliRunner |
| from file_organizer.cli import app |
| |
| runner = CliRunner() |
| |
| def test_organize_command(): |
| # Use Copilot to generate test cases |
| result = runner.invoke(app, ['organize', 'test_dir', '--dry-run']) |
| assert result.exit_code == 0 |
| assert "DRY RUN" in result.stdout |
| |
| def test_organize_with_verbose(): |
| result = runner.invoke(app, ['organize', 'test_dir', '--verbose']) |
| assert result.exit_code == 0 |
| |
| def test_stats_command(): |
| result = runner.invoke(app, ['stats', 'test_dir']) |
| assert result.exit_code == 0 |
| ``` |
|
|
| **Copilot Prompts:** |
| - "Generate pytest fixtures for mocking HuggingFace Inference API" |
| - "Create test cases for error handling with API timeouts" |
| - "Write integration tests for the organize command" |
| - "Mock transformers pipeline for local model testing" |
|
|
| **Example Mocking HuggingFace:** |
|
|
| ```python |
| # tests/conftest.py |
| import pytest |
| from unittest.mock import Mock, patch |
| |
| @pytest.fixture |
| def mock_hf_client(): |
| """Mock HuggingFace InferenceClient.""" |
| with patch('huggingface_hub.InferenceClient') as mock: |
| mock_instance = Mock() |
| mock_instance.text_generation.return_value = '{"strategy": "test"}' |
| mock.return_value = mock_instance |
| yield mock_instance |
| |
| @pytest.fixture |
| def mock_transformers_pipeline(): |
| """Mock transformers pipeline for local models.""" |
| with patch('transformers.pipeline') as mock: |
| mock_pipeline = Mock() |
| mock_pipeline.return_value = [{"label": "POSITIVE", "score": 0.99}] |
| mock.return_value = mock_pipeline |
| yield mock_pipeline |
| ``` |
|
|
| #### 5.2 Code Quality Tools |
|
|
| ```bash |
| # Add quality tools |
| pixi add ruff mypy black isort |
| ``` |
|
|
| **Set Up:** |
| - Linting with ruff |
| - Type checking with mypy |
| - Code formatting with black |
| - Import sorting with isort |
|
|
| **Create `pyproject.toml` configuration (use Copilot):** |
|
|
| ```toml |
| [tool.ruff] |
| line-length = 100 |
| target-version = "py311" |
| |
| [tool.mypy] |
| python_version = "3.11" |
| strict = true |
| |
| [tool.black] |
| line-length = 100 |
| ``` |
|
|
| --- |
|
|
| ### Phase 6: Package Publishing with Pixi (Week 9) |
|
|
| #### 6.1 Preparing for Publication |
|
|
| **Project Structure:** |
|
|
| ``` |
| my-cli-tool/ |
| βββ pixi.toml # Pixi configuration |
| βββ pyproject.toml # Python package metadata |
| βββ README.md # Documentation |
| βββ LICENSE # License file |
| βββ src/ |
| β βββ my_cli_tool/ |
| β βββ __init__.py |
| β βββ cli.py |
| β βββ ... |
| βββ tests/ |
| β βββ test_*.py |
| βββ docs/ |
| βββ ... |
| ``` |
|
|
| **Configure `pyproject.toml` for Publishing:** |
|
|
| ```toml |
| [build-system] |
| requires = ["hatchling"] |
| build-backend = "hatchling.build" |
| |
| [project] |
| name = "my-cli-tool" |
| version = "0.1.0" |
| description = "AI-powered file organization CLI" |
| authors = [{name = "Your Name", email = "you@example.com"}] |
| readme = "README.md" |
| requires-python = ">=3.11" |
| dependencies = [ |
| "typer>=0.9", |
| "rich>=13.0", |
| "transformers>=4.30", |
| "huggingface-hub>=0.16", |
| ] |
| |
| [project.scripts] |
| my-cli = "my_cli_tool.cli:cli" |
| |
| [project.urls] |
| Homepage = "https://github.com/yourusername/my-cli-tool" |
| Documentation = "https://my-cli-tool.readthedocs.io" |
| ``` |
|
|
| **Use Copilot to:** |
| - Generate comprehensive README with usage examples |
| - Create CHANGELOG.md |
| - Write contributing guidelines |
| - Generate documentation |
|
|
| #### 6.2 Building and Publishing |
|
|
| **Build Package:** |
|
|
| ```bash |
| # Add build tools |
| pixi add hatchling build twine |
| |
| # Build the package |
| pixi run python -m build |
| |
| # This creates: |
| # - dist/my_cli_tool-0.1.0.tar.gz |
| # - dist/my_cli_tool-0.1.0-py3-none-any.whl |
| ``` |
|
|
| **Publish to PyPI:** |
|
|
| ```bash |
| # Test on TestPyPI first |
| pixi run twine upload --repository testpypi dist/* |
| |
| # Then publish to PyPI |
| pixi run twine upload dist/* |
| ``` |
|
|
| **Publish as Pixi Package:** |
|
|
| ```bash |
| # Create pixi.toml with package metadata |
| pixi project init --name my-cli-tool |
| |
| # Add to pixi.toml: |
| [project] |
| name = "my-cli-tool" |
| version = "0.1.0" |
| description = "AI-powered file organization CLI" |
| channels = ["conda-forge"] |
| platforms = ["linux-64", "osx-64", "win-64"] |
| |
| [dependencies] |
| python = ">=3.11" |
| typer = ">=0.9" |
| rich = ">=13.0" |
| |
| [tasks] |
| start = "my-cli" |
| ``` |
|
|
| **Resources:** |
| - [Python Packaging Guide](https://packaging.python.org/) |
| - [Pixi Publishing Guide](https://pixi.sh/latest/advanced/publishing/) |
| - [Semantic Versioning](https://semver.org/) |
|
|
| --- |
|
|
| ### Phase 7: Real-World Project (Week 10-12) |
|
|
| #### 7.1 Choose a Project from the Ideas List |
|
|
| **Comprehensive Example Project:** |
|
|
| **[FileOrganizer](projects/FileOrganizer.md)** - AI-Powered File Organization CLI |
| - **What it demonstrates**: Complete integration of all concepts from this learning path |
| - **Key technologies**: Docker Model Runner, MCP servers, CrewAI multi-agent system, Typer CLI |
| - **Complexity**: Advanced |
| - **Best for**: Learners who have completed Phases 1-6 and want to see a production-ready example |
| - **Features**: |
| - Multi-agent system (Scanner, Classifier, Organizer, Deduplicator) |
| - Docker-based LLM deployment |
| - MCP server for file operations |
| - Research paper management with metadata extraction |
| - Comprehensive CLI with multiple commands |
| - **Learning outcomes**: See how Docker AI, MCP, multi-agent systems, and CLI development work together in a real project |
|
|
| **Recommended Starter Projects:** |
|
|
| 1. **smart-csv** (Data & Analytics) |
| - Good for: Learning data manipulation |
| - Key skills: Pandas, CSV processing, LLM integration |
| - Complexity: Medium |
|
|
| 2. **smart-summarize** (Document Processing) |
| - Good for: Text processing and AI integration |
| - Key skills: File I/O, API integration, prompt engineering |
| - Complexity: Low-Medium |
|
|
| 3. **error-translator** (DevOps) |
| - Good for: String processing and knowledge retrieval |
| - Key skills: Pattern matching, API usage, caching |
| - Complexity: Medium |
|
|
| 4. **task-prioritizer** (Productivity) |
| - Good for: Building practical tools |
| - Key skills: Data structures, AI reasoning, persistence |
| - Complexity: Medium |
|
|
| > **π‘ Tip**: Start with one of the simpler projects (2-4) to build confidence, then tackle FileOrganizer to see how all the concepts integrate in a production-ready application. |
|
|
| #### 7.2 Development Workflow with GitHub Copilot |
|
|
| **Step-by-Step Process:** |
|
|
| 1. **Planning Phase:** |
| - Use Copilot Chat to brainstorm features |
| - Generate project structure |
| - Create initial documentation |
|
|
| 2. **Implementation Phase:** |
| - Use Copilot for boilerplate code |
| - Ask Copilot to explain unfamiliar concepts |
| - Generate test cases alongside code |
|
|
| 3. **Refinement Phase:** |
| - Use Copilot to suggest optimizations |
| - Generate documentation and examples |
| - Create user guides |
|
|
| **Effective Copilot Prompts:** |
|
|
| ```python |
| # In comments, be specific: |
| # "Create a function that reads a CSV file, analyzes column types, |
| # and returns a dictionary with column names as keys and suggested |
| # data types as values. Handle errors gracefully." |
| |
| # Use descriptive function names: |
| def analyze_csv_column_types(filepath: str) -> dict[str, str]: |
| # Copilot will suggest implementation |
| pass |
| |
| # Ask for explanations: |
| # "Explain how to use asyncio to make concurrent API calls with rate limiting" |
| ``` |
|
|
| #### 7.3 Project Milestones |
|
|
| **Week 10: MVP (Minimum Viable Product)** |
| - [ ] Core functionality working |
| - [ ] Basic CLI interface |
| - [ ] Simple AI integration |
| - [ ] README with usage examples |
|
|
| **Week 11: Enhancement** |
| - [ ] Add configuration system |
| - [ ] Implement error handling |
| - [ ] Add progress indicators |
| - [ ] Write tests (>70% coverage) |
|
|
| **Week 12: Polish & Publish** |
| - [ ] Complete documentation |
| - [ ] Add examples and tutorials |
| - [ ] Set up CI/CD (GitHub Actions) |
| - [ ] Publish to PyPI |
| - [ ] Share on GitHub/social media |
|
|
| --- |
|
|
| ## π οΈ Essential Pixi Commands Reference |
|
|
| ```bash |
| # Project initialization |
| pixi init my-project |
| pixi init --channel conda-forge --channel bioconda |
| |
| # Dependency management |
| pixi add package-name # Add runtime dependency |
| pixi add --dev pytest # Add dev dependency |
| pixi add "package>=1.0,<2.0" # Version constraints |
| pixi remove package-name # Remove dependency |
| pixi update # Update all dependencies |
| |
| # Environment management |
| pixi shell # Activate environment |
| pixi run python script.py # Run command in environment |
| pixi run --environment prod start # Run in specific environment |
| |
| # Task management |
| pixi task add start "python -m my_cli" |
| pixi task add test "pytest tests/" |
| pixi task add lint "ruff check src/" |
| pixi run start # Run defined task |
| |
| # Multi-environment setup |
| [feature.dev.dependencies] |
| pytest = "*" |
| ruff = "*" |
| |
| [environments] |
| default = ["dev"] |
| prod = [] |
| ``` |
|
|
| --- |
|
|
| ## π Learning Resources |
|
|
| ### Documentation |
| - [Pixi Official Docs](https://pixi.sh/latest/) |
| - [Python Packaging Guide](https://packaging.python.org/) |
| - [Click Documentation](https://click.palletsprojects.com/) |
| - [OpenAI API Reference](https://platform.openai.com/docs/) |
| - [Docker AI Documentation](https://docs.docker.com/ai/) |
| - [Docker Compose Models Reference](https://docs.docker.com/ai/compose/models-and-compose/) |
| - [Docker MCP Gateway](https://github.com/docker/mcp-gateway/) |
| - [Docker MCP Catalog](https://hub.docker.com/mcp) |
|
|
| ### Tutorials & Courses |
| - [Real Python: Building CLI Applications](https://realpython.com/command-line-interfaces-python-argparse/) |
| - [GitHub Copilot Learning Path](https://github.com/skills/copilot) |
| - [LangChain Tutorials](https://python.langchain.com/docs/tutorials/) |
|
|
| ### Example Projects |
| - [Typer Examples](https://github.com/tiangolo/typer/tree/master/docs_src) |
| - [Rich Examples](https://github.com/Textualize/rich/tree/master/examples) |
| - [AI CLI Tools on GitHub](https://github.com/topics/ai-cli) |
|
|
| ### Community |
| - [Python Discord](https://discord.gg/python) |
| - [r/Python](https://reddit.com/r/Python) |
| - [Pixi GitHub Discussions](https://github.com/prefix-dev/pixi/discussions) |
|
|
| --- |
|
|
| ## π‘ Tips for Success |
|
|
| ### Using GitHub Copilot Effectively |
|
|
| 1. **Write Clear Comments:** |
| ```python |
| # Create a function that takes a list of file paths, |
| # sends them to GPT-4 for analysis, and returns |
| # a structured JSON response with organization suggestions |
| ``` |
|
|
| 2. **Use Descriptive Names:** |
| - Good: `analyze_and_categorize_files()` |
| - Bad: `process()` |
|
|
| 3. **Break Down Complex Tasks:** |
| - Don't ask Copilot to generate entire applications |
| - Build incrementally, function by function |
|
|
| 4. **Review and Understand:** |
| - Always review Copilot's suggestions |
| - Understand the code before accepting it |
| - Test thoroughly |
|
|
| 5. **Use Copilot Chat for:** |
| - Explaining error messages |
| - Suggesting alternative approaches |
| - Generating test cases |
| - Writing documentation |
|
|
| ### Pixi Best Practices |
|
|
| 1. **Use Feature Flags:** |
| ```toml |
| [feature.ai] |
| dependencies = {openai = "*", anthropic = "*"} |
| |
| [feature.dev] |
| dependencies = {pytest = "*", ruff = "*"} |
| |
| [environments] |
| default = ["ai"] |
| dev = ["ai", "dev"] |
| ``` |
|
|
| 2. **Define Tasks:** |
| ```toml |
| [tasks] |
| dev = "python -m my_cli --debug" |
| test = "pytest tests/ -v" |
| lint = "ruff check src/" |
| format = "black src/ tests/" |
| ``` |
|
|
| 3. **Lock Dependencies:** |
| - Commit `pixi.lock` to version control |
| - Ensures reproducible builds |
|
|
| 4. **Use Channels Wisely:** |
| - Start with `conda-forge` |
| - Add specialized channels as needed |
|
|
| ### Development Workflow |
|
|
| 1. **Start Small:** |
| - Build the simplest version first |
| - Add features incrementally |
| - Test each addition |
|
|
| 2. **Iterate Based on Feedback:** |
| - Share early with friends/colleagues |
| - Gather feedback |
| - Improve based on real usage |
|
|
| 3. **Document as You Go:** |
| - Write docstrings immediately |
| - Update README with new features |
| - Keep CHANGELOG current |
|
|
| 4. **Test Continuously:** |
| - Write tests alongside code |
| - Run tests before committing |
| - Aim for >80% coverage |
|
|
| --- |
|
|
| ## π― Success Metrics |
|
|
| By the end of this learning path, you should be able to: |
|
|
| - β
Set up a Python project with pixi |
| - β
Build a CLI application with commands and options |
| - β
Integrate AI/LLM capabilities effectively |
| - β
Write tests and maintain code quality |
| - β
Publish a package to PyPI |
| - β
Use GitHub Copilot to accelerate development |
| - β
Build one complete AI-powered CLI tool |
|
|
| --- |
|
|
| ## π
Next Steps |
|
|
| After completing this learning path: |
|
|
| 1. **Build More Projects:** |
| - Try different project ideas from the list |
| - Experiment with different AI models |
| - Contribute to open-source CLI tools |
|
|
| 2. **Advanced Topics:** |
| - Plugin architectures |
| - Multi-command CLIs |
| - Database integration |
| - Web dashboards for CLI tools |
| - CI/CD automation |
|
|
| 3. **Share Your Work:** |
| - Write blog posts about your projects |
| - Create video tutorials |
| - Contribute to the community |
| - Help others learn |
|
|
| --- |
|
|
| *Last Updated: 2024-12-04* |
|
|