# Latest Developments — Source Configuration (ADR-0018) # # Two independent top-level sections: # # sources: flat list of fetch sources — read by src/pipeline/fetch.py # digest: email digest settings — read by src/digest/send.py # # Neither section references the other. Adding or removing a source never # requires touching the digest section, and vice versa. # # Environment variables (set as GitHub Secrets): # EMAIL_SENDER, EMAIL_RECIPIENT, EMAIL_PROVIDER # EMAIL_PASSWORD or RESEND_API_KEY # YOUTUBE_API_KEY — YouTube Data API v3 # GEMINI_API_KEY — Google AI Studio (free at aistudio.google.com) # --------------------------------------------------------------------------- # sources — flat list, one entry per source # # Every entry has these common fields: # type rss | youtube | substack | hackernews | arxiv | # huggingface | paperswithcode | operator_changelog | # replicate | openreview | openrouter # name human-readable label (also used as source_name on ProcessedItem) # source_class primary | operator | practitioner | media | market # enabled true | false (default: true) # # Type-specific options follow inline (see per-type examples below). # --------------------------------------------------------------------------- sources: # ── RSS / Atom feeds ────────────────────────────────────────────────────── - type: rss name: "Anthropic Blog" url: "https://www.anthropic.com/rss.xml" source_class: operator enabled: true - type: rss name: "OpenAI Blog" url: "https://openai.com/blog/rss.xml" source_class: operator enabled: true - type: rss name: "Google AI Blog" url: "https://blog.google/technology/ai/rss/" source_class: operator enabled: true - type: rss name: "DeepMind Blog" url: "https://deepmind.google/blog/rss.xml" source_class: operator enabled: true - type: rss name: "Ethan Mollick — One Useful Thing" url: "https://www.oneusefulthing.org/feed" source_class: practitioner enabled: true - type: rss name: "Simon Willison's Weblog" url: "https://simonwillison.net/atom/everything/" source_class: practitioner enabled: true - type: rss name: "Together AI Blog" url: "https://www.together.ai/blog/rss.xml" source_class: operator enabled: true - type: rss name: "Lambda Blog" url: "https://lambda.ai/blog/rss.xml" source_class: operator enabled: true # SDK/library release feeds are disabled — they produce pure version-bump # items (e.g. "v0.8.3 released") with no substantive analysis content and # exhaust Gemini enrichment quota on noise. Consider re-enabling individual # feeds only after adding a pre-enrichment filter that skips items whose # titles match a semver-only pattern (e.g. /^v?\d+\.\d+/). - type: rss name: "Groq SDK Releases" url: "https://github.com/groq/groq-python/releases.atom" source_class: operator enabled: false - type: rss name: "Cerebras SDK Releases" url: "https://github.com/Cerebras/cerebras-cloud-sdk-python/releases.atom" source_class: operator enabled: false - type: rss name: "Mistral Inference Releases" url: "https://github.com/mistralai/mistral-inference/releases.atom" source_class: operator enabled: false - type: rss name: "Ollama Releases" url: "https://github.com/ollama/ollama/releases.atom" source_class: practitioner enabled: false - type: rss name: "llama.cpp Releases" url: "https://github.com/ggerganov/llama.cpp/releases.atom" source_class: practitioner enabled: false - type: rss name: "LocalAI Releases" url: "https://github.com/mudler/LocalAI/releases.atom" source_class: practitioner enabled: false # ── YouTube channels ────────────────────────────────────────────────────── - type: youtube name: "Nate Jones" channel_id: "UC0C-17n9iuUQPylguM1d-lQ" source_class: practitioner enabled: true max_videos: 8 - type: youtube name: "Wes Roth" channel_id: "UCqcbQf6yw5KzRoDDcZ_wBSw" source_class: practitioner enabled: true max_videos: 5 - type: youtube name: "Matthew Berman" channel_id: "UCawZsQWqfGSbCI5yjkdVkTA" source_class: practitioner enabled: true max_videos: 5 - type: youtube name: "The AI Daily Brief" channel_id: "UCKelCK4ZaO6HeEI1KQjqzWA" source_class: media enabled: true max_videos: 3 # ── Substack newsletters ────────────────────────────────────────────────── - type: substack name: "Nate's Newsletter" slug: "natesnewsletter" source_class: media enabled: true # ── Singleton fetchers — one entry per fetcher ──────────────────────────── - type: hackernews name: "Hacker News" source_class: practitioner enabled: true min_score: 100 max_stories: 8 keywords: - "LLM" - "large language model" - "Claude" - "GPT" - "Gemini" - "Llama" - "AI agent" - "transformer" - "RAG" - "fine-tuning" - "inference" - "benchmark" - "Anthropic" - "OpenAI" - "DeepMind" - "Mistral" - "Opencode" - "Claws" - "post training" - "copilot" - "cowork" - type: arxiv name: "arXiv" source_class: primary enabled: true categories: - cs.AI - cs.LG - cs.CL - cs.CV - cs.RO max_papers: 8 - type: huggingface name: "HuggingFace Models" source_class: primary enabled: true max_models: 15 min_downloads: 1000 - type: paperswithcode name: "Papers with Code" source_class: primary enabled: true page_size: 15 min_stars: 0 - type: operator_changelog name: "Operator Changelogs" source_class: operator enabled: true feeds: - "https://www.anthropic.com/rss.xml" - "https://openai.com/blog/rss.xml" - "https://blog.google/technology/ai/rss/" - "https://deepmind.google/blog/rss.xml" - type: replicate name: "Replicate Models" source_class: operator enabled: false limit: 5 - type: openreview name: "OpenReview Papers" source_class: primary enabled: true limit: 15 venues: - "ICLR.cc/2025/Conference/-/Accepted" - "NeurIPS.cc/2025/Conference/-/Accepted" - "ICML.cc/2025/Conference/-/Accepted" - type: openrouter name: "OpenRouter Pricing" source_class: market enabled: false limit: 10 # --------------------------------------------------------------------------- # digest — email digest settings # # Completely independent of the sources section. Filter predicates reference # only ProcessedItem field names (Schema Contract B), never source names or types. # --------------------------------------------------------------------------- digest: subject: "Daily AI Digest — {date}" send_if_empty: false # Filters applied to ProcessedItem records before selecting digest items. # All three reference ProcessedItem field names — not source names or types. min_credibility: 0.3 # exclude items with credibility_score below this max_hype_risk: 0.8 # exclude items with hype_risk above this exclude_marketing: true # exclude items where is_marketing is true # Gemini digest generation model: "gemini-2.5-flash" max_tokens: 2000 max_items_per_source: 5 prompt: | You are summarising content from AI/ML sources for a senior software engineer who follows the LLM space closely. Be concise and technical. For each item, write: Theme: [1–3 word label, e.g. "agentic RAG", "fine-tuning", "inference cost"] Summary: [2–3 sentences: what it is, why it matters, one concrete takeaway] Focus on: - New model releases and their key capabilities or benchmarks - Novel research techniques with practical implications - Important open-source releases (libraries, tools, datasets) - Significant industry news (funding, partnerships, policy) - Practical developer tutorials or insights worth knowing Skip: - Pure marketing announcements with no technical substance - Repetitive coverage of the same story - Beginner-level tutorials unless the technique is genuinely new After all items, add a ## TL;DR section: exactly 3 bullet points, each a single concise sentence naming the most impactful item and why it matters. Follow with one "Recurring theme: …" line. Finally, add a ## Item Themes section listing each item's URL and its theme label, one per line: - | And a ## Item Summaries section: - | # --------------------------------------------------------------------------- # pipeline — processing pipeline settings # # gemini_model: fallback hint used only when the ListModels API is unreachable. # At runtime the pipeline calls ListModels, discovers all available Pro and # Flash models, and builds the cascade automatically in this priority order: # # Tier 0 — Pro (gemini-X.Y-pro) highest capability, lowest RPD # Tier 1 — Flash (gemini-X.Y-flash) balanced # Tier 2 — Flash-Lite (gemini-X.Y-flash-lite) highest RPD, lightest # # Within each tier: newest major.minor version first, stable before preview. # The cascade falls through to the next model only when daily quota (RPD) is # exhausted — never on rate-limit (RPM), which is handled by back-off. # # This setting is prepended to the fallback cascade when the API is down, so # set it to your preferred starting model (default: gemini-2.5-pro). # # Theme clustering and email digest always use gemini-2.5-flash regardless # of this setting (1 call/run; quality matters more than throughput there). # # gemini_rpm: minimum interval floor (60 / rpm seconds between calls). # The pipeline also adapts dynamically from x-ratelimit-remaining-requests # response headers — so this value only governs the fastest we'll ever go, # not a ceiling on how slow we'll back off when quota runs low. # # enrich_max_output_tokens: Gemini token budget per enrichment call; default 500. # With thinking_budget=0 (see src/pipeline/stages/enrich.py) the model no # longer burns output tokens on reasoning, so 500 is sufficient, but 800 # provides headroom against longer SUMMARY fields. # --------------------------------------------------------------------------- pipeline: gemini_model: "gemini-2.5-pro" gemini_rpm: 15 enrich_max_output_tokens: 800 # --------------------------------------------------------------------------- # history — shared global section # --------------------------------------------------------------------------- history: enabled: true history_days: 7 history_dir: history # --------------------------------------------------------------------------- # logging — shared global section # --------------------------------------------------------------------------- logging: level: "INFO" log_file: null