Today started as building automated Instagram card-news posting and ended with tearing up the pipeline's whole structure. Chasing one bug led me to a data-source limitation and, eventually, integrating a whole new API — here's the day in order.
Chasing the Korean card-news parsing bug
The session started with last time's homework: the Korean card-news cover-parsing bug. I pulled 15 real source articles and ran them through, but that particular bug never reproduced. Instead I found a much more frequent real problem — the closing card was showing made-up link text like [blog link] straight from the model. I fixed it by making the parser tolerant of label variations and adding a regex to filter out link phrases.
Wiring up Instagram auto-posting
Posting card-news images to Instagram needed a public URL. I compared GitHub raw hosting against Cloudflare R2 and went with R2 since it lets me auto-delete images after posting. I issued the account, bucket, and API token myself and personally verified upload, public access, and deletion. Carrying over the "draft, then human review" principle I'd already applied to Blogger, I built a two-step flow that separates creating the carousel container from actually publishing it. With that structure, I got the first real Korean card-news post published.
Called out for weak copy
Right after posting, I got feedback that the copy was too generic. Digging in, I found the pipeline was only pulling the single latest value for each economic indicator, so the model had no basis at all for judging direction of change — it kept inventing phrases like "a stabilizing trend." I fixed it by also pulling the prior value and pre-computing the actual change in Python before it ever reaches the prompt. While I was at it, I also fixed a rendering bug where interest rates were showing up mangled, like 3.6300000000.
Hitting a wall trying to set up a cron job
Asked to have this run automatically every day, I first had to explain the difference between cron and launchd.
| Aspect | cron | launchd |
|---|---|---|
| If missed during sleep | Just skipped | Re-runs on wake |
| Fit for a laptop | Low | High |
But when asked for three sessions a day — "pre-market forecast / mid-morning recap / closing preview" — it came out that the current pipeline only handles US macro indicators and has no Korean market data at all. I pushed that feature to a separate sub-project and instead changed direction to first expand along a "US/Korea topic × English/Korean language" structure.
Wiring in Bank of Korea ECOS data
For Korean macro indicators, I looked into the Bank of Korea's ECOS API. The statistical table codes weren't something I could be confident about from the docs alone, so I called the base rate, CPI, unemployment rate, and GDP one by one with a real issued key and cross-checked them directly against the top-100-indicators values. I matched the new collection script's format to the existing US data script so the pipeline handles both countries' data without distinction. I actually ran all four combinations and confirmed the country shows up correctly in each title.
Bugs that surfaced while lengthening for SEO
After feedback that the posts were too short for SEO/AdSense standards, I raised the target length to 1,000–1,500 words in English and 1,500–2,000 characters in Korean. But then I found the model was converting GDP values directly into Korean units like "조" (trillion) or "억" (hundred million) and getting the order of magnitude flat-out wrong. I fixed it by pre-converting the values in Python before handing them to the model. On top of that, I caught — twice — the length-instruction text itself leaking straight into the meta description, so I kept having to strengthen the regex.
Registering the automation, and next homework
I finally registered launchd to auto-run all four combinations every day at 7 a.m., and confirmed via a manual trigger that all four drafts generate correctly. But I discovered a new problem: since the indicators only change monthly or quarterly while this runs daily, posts could end up duplicating each other on days when the data hasn't moved. I decided to detect unchanged data and either skip it or substitute different content, but left the implementation for the next session.
Trouble Shooting
| Symptom | Cause | Fix |
|---|---|---|
| Fake link text kept showing up on the card-news closing card | The model kept attaching link text despite an instruction not to generate URLs | Added a regex filter that strips out link phrases |
| Copy kept repeating clichés like "a stabilizing trend" | Only the single latest indicator value was pulled, giving no basis for judging direction of change | Also pull the prior value and pre-compute the change in Python before it reaches the prompt |
| Interest rate values rendered mangled, like 3.6300000000 | The raw decimal was displayed as-is on a large number | Added a formatting function with rounding and thousands separators |
| GDP displayed nearly 1000x off from the real value | The model converted units itself with no unit information, and got it wrong | Pre-convert to trillion-scale units in Python before handing off |
| Length-instruction text leaked straight into the meta description | The model echoed the prompt's length instructions verbatim | Strengthened the regex to also catch parenthesis/dash variants |
Reflections / Next steps
I didn't expect that going in to fix one bug would end with adding a whole new data source. It also reconfirmed that handing arithmetic like change calculations or unit conversion to a small local model reliably gets it wrong — the answer is to let code do the math and have the model only use the result. Next session picks up with content-duplication-prevention logic.
[Previous post: Building the Instagram Card-News Pipeline]
Comments
Post a Comment