### Toy examples docstring for read_note function Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md Shows minimal illustrative calls that are unrealistic, demonstrating how not to guide the agent. Highlights the need for realistic paths and proper usage examples. ```Python """Examples: read_note("test.md") read_note("foo.md", response_format="detailed") """ ``` -------------------------------- ### Starting FastAPI Server with Uvicorn Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Commands to run the AI coach agent API server using `uvicorn`. Demonstrates starting the server with default and custom ports, using `python -m`, and configuring for production with specific host and worker settings. Includes example endpoints for health check and the agent. ```bash # Standard development server (default port 8030) uv run uvicorn src.main:app --host 127.0.0.1 --port 8030 --reload # Custom port uv run uvicorn src.main:app --host 127.0.0.1 --port 8080 --reload # Using python -m uv run python -m src.main # Production mode (listen on all interfaces) uv run uvicorn src.main:app --host 0.0.0.0 --port 8030 # With workers for production uv run uvicorn src.main:app --host 0.0.0.0 --port 8030 --workers 4 # Access the API: # Health check: GET http://localhost:8030/health # Agent endpoint: POST http://localhost:8030/api/pydantic-agent ``` -------------------------------- ### Realistic examples docstring for read_note function Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md Provides concrete usage examples with realistic file paths and response_format options, guiding the agent on proper invocation of the read_note tool. ```Python """Examples: # Check daily note metadata read_note("daily/2025-01-15.md", response_format="minimal") # Get project overview before update read_note("projects/website-redesign.md", response_format="concise") """ ``` -------------------------------- ### Example .env.example for YouTube RAG Pipeline Configuration Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Provides an example `.env.example` file demonstrating the required environment variables for configuring the YouTube RAG pipeline, including Supabase API keys, YouTube channel ID, processing parameters, and embedding settings. ```bash # YouTube RAG Pipeline SUPADATA_API_KEY=your_supadata_key_here YOUTUBE_CHANNEL_ID=UCxxxxxxxxxxxxx YOUTUBE_DAYS_BACK=7 YOUTUBE_MAX_RETRIES=1 YOUTUBE_BATCH_SIZE=5 # Chunking (token-based) MIN_CHUNK_TOKENS=400 MAX_CHUNK_TOKENS=1000 ``` -------------------------------- ### CLI usage examples for YouTube RAG pipeline Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Example commands for running the YouTube RAG pipeline CLI with different configurations. Shows basic usage with environment variables, channel ID override, and custom days back parameter. Uses uv run for Python execution in a virtual environment context. ```bash # Use env vars uv run python -m src.rag_pipeline.cli # Override channel uv run python -m src.rag_pipeline.cli --channel-id UCxxxxx # Custom days back uv run python -m src.rag_pipeline.cli --days-back 14 ``` -------------------------------- ### Add YouTube RAG Pipeline to README Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Integrates a section about the YouTube RAG pipeline into the project's main README file. It highlights features, provides a quick start guide, and links to detailed documentation. ```markdown ## YouTube RAG Pipeline Automatically fetches YouTube video transcripts, chunks them intelligently, and stores in vector database for semantic search by the AI coach. **Features:** - Fetch transcripts from YouTube channel with timestamps - Token-aware hybrid chunking (400-1000 tokens) - Configurable embedding provider (OpenAI/Ollama) - Vector storage in Supabase with pgvector - CLI and programmatic interfaces - Retry logic and error handling **Quick Start:** ```bash # Setup environment variables (see .env.example) # Run database migration (see docs/youtube-rag-pipeline.md) # Process channel videos uv run python -m src.rag_pipeline.cli ``` See [docs/youtube-rag-pipeline.md](docs/youtube-rag-pipeline.md) for full documentation. ``` -------------------------------- ### Python Specific Affirmative Guidance Example Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md An example of specific affirmative guidance in a docstring. This improves upon vague guidance by clearly outlining the precise actions the tool can perform, aiding AI agent comprehension. ```python """Use this when you need to: - Read the content of a single known note - Extract metadata from frontmatter for a specific file - Verify a note exists at a specific path """ ``` -------------------------------- ### Fragmented tool usage example Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md Demonstrates separate low-level tool calls (read_note, patch_note, update_metadata) that require the agent to orchestrate multiple steps, illustrating a less efficient approach. ```Python read_note(path) # Tool 1 patch_note(path, old, new) # Tool 2 update_metadata(path, metadata) # Tool 3 # Agent must call 3+ tools for simple "update note" task ``` -------------------------------- ### Verify Supabase Table and Vector Extension Setup Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md SQL queries to verify the creation of essential tables (`channels`, `videos`, `transcript_chunks`) and the enablement of the `vector` extension in Supabase, ensuring the database is ready for RAG operations. ```sql -- Verify tables created SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN ('channels', 'videos', 'transcript_chunks'); -- Verify vector extension enabled SELECT * FROM pg_extension WHERE extname = 'vector'; ``` -------------------------------- ### Consolidated note management example Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md Shows a unified obsidian_note_manage function that handles read, update, patch, and append operations in a single call, promoting efficient tool usage and reducing orchestration complexity. ```Python obsidian_note_manage( path=path, operation="patch", # or "read", "update", "append" find_replace=(old, new), metadata_updates=metadata ) # Agent does everything in one call ``` -------------------------------- ### Environment Configuration File (.env) Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Example structure for the `.env` file, detailing all required environment variables for the YouTube RAG pipeline, chunking settings, embedding and LLM providers, Supabase configuration, and agent settings. Replace placeholder values with your actual API keys and configuration. ```bash # .env file structure # YouTube RAG Pipeline Configuration SUPADATA_API_KEY=your_supadata_key_here YOUTUBE_CHANNEL_ID=UCxxxxxxxxxxxxx YOUTUBE_DAYS_BACK=7 YOUTUBE_MAX_RETRIES=1 YOUTUBE_BATCH_SIZE=5 # Chunking Settings MIN_CHUNK_TOKENS=400 MAX_CHUNK_TOKENS=1000 # Embedding Provider (openai, ollama, or openrouter) EMBEDDING_PROVIDER=openai EMBEDDING_BASE_URL=https://api.openai.com/v1 EMBEDDING_API_KEY=sk-your-api-key-here EMBEDDING_MODEL_CHOICE=text-embedding-3-small # Supabase Configuration SUPABASE_URL=https://your-project.supabase.co SUPABASE_SERVICE_KEY=your-service-key-here # LLM Provider Configuration LLM_PROVIDER=openai LLM_BASE_URL=https://api.openai.com/v1 LLM_API_KEY=sk-your-api-key-here LLM_CHOICE=gpt-4o-mini # Agent Settings MAX_TRANSCRIPT_CHARS=20000 API_PORT=8030 RATE_LIMIT_REQUESTS=5 ENVIRONMENT=development ``` -------------------------------- ### Install Dependencies for YouTube RAG Pipeline Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Installs or synchronizes project dependencies using the 'uv' package manager. This command ensures all necessary libraries for the RAG pipeline are present and up-to-date. ```bash uv sync ``` -------------------------------- ### Python Agent Tool Docstring Template Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md This template defines a structured docstring for Python functions decorated as agent tools, guiding LLMs on when and how to use the tool. It includes sections for tool selection scenarios, parameter guidance, returns, performance notes, and examples to enable efficient composition in workflows. Dependencies include an agent framework with RunContext and @agent.tool decorator; inputs are parameters like ctx, param1; outputs are strings in specified formats; limitations cover token usage and resource constraints. ```python @agent.tool async def tool_name( ctx: RunContext[AgentDependencies], param1: str, param2: int = 10, response_format: str = "concise" ) -> str: """[One-line summary of what this tool does]. Use this when you need to: - [Specific scenario 1 where this tool is the right choice] - [Specific scenario 2] - [Specific scenario 3] Do NOT use this for: - [Scenario where OTHER_TOOL should be used instead] - [Scenario where ANOTHER_TOOL should be used instead] - [Anti-pattern or common misuse] Args: param1: [Standard description] Use this to [explain purpose and when to vary it]. param2: [Standard description]. Range: 1-100. - Small values (1-10): [use case] - Medium values (10-50): [use case] - Large values (50+): [use case and warnings] response_format: Control output verbosity and token usage. - "minimal": [Description] (~50 tokens, use when [scenario]) - "concise": [Description] (~150 tokens, default, balanced) - "detailed": [Description] (~1500+ tokens, use sparingly when [scenario]) Returns: [Description of return value]. Format: [Structure/format details that help agent parse]. Performance Notes: - Minimal format: ~50 tokens (use for [scenario]) - Concise format: ~150 tokens (default, good for most cases) - Detailed format: ~1500+ tokens (only when full content needed) - Typical execution time: [duration] for [scenario] - Max [resource limit]: [value] ([what happens if exceeded]) - [Other performance characteristics] Examples: # [Brief description of what this example shows] tool_name( param1="projects/alpha.md", param2=5, response_format="minimal" ) # [Description of complex case] tool_name( param1="research/ai-overview.md", param2=50, response_format="detailed" ) # [Description of edge case or important variation] tool_name( param1="inbox/quick-note.md", param2=1, response_format="concise" ) """ ``` -------------------------------- ### Running Project Tests with Pytest Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Commands to execute the test suite using `pytest`. Shows how to run all tests, filter by markers (unit, integration), run specific test files or modules, and generate a coverage report. Includes an example of the test execution output. ```bash # Run all tests with verbose output uv run pytest tests/ -v # Run only unit tests uv run pytest tests/ -v -m unit # Run integration tests uv run pytest tests/ -m integration # Run specific test file uv run pytest tests/agent/test_config.py -v # Run with coverage report uv run pytest tests/ --cov=src --cov-report=html # Run tests for specific module uv run pytest tests/tools/rag_tools/ -v # Example output: # tests/agent/test_config.py::test_get_model PASSED [ 25%] # tests/agent/test_config.py::test_get_rate_limit PASSED [ 50%] ``` -------------------------------- ### Supabase + pgvector Setup and Best Practices Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Guidance on setting up Supabase with the pgvector extension for storing and querying embeddings, including recommended indexing strategies and client library usage. ```APIDOC ## Supabase + pgvector Setup ### Description This section provides instructions for setting up Supabase with the `pgvector` extension to serve as a vector database. It covers database configuration, indexing, and client-side interaction best practices. ### Extension Setup 1. **Enable pgvector**: Activate the `pgvector` extension within your Supabase project dashboard. 2. **Create tables**: Define tables that include a `vector` column with the appropriate dimension (e.g., `vector(384)` for MiniLM, `vector(1536)` for OpenAI). 3. **Create indexes**: Implement vector indexes like `IVFFlat` or `HNSW` to optimize similarity search performance. 4. **Utilize RPC functions**: Define and use Remote Procedure Call (RPC) functions for efficient vector similarity queries. ### Python Client Options - **`supabase-py`**: The official Python client library for interacting with Supabase. - **`vecs`**: A higher-level Python client specifically designed for Supabase's vector capabilities. - **Direct SQL (e.g., `psycopg2`)**: For complex queries or fine-grained control over database interactions. ### Best Practices - **Indexing**: Use `ivfflat` indexes, often with `lists` set to the square root of the number of rows, for a balance between performance and memory usage. - **Vector Dimensions**: Ensure the `vector` dimension matches your embedding model's output (e.g., 384 for `all-MiniLM-L6-v2`, 1536 for OpenAI `text-embedding-ada-002`). - **Metadata Storage**: Store associated metadata (like video URL, timestamps) in a `JSONB` column for flexible filtering and querying. - **Security**: Implement Row Level Security (RLS) policies in Supabase to control data access. - **Performance**: Employ connection pooling for your database connections to enhance application performance, especially under high load. ``` -------------------------------- ### Python Vague Affirmative Guidance Example Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md An example of vague affirmative guidance in a docstring. This type of guidance is insufficient for AI agents as it lacks specificity regarding the tool's exact purpose and scope. ```python """Use this when you need to work with notes.""" ``` -------------------------------- ### Ollama Local Embedding Setup Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/SETUP_GUIDE.md Shell commands and configuration for setting up local embeddings using Ollama. This approach replaces OpenAI embeddings with local processing. The setup includes pulling the nomic-embed-text model and configuring environment variables for local inference. ```bash ollama pull nomic-embed-text ``` -------------------------------- ### Tool execution logging pattern Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/logging_guide.md Complete pattern for logging tool execution including start, completion, and failure scenarios. Include tool name, parameters, duration, and retry information for proper debugging and monitoring. ```python logger.info("tool_execution_started", tool=name, params=params) try: result = await tool.execute(params) logger.info("tool_execution_completed", tool=name, duration_ms=duration) except ToolError: logger.exception("tool_execution_failed", tool=name, retry_count=count) raise ``` -------------------------------- ### Google-Style Docstring Example in Python Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/CLAUDE.md This snippet demonstrates the required Google-style docstring format for functions in the project. It includes type annotations for parameters and return types, descriptions of arguments, return value, and possible exceptions raised. Used to ensure consistent and comprehensive documentation across all code. ```python def process_request(user_id: str, query: str) -> dict[str, Any]: """Process a user request and return results. Args: user_id: Unique identifier for the user. query: The search query string. Returns: Dictionary containing results and metadata. Raises: ValueError: If query is empty or invalid. ProcessingError: If processing fails after retries. """ ``` -------------------------------- ### Python Agent-Optimized Docstring for Obsidian Note Reading Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md An agent-optimized Python tool docstring using the `@agent.tool` decorator. It provides explicit guidance on when and when NOT to use the tool, detailed parameter descriptions with usage scenarios, performance notes on token usage and execution time, and realistic examples. ```python @agent.tool async def obsidian_note_read( ctx: RunContext[AgentDependencies], path: str, response_format: str = "concise" ) -> str: """Read a single note from the Obsidian vault with token-efficient formatting. Use this when you need to: - View the content of a SPECIFIC note you already know the path to - Check metadata (tags, status, dates) from frontmatter - Verify a note exists before performing other operations - Read content to inform a follow-up action (update, summarize) Do NOT use this for: - Finding notes (use obsidian_vault_query with search instead) - Reading MULTIPLE notes at once (use obsidian_vault_query with batch mode) - Analyzing note relationships (use obsidian_graph_analyze instead) - Just checking if a note exists (use response_format="minimal") Args: path: Relative path from vault root. Examples: "daily/2025-01-15.md", "projects/alpha.md", "inbox/ideas.md" Do NOT include vault path - just the relative path within the vault. response_format: Control output verbosity to save tokens. - "minimal": Title, tags, summary only (~50 tokens) Use when: Just need to check metadata or verify existence - "concise": Key metadata + content preview (~150 tokens) Use when: Need overview before deciding next action (DEFAULT) - "detailed": Full content with all frontmatter (~1500+ tokens) Use when: Need complete content for summarization or analysis Returns: Formatted markdown string with note content. Minimal: Title, tags, modified date Concise: Above + first 100 words of content Detailed: Full content with complete frontmatter section Performance Notes: - Minimal format: ~50 tokens (recommended for metadata checks) - Concise format: ~150 tokens (default, good balance) - Detailed format: ~1500+ tokens (use only when truly needed) - Execution time: 10-50ms for typical notes - Max file size: 10MB (raises error if exceeded) - Always prefer concise over detailed to conserve tokens Examples: # Check if daily note exists and get its tags (minimal) obsidian_note_read( path="daily/2025-01-15.md", response_format="minimal" ) # Get overview of project note before updating (concise - default) obsidian_note_read( path="projects/website-redesign.md", response_format="concise" ) # Read full research note for comprehensive analysis (detailed) obsidian_note_read( path="research/ai-safety-overview.md", response_format="detailed" ) # Quick metadata check on meeting notes obsidian_note_read( path="meetings/2025-01-15-standup.md", response_format="minimal" ) """ ``` -------------------------------- ### Structured Logging with Custom Logger Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Demonstrates structured logging implementation using a custom logger utility. Imports get_logger to create a module-specific logger instance and shows examples of info and exception logging with contextual data. Supports JSON-formatted structured logs for better observability. ```python from src.utils.logging import get_logger logger = get_logger(__name__) logger.info("video_processing_started", video_id="abc123", title="Test Video") logger.exception("transcript_fetch_failed", video_id=video_id, error_type=type(e).__name__) ``` -------------------------------- ### Integration Tests for RAG Pipeline in Python Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md This Python code snippet demonstrates integration testing for the full YouTube RAG Pipeline, from fetching videos to storage. It uses pytest and asyncio for asynchronous testing, with dependencies on the pipeline class, configuration, and external clients. Inputs include mocked API responses and configuration parameters; outputs are assertions on processing results like total videos processed. Limitations include the need for mocked external calls and specific test client setups. ```python import pytest from src.rag_pipeline.pipeline import YouTubeRAGPipeline from src.rag_pipeline.config import YouTubeRAGConfig @pytest.mark.integration @pytest.mark.asyncio async def test_pipeline_end_to_end(test_supabase_client, test_embedding_client): """Test full pipeline from video fetch to storage.""" config = YouTubeRAGConfig( supadata_api_key="test_key", youtube_channel_id="test_channel", days_back=7, max_retries=1, min_tokens=100, max_tokens=500 ) pipeline = YouTubeRAGPipeline(config) # Mock external API calls with patch.object(pipeline.youtube_service, 'get_recent_videos') as mock_videos: mock_videos.return_value = [/* test video data */] result = await pipeline.process_channel() assert result.total_videos > 0 # Add more assertions ``` -------------------------------- ### Run linting and type checking commands with uv and ruff Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt These Bash commands execute the ruff linter and mypy type checker on the project's source code using uv. They help maintain code quality by detecting style issues, unused variables, and type errors. The commands can be run individually or combined, and output examples illustrate both success and failure scenarios. ```bash # Run ruff linter\nuv run ruff check src/\n\n# Auto-fix linting issues\nuv run ruff check --fix src/\n\n# Run mypy type checker\nuv run mypy src/\n\n# Run both checks together\nuv run ruff check src/ && uv run mypy src/\n\n# Example output (success):\n# All checks passed!\n#\n# Success: no issues found in 42 source files\n\n# Example output (issues found):\n# src/agent/agent.py:45:12: error: Missing return statement [return-value]\n# src/tools/rag_tools/service.py:89:5: F841 Local variable `result` is assigned to but never used\n# Found 2 errors in 2 files (checked 42 source files) ``` -------------------------------- ### Initialize and Run YouTube RAG Pipeline (Python) Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Demonstrates how to initialize the YouTube RAG pipeline with default or custom configurations and run the complete video processing workflow. It accesses results such as processed videos, created chunks, and any errors encountered. Dependencies include the pipeline and config modules. ```python from src.rag_pipeline.pipeline import YouTubeRAGPipeline from src.rag_pipeline.config import get_config # Initialize pipeline with default config from environment pipeline = YouTubeRAGPipeline() # Or with custom configuration config = get_config() config.days_back = 14 config.batch_size = 10 pipeline = YouTubeRAGPipeline(config) # Run the complete pipeline result = await pipeline.process_channel() # Access results print(f"Processed {result.processed} out of {result.total_videos} videos") print(f"Created {result.chunks_created} transcript chunks") print(f"Failed: {result.failed}, Skipped: {result.skipped}") if result.errors: print("Errors encountered:") for error in result.errors: print(f" - {error}") ``` -------------------------------- ### GET /health Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-ai-coach-agent.md Provides the health status of the API server and its services. ```APIDOC ## GET /health ### Description This endpoint checks and returns the overall health status of the API server and its integrated services. ### Method GET ### Endpoint /health ### Parameters None ### Request Example None ### Response #### Success Response (200) - **status** (string) - The overall health status (e.g., "ok"). - **timestamp** (string) - The timestamp when the health check was performed. - **services** (object) - An object containing the health status of individual services. #### Response Example ```json { "status": "ok", "timestamp": "2023-10-27T10:00:00Z", "services": { "database": "ok", "llm": "ok" } } ``` ``` -------------------------------- ### GET /health Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Health check endpoint that returns service status and client initialization state. Useful for monitoring and debugging. ```APIDOC ## GET /health ### Description Health check endpoint that returns service status and client initialization state. ### Method GET ### Endpoint /health ### Response #### Success Response (200) - **status** (string) - Service status ("healthy" or "unhealthy") - **timestamp** (string) - Current timestamp in ISO format - **services** (object) - Key-value pairs of service names and their initialization status #### Response Example { "status": "healthy", "timestamp": "2025-01-15T10:30:45.123456+00:00", "services": { "embedding_client": true, "supabase": true, "http_client": true, "title_agent": true } } ``` -------------------------------- ### Structured logging with keyword arguments Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/logging_guide.md Demonstrate proper structured logging using keyword arguments instead of string formatting. Always use snake_case event names that describe what happened, including context like IDs, input values, and performance metrics. ```python logger.info("database_connection_established", connection_id="conn-123", duration_ms=45.2) logger.info("tool_execution_started", tool="data_processor", params={"format": "json"}) logger.info("api_request_completed", endpoint="/v1/users", status=200, duration_ms=234.5) # ❌ WRONG - no string formatting # logger.info(f"User {user_id} created") # ✅ CORRECT - structured kwargs logger.info("user_created", user_id="123", role="admin") ``` -------------------------------- ### YouTube RAG Pipeline CLI Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Command-line interface for running the complete YouTube transcript processing pipeline with various configuration options. ```APIDOC ## YouTube RAG Pipeline CLI ### Description Command-line interface for running the complete YouTube transcript processing pipeline. ### Usage uv run python -m src.rag_pipeline.cli [options] ### Parameters #### Options - **--channel-id** (string) - Optional - Override default YouTube channel ID - **--days-back** (integer) - Optional - Number of days to look back for videos (default: 7) - **--dry-run** (flag) - Optional - Run pipeline without writing to database ### Output - Channel configuration details - Processing progress - Summary statistics (videos processed, chunks created) - Error reports ### Example Output ============================================ YouTube RAG Pipeline ============================================ Channel ID: UCxxxxxxxxxxxxx Days back: 7 Embedding provider: openai Embedding model: text-embedding-3-small Chunk size: 400-1000 tokens ============================================ [Processing videos...] ============================================ Pipeline Results ============================================ Total videos found: 12 Successfully processed: 10 Failed: 1 Skipped (already processed): 1 Total chunks created: 234 Errors encountered: ❌ abc123xyz: Transcript unavailable ============================================ ``` -------------------------------- ### Set up environment configuration module Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Python script to create a configuration module for the RAG pipeline, including loading environment variables using python-dotenv. This module will manage configuration values such as API keys and database connection strings. ```python from dotenv import load_dotenv import os # Load environment variables from .env file load_dotenv() class Config: # Supabase configuration SUPABASE_URL = os.getenv('SUPABASE_URL') SUPABASE_KEY = os.getenv('SUPABASE_KEY') # YouTube API configuration YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY') # Embedding model configuration EMBEDDING_MODEL = os.getenv('EMBEDDING_MODEL', 'all-MiniLM-L6-v2') EMBEDDING_DIMENSION = int(os.getenv('EMBEDDING_DIMENSION', 384)) # Processing configuration MAX_RETRIES = int(os.getenv('MAX_RETRIES', 3)) PROCESSING_BATCH_SIZE = int(os.getenv('PROCESSING_BATCH_SIZE', 10)) # Logging configuration LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO') ``` -------------------------------- ### Configure Embedding Client with Environment Variables Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Initializes an AsyncOpenAI client for embeddings based on environment configuration. Supports multiple providers (OpenAI, Ollama) with provider-specific handling. Returns a configured client instance ready for embedding operations. ```python def get_agent_clients(): embedding_provider = os.getenv('EMBEDDING_PROVIDER', 'openai') base_url = os.getenv('EMBEDDING_BASE_URL', 'https://api.openai.com/v1') api_key = os.getenv('EMBEDDING_API_KEY') if embedding_provider == 'ollama': # Special handling for Ollama embedding_client = AsyncOpenAI(base_url=base_url, api_key="ollama") else: embedding_client = AsyncOpenAI(base_url=base_url, api_key=api_key) return embedding_client ``` -------------------------------- ### Get Full Video Transcript (Python) Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt Retrieves the complete transcript for a given YouTube video ID by combining all its chunks. It requires a Supabase client and allows specifying a maximum character limit for truncation. Handles errors for invalid video IDs or missing data. ```python from src.tools.rag_tools.service import get_full_video_transcript from src.utils.clients import get_agent_clients # Initialize clients _, supabase = get_agent_clients() # Get full transcript by video ID video_id = "dQw4w9WgXcQ" transcript = await get_full_video_transcript( supabase=supabase, video_id=video_id, max_chars=20000 # Truncate if longer than 20k chars ) print(transcript) # Handle errors try: transcript = await get_full_video_transcript(supabase, "invalid_id") except Exception as e: print(f"Error: {e}") ``` -------------------------------- ### Create database schema with pgvector extension Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md SQL script to set up the database schema in Supabase, including enabling the pgvector extension and creating tables for channels, videos, and transcript chunks. Also includes indexes for performance optimization and a function for vector similarity search. ```sql -- Enable pgvector extension CREATE EXTENSION IF NOT EXISTS vector; -- Channels table CREATE TABLE IF NOT EXISTS channels ( id TEXT PRIMARY KEY, name TEXT NOT NULL, url TEXT, last_processed_at TIMESTAMPTZ, active BOOLEAN DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Videos table CREATE TABLE IF NOT EXISTS videos ( id TEXT PRIMARY KEY, channel_id TEXT REFERENCES channels(id) ON DELETE CASCADE, title TEXT NOT NULL, url TEXT NOT NULL, published_at TIMESTAMPTZ, duration_seconds INTEGER, status TEXT DEFAULT 'pending', -- pending, processing, completed, failed transcript_available BOOLEAN DEFAULT FALSE, error_message TEXT, retry_count INTEGER DEFAULT 0, processed_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Transcript chunks with embeddings CREATE TABLE IF NOT EXISTS transcript_chunks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), video_id TEXT REFERENCES videos(id) ON DELETE CASCADE, chunk_index INTEGER NOT NULL, text_content TEXT NOT NULL, start_offset_ms INTEGER, end_offset_ms INTEGER, duration_ms INTEGER, token_count INTEGER, embedding vector(384), -- Adjust dimension based on embedding model metadata JSONB DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(video_id, chunk_index) ); -- Indexes for performance CREATE INDEX IF NOT EXISTS idx_videos_channel_id ON videos(channel_id); CREATE INDEX IF NOT EXISTS idx_videos_status ON videos(status); CREATE INDEX IF NOT EXISTS idx_videos_published_at ON videos(published_at DESC); CREATE INDEX IF NOT EXISTS idx_chunks_video_id ON transcript_chunks(video_id); -- Vector similarity index (IVFFlat) CREATE INDEX IF NOT EXISTS idx_chunks_embedding ON transcript_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); -- RPC function for vector search CREATE OR REPLACE FUNCTION match_transcript_chunks( query_embedding vector(384), match_count INT DEFAULT 5, filter JSONB DEFAULT '{}'::jsonb ) RETURNS TABLE ( id UUID, video_id TEXT, text_content TEXT, start_offset_ms INTEGER, similarity FLOAT, metadata JSONB ) LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT tc.id, tc.video_id, tc.text_content, tc.start_offset_ms, 1 - (tc.embedding <=> query_embedding) AS similarity, tc.metadata FROM transcript_chunks tc WHERE CASE WHEN filter != '{}'::jsonb THEN tc.metadata @> filter ELSE TRUE END ORDER BY tc.embedding <=> query_embedding LIMIT match_count; END; $$; -- Row Level Security (optional but recommended) ALTER TABLE channels ENABLE ROW LEVEL SECURITY; ALTER TABLE videos ENABLE ROW LEVEL SECURITY; ALTER TABLE transcript_chunks ENABLE ROW LEVEL SECURITY; -- Example RLS policy (adjust based on your auth strategy) CREATE POLICY "Public read access" ON transcript_chunks FOR SELECT USING (true); ``` -------------------------------- ### Initialize YouTube RAG Pipeline Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Creates a pipeline orchestrator instance with configured services. Initializes YouTube, chunking, embedding, and storage services. Requires a YouTubeRAGConfig configuration object. Returns a configured pipeline ready for video processing. ```python from typing import Optional from .config import YouTubeRAGConfig, get_config from src.utils.logging import get_logger class YouTubeRAGPipeline: def __init__(self, config: Optional[YouTubeRAGConfig] = None): self.config = config or get_config() self.youtube_service = YouTubeService(self.config) self.chunking_service = ChunkingService(self.config) self.embedding_service = EmbeddingService(self.config) self.storage_service = StorageService(self.config) logger = get_logger(__name__) logger.info("pipeline_initialized", channel_id=self.config.youtube_channel_id) ``` -------------------------------- ### Import shared logger and basic usage Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/logging_guide.md Import the shared logger instance and demonstrate proper usage with appropriate log levels. Use debug for diagnostics, info for operations, warning for recoverable issues, and error for non-fatal problems. ```python from src.shared.logging import get_logger logger = get_logger(__name__) # Use appropriate log levels logger.debug("diagnostic_information", component="cache") logger.info("user_created", user_id="123", role="admin") logger.warning("retry_attempt", attempt=3, max_retries=5) logger.error("connection_failed", service="database") logger.exception("operation_failed", operation="process_data") ``` -------------------------------- ### YouTube RAG Pipeline CLI in Bash Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt This command-line script runs the YouTube transcript processing pipeline, fetching, chunking, and indexing videos. It uses uv to run Python modules with options like channel ID, days back, and dry run mode, outputting processing results and errors. Dependencies include uv and Python environment with configured .env; limitations include reliance on YouTube API for transcripts and potential failures for unavailable videos without built-in retries. ```bash # Basic usage - process last 7 days (from .env config) uv run python -m src.rag_pipeline.cli # Override channel ID uv run python -m src.rag_pipeline.cli --channel-id UCxxxxxxxxxxxxx # Process last 14 days of videos uv run python -m src.rag_pipeline.cli --days-back 14 # Dry run mode (no database writes) uv run python -m src.rag_pipeline.cli --dry-run # Example output: # ============================================================ # YouTube RAG Pipeline # ============================================================ # Channel ID: UCxxxxxxxxxxxxx # Days back: 7 # Embedding provider: openai # Embedding model: text-embedding-3-small # Chunk size: 400-1000 tokens # ============================================================ # # [Processing videos...] # # ============================================================ # Pipeline Results # ============================================================ # Total videos found: 12 # Successfully processed: 10 # Failed: 1 # Skipped (already processed): 1 # Total chunks created: 234 # # Errors encountered: # ❌ abc123xyz: Transcript unavailable # ============================================================ ``` -------------------------------- ### Python YouTube Service for Supadata API Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/requests/youtube-rag-pipeline.md Implements a YouTube Service to interact with the Supadata API for fetching video data. It supports retrieving recent videos from a given channel and fetching detailed transcripts with timestamped segments for a specific video. The service includes error handling for API requests and transcript unavailability, along with structured logging. It requires YouTubeRAGConfig for API key and Supadata client setup. ```python from supadata import Supadata from typing import List, Optional from .schemas import VideoMetadata, Transcript, TranscriptSegment from .config import YouTubeRAGConfig from src.utils.logging import get_logger from datetime import datetime, timedelta logger = get_logger(__name__) class YouTubeService: """Service for fetching YouTube data via Supadata API.""" def __init__(self, config: YouTubeRAGConfig): self.config = config self.client = Supadata(api_key=config.supadata_api_key) async def get_recent_videos( self, channel_id: str, days_back: int = 7 ) -> List[VideoMetadata]: """Fetch recent videos from channel. Args: channel_id: YouTube channel ID. days_back: Number of days to look back. Returns: List of video metadata objects. Raises: SupadataError: If API request fails. """ logger.info("fetching_channel_videos", channel_id=channel_id, days_back=days_back) try: # Fetch video IDs response = self.client.youtube.channel.videos( id=channel_id, type="video", limit=100 # Adjust based on channel upload frequency ) video_ids = response.video_ids logger.info("videos_fetched", count=len(video_ids)) # Filter by date (requires fetching metadata) cutoff_date = datetime.now() - timedelta(days=days_back) recent_videos = [] for video_id in video_ids: # Note: Supadata doesn't provide publish date in bulk # May need to use YouTube Data API or check after transcript fetch video = VideoMetadata( id=video_id, channel_id=channel_id, title="", # Will be enriched from transcript metadata url=f"https://youtube.com/watch?v={video_id}" ) recent_videos.append(video) return recent_videos except Exception as e: logger.exception("channel_fetch_failed", channel_id=channel_id, error=str(e)) raise async def get_transcript( self, video_id: str, retry: bool = False ) -> Optional[Transcript]: """Fetch transcript for video with timestamps. Args: video_id: YouTube video ID. retry: Whether this is a retry attempt. Returns: Transcript object or None if unavailable. Raises: SupadataError: If API request fails (non-transcript errors). """ logger.info("fetching_transcript", video_id=video_id, retry=retry) try: response = self.client.youtube.transcript( video_id=video_id, text=False # Get segments with timestamps ) segments = [ TranscriptSegment( text=seg["text"], offset_ms=seg["offset"], duration_ms=seg["duration"], lang=seg.get("lang", "en") ) for seg in response.content ] transcript = Transcript( video_id=video_id, segments=segments, lang=response.lang, available_langs=response.available_langs ) logger.info("transcript_fetched", video_id=video_id, segments=len(segments)) return transcript except Exception as e: # Check if transcript unavailable (206 status) if "transcript-unavailable" in str(e).lower(): logger.warning("transcript_unavailable", video_id=video_id) return None logger.exception("transcript_fetch_error", video_id=video_id, error=str(e)) raise ``` -------------------------------- ### SQL Database Schema for RAG Pipeline Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt SQL migration script to set up the Supabase database schema. It includes creating tables for channels, videos, and transcript chunks, enabling the pgvector extension, and defining a function for vector similarity search. Ensure the vector dimension in `transcript_chunks` table matches your embedding model. ```sql -- Execute in Supabase Dashboard > SQL Editor -- Enable pgvector extension CREATE EXTENSION IF NOT EXISTS vector; -- Create channels table CREATE TABLE IF NOT EXISTS channels ( id TEXT PRIMARY KEY, name TEXT NOT NULL, url TEXT, last_processed_at TIMESTAMPTZ, active BOOLEAN DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Create videos table CREATE TABLE IF NOT EXISTS videos ( id TEXT PRIMARY KEY, channel_id TEXT REFERENCES channels(id) ON DELETE CASCADE, title TEXT NOT NULL, url TEXT NOT NULL, published_at TIMESTAMPTZ, duration_seconds INTEGER, status TEXT DEFAULT 'pending', transcript_available BOOLEAN DEFAULT FALSE, error_message TEXT, retry_count INTEGER DEFAULT 0, processed_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Create transcript chunks with embeddings -- NOTE: Adjust vector dimension based on embedding model -- text-embedding-3-small: 1536 -- nomic-embed-text: 768 -- all-MiniLM-L6-v2: 384 CREATE TABLE IF NOT EXISTS transcript_chunks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), video_id TEXT REFERENCES videos(id) ON DELETE CASCADE, chunk_index INTEGER NOT NULL, text_content TEXT NOT NULL, start_offset_ms INTEGER, end_offset_ms INTEGER, duration_ms INTEGER, token_count INTEGER, embedding vector(1536), -- Match your model's dimensions metadata JSONB DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(video_id, chunk_index) ); -- Create indexes for performance CREATE INDEX idx_chunks_embedding ON transcript_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); -- Create vector search RPC function CREATE OR REPLACE FUNCTION match_transcript_chunks( query_embedding vector(1536), match_count INT DEFAULT 5, filter JSONB DEFAULT '{}'::jsonb ) RETURNS TABLE ( id UUID, video_id TEXT, text_content TEXT, start_offset_ms INTEGER, similarity FLOAT, metadata JSONB ) LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT tc.id, tc.video_id, tc.text_content, tc.start_offset_ms, 1 - (tc.embedding <=> query_embedding) AS similarity, tc.metadata FROM transcript_chunks tc WHERE CASE WHEN filter != '{}'::jsonb THEN tc.metadata @> filter ELSE TRUE END ORDER BY tc.embedding <=> query_embedding LIMIT match_count; END; $$; ``` -------------------------------- ### Unified note management docstring Source: https://github.com/coleam00/dynamous-ai-coach/blob/main/PRPs/ai_docs/tool_guide.md Provides a comprehensive docstring for the obsidian_note_manage function, explaining its consolidated capabilities and detailing each operation mode for agent guidance. ```Python """Unified note management - handles read, write, patch, and metadata updates. This consolidates what would otherwise require 3-4 separate tool calls. Use operation parameter to specify what you want to do: - \"read\": View note content - \"update\": Replace entire content - \"patch\": Find and replace text - \"append\": Add to end of note """ ``` -------------------------------- ### Enforce Rate Limiting for User API Requests (Python) Source: https://context7.com/coleam00/dynamous-ai-coach/llms.txt This checks user rate limits in Supabase and stores allowed requests. Dependencies: db_utils for checks/storage, agent clients for Supabase. Inputs: user ID, request ID, query; configurable rate limit (default 5/min). Outputs: boolean for allowance, tracks requests expiring after 1 minute. Limitations: Assumes Supabase setup; rejects exceedances with 429. ```Python from src.api.db_utils import check_rate_limit, store_request from src.utils.clients import get_agent_clients _, supabase = get_agent_clients() user_id = "user-123-abc" request_id = "req-789-ghi" # Check if user has exceeded rate limit (default 5 requests per minute) rate_limit_ok = await check_rate_limit(supabase, user_id, rate_limit=5) if rate_limit_ok: # Store the request for rate limiting await store_request( supabase=supabase, request_id=request_id, user_id=user_id, query="What is the best morning routine?" ) print("Request allowed and tracked") else: print("Rate limit exceeded - request rejected") # Return 429 or error response # Rate limit automatically expires after 1 minute # Requests older than 1 minute don't count toward the limit ```