慣性聚合 関心のあるブログ、ニュース、テクノロジーを効率的に追跡
原文を読む 慣性聚合で開く

おすすめ購読元

J
Java Code Geeks
腾讯CDC
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
L
LangChain Blog
Vercel News
Vercel News
云风的 BLOG
云风的 BLOG
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
The GitHub Blog
The GitHub Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog
P
Proofpoint News Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
IT之家
IT之家
A
About on SuperTechFans
H
Help Net Security

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How I Built a Multi-System Astrology Bot in Python (And W...
Yegor Shusty · 2026-05-24 · via DEV Community

Вот, держи готовый — копируй в body dev.to:


Every horoscope app reduces you to 1 of 12 sun signs. Real astrologers don't work like that — they cross-reference Western astrology, Vedic (Jyotish), Chinese Ba Zi, numerology, Human Design, and more. So I built a Telegram bot that does the same: one daily forecast synthesized from 13 systems, based on your full birth date.

It's been live for ~1 month. Small still — 83 users — but I want to share the parts that actually taught me something.

The Architecture: Why Combining 13 Systems Is a Data Problem, Not an Astrology Problem

Each system is a separate calculator. Western astrology needs ecliptic longitudes (I use Skyfield + NASA ephemeris). Vedic needs tithi (lunar day, 1-30) and nakshatra (27 lunar mansions). Ba Zi needs solar-term boundaries to assign the day-pillar element. Numerology needs digit-reductions with master-number exceptions (11, 22, 33 don't reduce before arithmetic).

Each one is finicky in its own way. Combine them and you get an interesting failure mode: latent bugs that wait for the calendar.

My favourite: a lunar-day translation table had 5 entries, but _tithi_group(30) returned index 5 (Amavasya / new moon). The bug sat dormant for weeks. Then a new moon arrived:

day_label = _TITHI_DAY_LABEL[lang][group_idx]
# IndexError: list index out of range

Enter fullscreen mode Exit fullscreen mode

Content generation crashed for all three languages. The bot's startup also called ensure_content(today), so it entered a crash-loop. I learned two things that day:

  1. Latent bugs wait for the calendar. Any code path that runs only on specific astronomical events needs explicit tests at those boundary conditions.
  2. Startup hooks shouldn't crash the process. Wrap them in try/except so the bot stays alive and the admin can still introspect via diagnostic commands.

LLM Cost Architecture: One Sentinel Saved 99% of the Bill

The bot rewrites raw template output into warm conversational language using Gemini. Daily, monthly, yearly forecasts. With per-user rewriting, costs scale linearly with users — bad.

But the general forecast (the morning broadcast everyone receives) is identical for every user. So I use a sentinel pattern: user_id=0 means "shared cache row". The first user to trigger the daily LLM rewrite warms the cache; everyone else reads from it.

async def get_cached(session, user_id, date, lang, content_type):
    row = await session.get(LLMOutputCache,
                            (user_id, content_type, 0, date, lang))
    return row.text if row else None

Enter fullscreen mode Exit fullscreen mode

This is a 5-line idea, but it cut my LLM bill from "uncomfortable" to "barely noticeable." Pre-warm cron at 03:00 UTC fills the cache before anyone wakes up.

The Hallucination Guard

Gemini is happy to invent astrological facts that aren't in your seed. The seed mentions the Moon; the rewrite confidently introduces Venus. For an astrology bot, that's a catastrophe — users trust the output.

My guard tokenises both texts and rejects the rewrite if any new planet name appears in the output that wasn't in the input. Sign names are tolerated (LLM often adds "the Scorpio Moon" as natural metaphor — that's fine), but actual planet additions = reject and fall back to Groq, then to plain template.

new_planets = _extract_astro_tokens(rewritten) \
            - _extract_astro_tokens(original)
new_planets &= _PLANET_TOKENS
if new_planets:
    log.warning("hallucination guard fired: %s", new_planets)
    return None  # fall back

Enter fullscreen mode Exit fullscreen mode

About 2-3% of Gemini outputs trigger it. The bot silently falls back; the user never sees garbage.

Auto-posting: Single Source of Truth

I publish the same daily forecast to Telegram channel, Instagram (carousel of 4 PNG slides), and Threads. Three different formats, three different APIs, one piece of source content.

Key insight: share the cached LLM rewrite across surfaces. The IG caption pulls from llm_output_cache for user_id=0. Threads' main post pulls from the same cache and crops at the nearest sentence boundary under 500 chars. Zero extra LLM cost; one truth.

main_text = await get_cached(0, today, lang, CONTENT_TYPE_DAILY)
if len(main_text) > 500:
    head = main_text[:500]
    for sep in (". ", "! ", "? "):
        idx = head.rfind(sep)
        if idx >= 200:
            main_text = head[:idx+1].rstrip()
            break

Enter fullscreen mode Exit fullscreen mode

The IG slide renderer uses a separate Gemini call with response_mime_type=application/json for tight char budgets (slides have visual constraints PNG-renderer must respect). One LLM call per language per day, cached 24h in Redis.

The Meta Ban (Or: What I Did Wrong)

Here's the part I'd undo. I had:

  • Per-post engagement-bait on every Threads/IG post: "leave a reaction, share with someone" — identical wording every day.
  • Daily 5-post self-reply chains (main post + numerology reply + Ba Zi reply + Jyotish reply + CTA-with-link reply).
  • Machine-perfect timing: 04:02 UTC ±0 every single day.

Each of these is a textbook spam signal. The combination — automated bot posting, identical engagement-bait, daily self-reply chains with outbound links — is exactly what Meta's integrity systems are designed to penalise.

The English account was disabled outright: "We've reviewed your account and found that it doesn't follow our Community Standards on account integrity." The Russian one survived but was shadow-restricted (posts publish via API but the account vanishes from search/profiles).

The de-spam was straightforward in code:

  • Dropped per-post engagement-bait, kept only a soft "link in bio" CTA
  • Cut the 5-post chain to a single forecast post
  • Added jitter=14400 seconds (±4h) to the cron so the post lands at varying times each day
scheduler.add_job(
    send_threads_post,
    trigger="cron",
    hour=10, minute=0,
    jitter=14400,  # ±4h — fires anywhere in 06:00-14:00 UTC daily
    id="threads_post",
)

Enter fullscreen mode Exit fullscreen mode

The harder lesson: automated social posting on Meta platforms is fragile by design. Meta does not want pure-broadcast bot accounts. A new account you create and immediately hook to a cron will get banned again, the same way. If social presence matters to a project, the human-run path is the only durable one.

Honest Numbers After 1 Month

  • 83 users
  • DAU/MAU ratio: ~9% (healthy benchmarks are 20%+ — retention is my real problem)
  • Profile completion rate: 73.5% (onboarding works)
  • Most-used feature: monthly forecast (high re-engagement, 7 users opened it 25 times in a week)
  • Least-used feature: invite/referral (1 invite in 30 days — turns out shipping a referral mechanism in code is nothing if it's not surfaced in the UI)
  • Paid conversions: 0 (haven't pushed monetisation yet)

What I'd Tell Past-Me

  1. Distribution is harder than the product. I shipped the bot in 3 weeks. Getting people to use it is the actual work, and it's an entirely different skill.
  2. Boring infrastructure decisions compound. Sentinel cache, hallucination guard, dockerised stack with admin diagnostic commands — none of these are cool. All of them have saved hours.
  3. Don't optimise for channels that hate you. Meta's auto-poster ban is a feature, not a bug. Build for the channels where your behaviour is welcome.

The bot is live and free: t.me/CosmoCast_bot — send your birth date, get the forecast.

Happy to answer anything in the comments about the LLM cost architecture, the hallucination guard, the auto-poster setup, or the Meta-ban post-mortem.