Ang Teksto ang Madaling Bahagi: ang Pipeline na Naglalagay ng Larawan sa AI-Written Articles
Solusyonado na ang paggawa ng teksto. Hindi pa solusyonado ang paglalagay ng larawan dito. Ang end-to-end pipeline — router prompt, paghahanap ng litrato, Mermaid diagrams, verified charts, at ang alt text, credit, at ImageObject markup na ginagawang SEO ito.
Isa kang developer na may target sa content: dose-dosenang artikulo bawat buwan, marahil daan-daan. Kinakaya ng writing model ang draft, ang outline, ang meta description, ang internal links. Pagkatapos ay tinatamaan ng pipeline ang isang hakbang na walang sariling modelo — ang mga larawan — at humihinto ito. Hindi dahil mahirap kumuha ng mga larawan, kundi dahil walang bahagi ng stack na alam alin na larawan, mula sa saan, may anong lisensya, na inilalarawan paano.
Ang artikulong ito ang nawawalang hakbang na iyon, nakakonekta mula simula hanggang katapusan: anong uri ng visual ang dapat gawin para sa anong uri ng seksyon, ang prompt na nagpapapalit ng natapos na draft tungo sa mga search brief, ang API call na nagbabalik ng mga larawan, ang ikalawang modelo na gumuhit ng hindi kayang ipakita ng litrato, at ang assembler na naglalabas ng markup na talagang mababasa ng Google. Dalawang kumpletong workflow sa bandang huli, handang i-adopt.
Solusyonado na ang teksto. Dito na-stall ang ilustrasyon.
Isagawa ang tapat na audit ng isang awtomatikong article pipeline. Outline: solusyonado. Draft: solusyonado. Titulo, meta description, schema, internal links, salin: solusyonado, lahat ng iisang modelo, lahat sa teksto. Pagkatapos:
| Hakbang sa pipeline | Status | Ano talaga ang humaharang |
|---|---|---|
| Outline at draft | Solusyonado | Isang tawag sa modelo, isang prompt |
| Titulo, meta, schema, links | Solusyonado | Teksto papasok, teksto palabas |
| Hero image | Naharang | Kailangan ng tunay na file, isang lisensya, mga dimensyon, at alt text — wala sa mga ito ang kayang gawin ng text model |
| Mga larawan sa seksyon | Naharang | Tatlo hanggang lima bawat artikulo, magkaiba ang bawat isa, walang nauulit sa buong site |
| Mga chart at diagram | Naharang | Dapat tumpak — ang isang visual na hindi kayang ibalik ng search at hindi dapat imbentuhin ng isang generator |
Ang pagkabigo ay hindi estetiko, ito ay istruktural: ang artikulo ay inilalabas na may stock placeholder, o
may parehong larawan sa nakaraang labindalawang artikulo, o may generated image na ang kamay na may anim na daliri ang
unang makikita ng mambabasa. At ang larawan ay hindi palamuti — malinaw na sinasabi ng dokumentasyon ng Google
tungkol sa larawan: ang alt text ay "ang pinakamahalagang attribute pagdating sa pagbibigay ng metadata
para sa isang larawan", at ang gabay ay gumamit ng tunay na <img> elements na may
deskriptibong alt sa halip na CSS backgrounds, upang mahanap at maintindihan
ang larawan nang buo.1
Apat na uri ng visual, apat na uri ng modelo
Ang pinakamalaking pagkakamali sa disenyo ay ituring ang "ang larawan" bilang iisang problema na may iisang provider. Ito ay apat, at ang router sa pagitan nila ay isang linya ng prompt, hindi isang serbisyo:
| Kailangan ng seksyon… | Gawin ito gamit ang | Bakit hindi ang iba |
|---|---|---|
| Isang eksena mula sa totoong mundohero, sitwasyon ng tao, lugar, bagay, kilos | Semantic photo search (Pexafy) | Nag-iimbento ng detalye ang generator; walang maigugraph ang isang chart |
| Mga numerong totoo nga sa iyobenchmarks, pricing, resulta ng survey, latency | Modelong sumusulat ng plotting code, pinapatakbo sa isang sandbox | Hindi mapagkakatiwalaan ang image model sa isang value; hindi kayang magdala ng data ang isang litrato |
| Isang istruktura o daloyarchitecture, sequence, state machine | Modelong sumusulat ng Mermaid / Graphviz, na-render nang deterministiko | Walang diagram ang mga libreng photo library ng iyong sistema |
| Ang produkto mo sa screendocs, changelog, tutorials | Scripted browser screenshot (Playwright) | Walang ibang paraan para ipakita ang UI na umiiral lang sa iyong build |
At paano naman ang mga ginawang ilustrasyon? May isa itong tapat na papel: ang eksenang hindi maaaring kunan ng litrato at hindi naman data — isang abstract na mekanismo, isang produktong wala pa, isang house illustration style na pagmamay-ari mo. (Ang buong argumento kung bakit mas mainam ang tunay na larawan kaysa sa generation — bilis sa malaking dami, katumpakan, ang problema sa pagkakapareho — ay ginawa dito.) Isang tanda ng direksyon: mula 2 Agosto 2026, hinihiling ng Article 50 ng EU AI Act na markahan ng mga provider ng generative systems ang mga synthetic na output sa isang machine-readable na format.2 Isa itong obligasyon sa mga AI provider at deployer, hindi isang panuntunan tungkol sa maaaring i-publish ng isang blog — pero ito ang dahilan kung bakit ang pinagmulan ng larawan sa itaas ng iyong artikulo ay unti-unting nagiging bagay na maaaring tsekin ng mambabasa sa halip na paniwalaan lang.
Ang pipeline, mula simula hanggang katapusan
Limang yugto. Yugto 3 lang ang humihipo sa isang image API, at yugto 4 lang ang opsyonal:
┌─ 1. WRITE ────────────────────────────────────────────────────┐
topic ──▶ LLM ──▶ draft.md (h2 sections, front-matter)
└───────────────────────────────┬───────────────────────────────┘
┌─ 2. BRIEF ────────────────────┴───────────────────────────────┐
draft.md ──▶ LLM ──▶ { hero: {...}, sections: [ {...} ] }
isang JSON object: bawat slot, isang kind +
alinman sa isang camera brief o isang data/diagram spec
└──────────┬──────────────────────────────────┬─────────────────┘
│ kind = "photo" │ kind = "chart" | "diagram"
▼ ▼
┌─ 3. SEARCH ───────────────┐ ┌─ 4. DRAW (optional) ─────────┐
GET /search/photos LLM ──▶ mermaid | plotting code
← larawang may kredito + ──▶ sandbox ──▶ .svg / .png
w/h, blur_hash, alt, (deterministic render, walang
lisensya, source URL imbentadong numero)
└──────────┬────────────────┘ └──────────────┬───────────────┘
└───────────────┬──────────────────┘
┌─ 5. ASSEMBLE ─────────────┴───────────────────────────────────┐
<img> na may width/height + fetchpriority | loading
alt na isinulat para sa tao · nakikitang kredito · ImageObject JSON-LD
photo_id na naka-imbak upang walang dalawang pahina ang magbahagi ng hero
└───────────────────────────────────────────────────────────────┘
Dalawang katangian ang mas mahalaga kaysa sa diagram. Ang yugto 2 ay isang router: pinagdedesisyunan nito bawat slot kung anong producer ang tatakbo, kaya hinding-hindi mo hihilingin sa isang photo library ang isang bar chart. At nasa yugto 5 kung saan nakasalalay ang SEO — lahat ng dinodokumento ng Google tungkol sa mga larawan (deskriptibong alt, licence metadata, isang LCP-safe hero) ay inilalabas dito, mula sa mga field na dala na ng search response.
Yugto 2: gawing visual briefs ang draft
Isang tawag sa modelo sa tapos nang draft, at ang ibinabalik nito ay isang plano sa halip na isang query. Kung paano magsulat ng iisang photo brief — kung bakit ang pamagat ng artikulo ang pinakamasamang input, kung ano ang hitsura ng isang 12-hanggang-25-salitang camera brief, at ang mga paraan kung paano ito nabibigo — ay inilahad nang buo sa gabay sa pag-iilustrasyon ng isang artikulo, at hindi na ito inuulit dito. Ang idinaragdag ng isang pipeline ay routing: ang parehong tawag ang dapat magpasya, slot by slot, kung aling producer ang tatakbo — at ang isang entry ng chart ay nagdadala ng data samantalang ang entry ng photo ay nagdadala ng eksena.
# system prompt — patakbuhin isang beses bawat natapos na draft
Ikaw ang art director ng isang teknikal na publikasyon. Basahin ang artikulo at
ibalik ang visual plan: isang entry para sa hero, isa bawat H2 section.
Para sa bawat entry pumili ng eksaktong isang kind:
"photo" isang tunay na eksena: may gumagawa ng isang bagay kung saan man,
isang lugar, isang bagay, isang kilos. Ang default para sa heroes.
"chart" binabanggit ng seksyon ang mga numerong NASA artikulo na. Huwag
kailanman mag-imbento ng value: kopyahin ang mga ito sa data, salita-sa-salita.
"diagram" inilalarawan ng seksyon ang isang istruktura, isang daloy, o isang sequence.
"none" maikli ang seksyon, o may dala nang code block.
Mga panuntunan para sa "photo" entries — ang field ay query:
Sumulat ng camera brief: isang eksenang maaaring kuhanan ng camera, 12 hanggang 25 salita,
sa Ingles, na tugma sa mood ng seksyon. Ipangalan ang nasa loob ng frame,
hindi ang paksa. Walang teksto, logo, brand o sikat na tao; walang
di-nakikitang metapora. (Kumpletong mga tuntunin, may mga halimbawa at failure cases:
pexafy.com/blog/illustrate-blog-articles-at-scale/)
HUWAG isulat ang alt text ng isang photo entry: ang larawang ibabalik ay ang
pinakamalapit na match sa brief, hindi ang eksenang inilarawan mo, kaya ang alt nito ay dapat
isulat batay sa napiling larawan. Ang chart at diagram entries AY may dalang alt —
doon ay ganap mong kontrolado kung ano ang ire-render.
Ibalik ang JSON lamang:
{
"hero": { "kind": "photo", "query": "…", "orientation": "landscape" },
"sections": [
{ "h2": "…", "kind": "photo", "query": "…" },
{ "h2": "…", "kind": "chart", "title": "…", "unit": "ms",
"data": [ {"label": "…", "value": 0} ], "alt": "…" },
{ "h2": "…", "kind": "diagram", "spec": "flowchart LR; …", "alt": "…" }
]
}
Ang linyang kind ang gumagawa ng karamihan sa trabaho, at ang instruksyong data ang gumagawa ng natitira: maaari lamang magdala ang isang chart entry ng mga numerong nasa draft na, kaya ang modelo ay nagsasalin sa halip na mag-imbento. Narito ang router sa tatlong tunay na seksyon ng isang artikulo para sa developer:
| Seksyon | kind | Ano ang ibinalik ng router |
|---|---|---|
| Hero — "Bakit 40 minuto ang nightly build namin" | photo |
"isang developer na nagtatrabaho pagkagabi sa isang desk na may dalawang monitor at isang mechanical keyboard sa isang madilim na silid na naiilawan ng mga screen" |
| "Saan talaga napupunta ang oras" | chart |
data na kinopya mula sa talata: install 480 s, compile 1080 s, test 720 s, upload 120 s |
| "Paano namin hinati ang graph" | diagram |
flowchart LR ng job dependency graph |
| "Ano ang binago namin, at ano ang uulitin namin" | photo |
"dalawang engineer na nakatayo sa harap ng isang whiteboard na puno ng diagram, magkasamang lumulutas ng isang problema" |
Yugto 3: nagbabalik ang mga larawan na may kredito
Bawat kind: "photo" entry ay isang request. Ang hero brief sa itaas, na pinatakbo laban sa
pampublikong API, ay ibinabalik ito sa 147 ms:
Ang huling section brief, isang ganap na magkaibang eksena, sa loob ng 144 ms:
Ang ibinabalik bawat larawan ang siyang bahaging nagpapagana sa yugto 5 — hindi lang isang file:
{
"photo_id": "019e1c7f-0063-759e-b498-33ce1714e6c9", // i-imbak ito: walang paulit-ulit
"urls": { "small": "…?w=400", "regular": "…?w=1080",
"large": "…?w=1920" },
"width": 3000, "height": 1688, // → walang layout shift
"blur_hash": "LJ8gjv9rVq-6OFxanNNFI7xco$Na", // → tunay na placeholder
"alt_description": "Person types on keyboard in front of dual monitors…",
"photographer_full_name": "Jakub Żerdzicki", // → ImageObject.creator
"source": "Unsplash", "license_type": "free",
"source_image_url": "https://unsplash.com/photos/…",
"attribution": { "html": "<span…>Photo by …</span>",
"plain": "Photo by Jakub Żerdzicki on Unsplash (…)" }
}
Yugto 4: ang hindi kayang sabihin ng litrato
Dalawang slot sa plano ang hindi maaaring hanapin sa search, at dito talaga kumikita ang ikalawang modelo ng papel nito — hindi para gumuhit ng larawan, kundi para magsulat ng code na gumuguhit nito. Mahalaga ang pagkakaiba: ang code ay maaaring suriin, deterministiko, at hindi maaaring mag-hallucinate ng taas ng isang bar.
Mga diagram: teksto papasok, SVG palabas
Nire-render ng Mermaid ang mga diagram mula sa isang plain-text na kahulugan,3 na siyang gumagawa nito bilang ang pinakaligtas na target para sa isang modelo: ang output ay maaaring siyasatin, mai-diff sa git, at nagre-render nang pareho sa bawat pagkakataon. Naibalik na ng router ang spec.
# ang "spec" field ng isang diagram entry, isinulat sa build/graph.mmd
cat build/graph.mmd
flowchart LR
install["install deps · 480s"] --> compile["compile · 1080s"]
compile --> test["test suite · 720s"]
compile --> upload["upload artifacts · 120s"]
npx -y @mermaid-js/mermaid-cli -i build/graph.mmd -o static/img/graph.svg
# → isang SVG na masusuri mo sa PR, hindi isang larawang dapat mong pagkatiwalaan
Mga chart: mga numero lang na nasa artikulo na
Parehong prinsipyo, isang dagdag na tanggulan. Kinopya ng router ang mga value mula sa draft; sumusulat ang modelo ng plotting code; tumatakbo ang code sa isang sandbox; sinusuri muli ng assembler ang mga value na na-render laban sa mga source number bago pahintulutan ang chart na malapit sa isang pahina.
import re, matplotlib
matplotlib.use("Agg") # headless: walang display sa CI
import matplotlib.pyplot as plt
def assert_in_draft(value, draft: str) -> None:
"""Ang isang na-plot na numero ay dapat lumitaw sa artikulo BILANG ISANG NUMERO."""
# Ang substring matching ang bitag dito: "120" ay nasa loob ng "1200", at
# nasa loob ng "?w=1200" — pumapasa ang naive na `str(v) in draft` sa kahit ano.
# Mag-match sa word boundaries, at tanggapin ang 1 234 / 1,234 / 1234.
body = re.sub(r"(?<=\d)[ ,](?=\d{3}\b)", "", draft) # tanggalin ang separators
if not re.search(rf"(?<![\d.]){re.escape(str(value))}(?![\d.])", body):
raise ValueError(f"{value} is not stated in the article — refusing to plot")
def render_chart(entry: dict, draft: str, out: str) -> str:
labels = [d["label"] for d in entry["data"]]
values = [d["value"] for d in entry["data"]]
for v in values:
assert_in_draft(v, draft) # na-hallucinate na value → walang chart
fig, ax = plt.subplots(figsize=(8, 4.5), dpi=160)
ax.barh(labels, values)
ax.set_xlabel(entry["unit"])
ax.set_title(entry["title"])
fig.tight_layout()
fig.savefig(out) # deterministiko, masusuring artefact
return out
Maikli ang tanggulan, ngunit isulat itong may ingat: hindi gumagana ang substring check.
Totoo ang "120" in draft para sa isang artikulong may laman na 1200 o
?w=1200, kaya ang naive na bersyon ay pumapasa sa lahat at walang pinoprotektahan. Mag-anchor sa
digit boundaries, i-normalize ang thousand separators, at ang uri ng pagkakamaling ikakalas ng isang teknikal
na artikulo sa mga komento — isang chart na sumasalungat sa sarili nitong talata — ay hindi maaaring makarating sa
production. Sumusunod ang mga screenshot sa parehong prinsipyo: ang isang scripted na page.screenshot()
laban sa iyong tunay na build ang tanging pinagmumulan ng katotohanan para sa iyong sariling UI, at nananatiling totoo ito habang
nagbabago ang UI.
Yugto 5: dito nakasalalay ang SEO sa pagsasama-sama
Lahat ng nauna ay gumawa ng mga file at field. Ang yugtong ito ay ginagawang markup ang mga ito — at sulit na maging eksakto dito, dahil tatlong dokumentadong pag-uugali ang napagpasyahan sa ilang linyang ito.
<!-- Nagmumula ang mga byte sa ibang origin: bayaran ang handshake nang maaga -->
<link rel="preconnect" href="https://images.unsplash.com" crossorigin>
<!-- LCP element: huwag kailanman lazy, laging high priority -->
<figure>
<img src="{urls.regular}"
width="{width}" height="{height}" <!-- pumapatay ng layout shift -->
alt="{alt}" <!-- isinulat PAGKATAPOS piliin -->
fetchpriority="high" decoding="async"
style="background:{color_hex}"> <!-- dominanteng kulay, 1 field -->
<figcaption>{attribution.html}</figcaption>
</figure>
<!-- Mga larawan sa seksyon, sa ibaba ng fold: ang kabaligtarang settings -->
<img src="{urls.regular}" width="{width}" height="{height}"
alt="{alt}" loading="lazy" decoding="async">
Hotlink o i-re-host? Nagha-hotlink ang snippet sa itaas, na siyang pinakamabilis na ipalabas at
ang dahilan ng preconnect: ang isang remote na hero ay nagkakahalaga ng isang DNS lookup at isang TLS
handshake sa critical path, at maaari nitong ubusin ang tinubo mo lang gamit ang
fetchpriority. Ganap na tinatanggal ng pag-re-host ang third-party origin, hinahayaan kang mag-serve
ng AVIF/WebP sa iyong sariling mga breakpoint, at nabubuhay kahit magbago ang upstream URL — sa kapalit ng
storage, isang fetch step sa pipeline, at ang iyong sariling CDN bill. Anuman ang piliin mo,
ang color_hex ay nagbibigay sa iyo ng placeholder para sa isang field (mas maganda ang blur hash, ngunit
kailangan itong i-decode muna sa isang data URI — hindi ito isang CSS color). Ang direktang pagkopya ng magaspang na hero
sa background: ang siyang dahilan kung bakit tahimik na nagpapalabas ang karamihan ng pipeline ng isang walang lamang kulay abo na kahon.
-
Huwag kailanman i-lazy-load ang hero. Malinaw ang sinasabi ng web.dev: "Huwag kailanman i-lazy-load ang
iyong LCP image, dahil laging magreresulta iyon sa hindi kinakailangang pagkaantala ng pag-load ng resource, at magkakaroon
ng negatibong epekto sa LCP", at inirerekomenda nito ang
fetchpriority="high"sa elementong malamang na maging ang LCP — na ginagamit nang tipid, sa isang larawan.4 Ang isang pipeline na naglalagay ngloading="lazy"sa bawat larawan, kasama ang hero, ang pinakakaraniwang self-inflicted na sugat sa Core Web Vitals sa automated publishing. -
Laging ilabas ang
widthatheight— bumabalik ang mga ito sa response, kaya walang dahilan; ang tanging pares ng attribute na iyon ang nagbibigay-daan sa browser na mareserba ang espasyo at pinipigilan ang paglukso ng layout. Gamitin angblur_hashbilang placeholder habang nilo-load ang file. -
Isulat ang alt pagkatapos ng pagpili, hindi bago. Ito ang mas maselan. Inilalarawan
ng
altfield ng plano ang eksenang hiniling mo; ang larawang nakuha mo ay ang pinakamalapit na match, hindi ang eksenang iyon. Ang pag-ilabas ng teksto ng brief bilang alt ay eksaktong kabiguan sa accessibility na dapat iwasan ng pipeline na ito — isang paglalarawan ng larawan na wala nga sa pahina. Buuin ang alt mula saalt_descriptionng napiling larawan, na pinong-pino laban sa talatang kinaroroonan nito. Ang gabay ng Google ay "mag-focus sa paglikha ng kapaki-pakinabang, mayaman-sa-impormasyon na nilalaman na gumagamit ng mga keyword nang wasto at nasa konteksto ng nilalaman ng pahina", at nagbababala ito na ang pagpuno ng alt attributes ng mga keyword ay "nagreresulta sa isang negatibong karanasan ng user at maaaring maging dahilan upang ituring ang iyong site bilang spam".1
Ang bahaging halos walang nag-a-automate: licence metadata
Sinusuportahan ng Google ang ImageObject structured data para sa image licensing. Kailangan nito ang
contentUrl kasama ang kahit isa sa creator, creditText,
copyrightNotice, o license, inirerekomenda ang acquireLicensePage,
at nagiging kwalipikado ang mga larawang may impormasyon ng lisensya para sa Licensable badge sa Google
Images.5 Bawat isa sa mga field na iyon ay nasa search response na
— kaya ang paglalabas nito ay isang template, hindi isang proyekto:
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "ImageObject",
"contentUrl": "{urls.large}", // kailangan
"creator": { "@type": "Person",
"name": "{photographer_full_name}" },
"creditText": "{photographer_full_name} on {source}",
"license": "{LICENSE_URL[source]}", // ang sariling pahina ng library
"acquireLicensePage": "{source_image_url}" // ang pahina ng larawan
}
</script>
# Ini-map ng LICENSE_URL ang `source` field sa lisensyang talagang namamahala sa
# larawan — unsplash.com/license, pexels.com/license, pixabay.com/…
Isang detalye na dapat itama: dapat itinuturo ng license ang lisensyang
namamahala sa larawang iyon — ang sariling licence page ng source library — hindi ang isang summary page sa
iyong domain. Binabasa ito ng Google upang magpasya sa badge eligibility, at ang isang self-referential URL ay
parehong mas mahina bilang isang signal at mahirap ipagtanggol bilang anumang bagay maliban sa isang link pabalik sa
sarili mo. Panatilihin ang sarili mong buod ng lisensya bilang isang internal na pahina para sa mga mambabasa; ilagay ang canonical
isa sa markup.
At habang nasa assembler ka: bigyan ang file ng isang maikli, deskriptibong pangalan sa halip na
IMG_0042.jpg, at idagdag ang larawan sa isang sitemap — tinatanggap ng image sitemap format ng Google
ang hanggang 1,000 na larawan bawat page URL.6 Isang linya lang ang bawat isa sa isang
pipeline at wala man sa dalawang ito ang natatapos kapag manwal ang ginawa.
Dalawang pipeline na maaaring i-adopt
Parehong limang yugto, dalawang napakaibang hugis — isa para sa mga artikulong sinusulat mo, isa para sa dokumentasyong dapat tumugma sa isang tumatakbong produkto. Piliin ang isa na kilala mo ang failure mode.
1 · Ang dev blog sa CI — Markdown sa repo
Nakatira ang mga artikulo bilang Markdown, kino-commit ang mga larawan sa tabi nila, at tumatakbo ang lahat sa push. Deterministiko, masusuring sa PR, walang runtime dependency sa anumang API:
on: { pull_request: { paths: ["content/**.md"] } }
jobs:
illustrate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements.txt
- run: python plan_to_pr.py $(git diff --name-only origin/main -- 'content/*.md')
env:
PEXAFY_API_KEY: ${{ secrets.PEXAFY_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- uses: peter-evans/create-pull-request@v6 # napupunta ang mga larawan sa PR
with: { commit-message: "chore(content): illustrate" }
Isang tao pa rin ang nag-a-approve ng PR, at iyon ang punto: iminumungkahi ng pipeline, nagdedesisyon ang reviewer, at ang front-matter na isinulat nito ay maaaring i-diff.
Ang kalahati ng search ay isang GET lang — ang request, ang score_threshold nito at ang mga fields na ibinabalik nito ay nakasulat linya por linya sa
gabay para sa iisang artikulo, kaya ini-import na lamang ito dito sa halip na i-print muli. Ang idinaragdag ng file na ito ay lahat ng kailangan ng isang plano na wala sa isang litrato: ang muling pagsubok sa isang brief na walang naibalik, ang pag-angkin sa isang photo_id para walang dalawang pahina ang magbahagi ng iisang larawan, at ang alt text na sinulat mula sa larawang naibalik.
import frontmatter
from photo_search import search # isang GET /search/photos; nililiban ang mga id na nasa `used`
def find_photo(entry: dict, used: set) -> dict | None:
"""Maghanap; kung sobrang specific ang brief, palawakin nang isang beses, tapos sumuko."""
orientation = entry.get("orientation", "landscape")
for query in (entry["query"], widen(entry["query"])):
photo = search(query, orientation, used)
if photo:
used.add(photo["photo_id"]) # i-claim ito: walang paulit-ulit sa buong site
return photo
return None # magdedesisyon ang caller: laktawan ang slot, o mag-fail
def widen(query: str) -> str:
"""Tanggalin ang huling clause — kadalasan ang sobrang specific."""
return query.rsplit(" in ", 1)[0] if " in " in query else query
def illustrate(path: str, plan: dict, used: set) -> None:
post = frontmatter.load(path)
hero = find_photo(plan["hero"], used)
if hero is None: # mas mabuti ang walang hero kaysa masamang hero
raise SystemExit(f"{path}: no photo above threshold — rewrite the brief")
post["hero"] = { # lahat ng kailangan ng template
"src": hero["urls"]["regular"], "w": hero["width"], "h": hero["height"],
# Inilalarawan ng alt ang larawang NAKUHA namin, hindi kailanman ang eksenang hiniling namin.
"alt": alt_for(hero, section=post.get("title", "")),
"bg": hero["color_hex"], "credit": hero["attribution"]["html"],
"creator": hero["photographer_full_name"], "id": hero["photo_id"],
"source": hero["source"],
"source_url": hero["source_image_url"], # → acquireLicensePage
}
open(path, "w").write(frontmatter.dumps(post))
def alt_for(photo: dict, section: str) -> str:
"""alt_description bilang batayan, pinaikli sa ~125 karakter para sa screen readers.
Ibalik ito sa modelo kasama ang talata kung gusto mo ng mas mahusay."""
base = photo.get("alt_description") or photo.get("description", "")
return base[:125].rstrip(" ,;")
2 · Docs at changelog — screenshot muna, larawan sa huli
Baliktarin ang mga default ng router. Sa dokumentasyon ng produkto ang tapat na visual ay halos laging ang sarili mong UI: isang Playwright script na nagbubukas ng tunay na build, nagtatakda ng nakapirming viewport, at kumukuha ng eksaktong estado na inilalarawan ng talata. Sinasaklaw ng mga diagram ang mga architecture page, at ang mga litrato ay lumilitaw lamang sa mga conceptual at landing page — kung saan wala talagang masasabi ang isang screenshot.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={"width": 1440, "height": 900},
device_scale_factor=2) # retina-crisp
page.goto("http://localhost:3000/dashboard")
page.get_by_role("button", name="New API key").click()
page.screenshot(path="static/img/docs/new-api-key.png")
browser.close()
# Tumatakbo sa parehong CI job kasama ang docs build → hindi kailanman kayang
# ilarawan ng screenshot ang isang bersyon ng UI na wala na.
Dalawang variant na sulit banggitin ngunit hindi sulat ng sariling recipe. Binabaligtad ng Programmatic
SEO ang loop: sa daan-daang pahina na na-generate mula sa isang database ay hindi ka naghahanap bawat pahina —
ang isang request ay nagbabalik ng hanggang 100 larawan, kaya naghahanap ka bawat topic cluster at nagtatalaga mula sa isang
pool, na may uniqueness constraint na siyang gumagawa ng deduplication
(ang arkitekturang iyon, nang buo).
At kailangan ng newsletters at social cards ang parehong larawan sa apat na crop: itago ang
photo_id, hilingin ang laki na kailangan mo mula sa urls, at maghanap lang muli
kapag talagang nabigo ang isang crop.
Ang parehong pipeline, bilang iisang agent
Kung isang modelo na ang sumusulat ng draft, ang pinakamaikling landas ay bigyan ito nang direkta ng search tool
sa halip na maglipat-lipat ng JSON sa pagitan ng mga proseso. Nagpapatakbo ang Pexafy ng isang hosted Model Context
Protocol server sa mcp.pexafy.com/mcp. Nasakop na sa ibang lugar ang setup ng connector at ang mga tool
na inilalantad nito — ang desktop at editor setup sa
gabay para sa iisang artikulo,
ang headless na variant para sa isang CI runner sa
artikulo tungkol sa content sa malaking sukat,
at kung ano ang itsura ng mas malawak na merkado ng connector — sino ang naglalabas ng MCP image server, sa anong mga termino —
sa pag-aaral ng
image search infrastructure para sa mga AI agent.
Ang mahalagang ipakita rito ay ang mangyayari sa pipeline na ito kapag hawak na ng agent ang mga
tool: hindi na ito magiging limang yugto kundi isang instruksyon na lamang.
Ikaw Narito ang draft. Buuin ang visual plan, ilustrahan ito, at magbukas ng PR.
Mga chart lamang mula sa mga numerong nasa teksto na.
Agent → plan: hero=photo · §2=chart · §3=diagram · §4=photo
→ search_photos(q="a developer working late at a desk with two
monitors and a mechanical keyboard in a dark room…")
← 16 photos · 147 ms · napili #1, 3000×1688, may kredito
→ mermaid-cli build/graph.mmd → static/img/graph.svg
→ chart.py §2 → 4 value na na-check laban sa draft ✓
→ search_photos(q="two engineers standing at a whiteboard…")
← 16 photos · 144 ms · napili #1
✓ 4 slot napunuan · 2 API call · alt + kredito + ImageObject naisulat
⚠ walang ibinalik ang §5 na higit sa 0.5 — sobrang abstract ang brief, muling isinulat bilang
"isang tao sa kusina na sinusuri ang mga numero sa isang laptop"
Ang huling linyang iyon ang dahilan kung bakit sulit magkaroon ng agent sa loop na ito kaysa sa isang purong script: ang failure mode ng automated illustration ay ang isang masamang brief, at ang muling pagsulat ng masamang brief ang eksaktong ginagamit sa isang language model. Panatilihin ang mga deterministikong bahagi — pagtatalaga, deduplication, ang numeric guard — sa code.
Ano ang gastos ng isang ilustradong artikulo
Ang tatlong photo slot bawat artikulo ay nangangahulugang tatlong search request, kaya ang free plan (5,000 requests/month) ay sumasaklaw sa 1,666 artikulo bawat buwan bago pa man lumitaw ang tanong ng pagbabayad — at kung pinagsasama-sama mo ang mga search bawat topic cluster sa halip na bawat artikulo, gumagalaw ang langit na iyon nang isa pang antas ng magnitude. Ang breakdown bawat plano, at ang pooling architecture na nagpapawalang-saysay dito, ay nasa kasamang artikulo tungkol sa pag-ilustra ng content sa malawakang saklaw.
Ang dalawang tawag sa modelo bawat artikulo — isa para sa draft, isa para sa visual plan — ay ilang libong token lamang at magiging pinakamurang linya sa pipeline; walang gastos ang Mermaid at matplotlib render maliban sa mga segundo ng CI. Ang bilang na nakakagulat sa mga tao ay kung aling linya ang hindi mura: ang paggawa ng apat na larawan bawat artikulo, apat na daang larawan bawat buwan, kasama ang mga pagsubok na hindi nakarating — at ang output ay wala pa ring photographer, petsa, o source URL.
Ang hindi naaayos ng pipeline na ito
Isang tapat na seksyon, dahil mahal ang pagkabigong pinipigilan nito. Isang mahusay na ini-ilustrang artikulo ay isang artikulo pa rin: ang tunay na photography, tumpak na chart, at wastong markup ay nagpapabuti sa isang pahinang karapat-dapat umiral. Hindi nila napapa-rank ang manipis, malawakang-produced na content. Binabanggit ng patakaran sa spam ng Google ang scaled content abuse — ang paggawa ng maraming pahina na pangunahing layunin ay manipulahin ang mga ranking at nag-aalok ng kaunting halaga sa mga user, gawin man ito gamit ang automation o hindi — at hindi salik sa paghatol na iyon ang kalidad ng mga ilustrasyon.7
Kaya ang framing na kumakapit: ang pipeline na ito ay isang quality floor na iyong kinokontrol, na inilalapat sa mga pahinang mayroon nang dahilan upang ilathala. Kung saan malinaw itong nagbabayad:
- Pinanggalingang mapapatunayan ng mambabasa. Ang isang credit line na may tunay na photographer at
isang source URL ay isang claim na maaaring i-check — at ang parehong mga field ang nagpapakain sa
ImageObjectmarkup na binabasa ng Google. - Accessibility at Core Web Vitals. Tunay na alt text, mga dimensyon sa bawat larawan, isang hero na hindi kailanman lazy-loaded. I-multiply sa bawat artikulong inilathala mo at ito ang kwento ng kalidad ng larawan ng site.
- Katumpakan kung saan ito masusuri. Isang chart na ang mga numero ay tsina-tsek laban sa artikulo, isang screenshot na na-generate mula sa tumatakbong build, isang diagram na masusuri bilang teksto sa PR — tatlong visual na hindi maaaring lumihis sa katotohanan nang hindi bumagsak ang isang test.
Sa usapin ng attribution, makitid ang punto na partikular sa pipeline:
ang argumento para sa laging
pag-render ng credit ay ginawa na sa ibang lugar, at ang idinaragdag ng isang automated assembler ay ang parehong string ng attribution na ini-print nito ay siya ring creditText na kailangan ng structured data. Isang field, dalawang lugar, ibinubuga sa parehong pagdaan ng template — kaya't mas kaunti pa ang dahilan ng isang pipeline kaysa sa isang tao para itong laktawan.
Saan magsisimula
- Idagdag ang router prompt sa anumang sumusulat na ng iyong mga draft, at i-print ang JSON nang hindi kumikilos dito. Basahin ang sampung plano. Kung pinapangalanan ng mga brief ang mga paksa sa halip na mga eksena, ayusin ang prompt bago magsulat ng anumang integration.
- Ikonekta lamang ang mga photo slot. Isang
GET /search/photosbawat brief, at itago angphoto_idmula sa unang araw — ang deduplication na iretrofit sa 3,000 live na pahina ay isang migration, hindi isang column. - Ilabas ang width, height, at alt sa parehong commit. Ito ang pinakamurang Core Web Vitals na trabahong gagawin mo kailanman.
- Pagkatapos idagdag ang yugto 4, mga diagram bago mga chart — teksto ang Mermaid, kaya ito ang walang failure mode maliban sa isang syntax error.
- Idagdag ang numeric guard bago makarating ang unang chart sa isang mambabasa, hindi pagkatapos.
Mga sanggunian at talababa
1 Google Search Central, Image SEO best practices: ang alt text
ay "ang pinakamahalagang attribute pagdating sa pagbibigay ng metadata para sa isang larawan"; ang gabay
ay lumikha ng "kapaki-pakinabang, mayaman-sa-impormasyon na nilalaman na gumagamit ng mga keyword nang wasto at nasa konteksto
ng nilalaman ng pahina", na iwasan ang mga alt attribute na puno ng keyword, gumamit ng HTML
<img> elements sa halip na CSS images, at magbigay sa mga file ng maiikli ngunit deskriptibong
pangalan.
2 EU AI Act, Article 50 — obligasyong pang-transparency na naaangkop simula 2 Agosto 2026: dapat markahan ng mga provider ng sistemang gumagawa ng synthetic na larawan, audio, video, o teksto ang output sa isang machine-readable na format at gawin itong madetektang artipisyal na ginawa. Sinasaklaw nito ang mga AI provider at deployer; hindi ito isang patakaran tungkol sa aling mga larawan ang maaaring ilathala ng isang website.
3 Nire-render ng Mermaid ang mga diagram at chart mula sa mga kahulugang inspirado ng Markdown na teksto, na siyang gumagawa sa output na masusuri at deterministiko.
4 web.dev, Optimize Largest Contentful Paint: "Magandang ideya na itakda ang
fetchpriority="high" sa isang <img> element kung sa palagay mo ay malamang na maging
ito ang LCP element ng iyong pahina", na ginagamit nang tipid; at "Huwag kailanman i-lazy-load ang iyong LCP image,
dahil laging magreresulta iyon sa hindi kinakailangang pagkaantala ng pag-load ng resource, at magkakaroon ng negatibong
epekto sa LCP."
5 Google Search Central, Image metadata (structured data): kailangan ng
ImageObject ang contentUrl kasama ang kahit isa sa creator,
creditText, copyrightNotice, o license; inirerekomenda ang
acquireLicensePage, at maaaring maging kwalipikado ang mga larawang may impormasyon ng lisensya para sa
Licensable badge sa Google Images.
6 Google Search Central, Image sitemaps: ang mga image sitemap ay nagbibigay-alam sa Google tungkol sa mga larawan sa isang site, kabilang ang mga natagpuan sa pamamagitan ng JavaScript, at tumatanggap ng hanggang 1,000 na larawan bawat page URL.
7 Google Search spam policies — scaled content abuse: ang paggawa ng maraming pahina na pangunahing layunin ay manipulahin ang mga ranking at nag-aalok ng kaunting halaga sa mga user, ginawa man sa pamamagitan ng automation, pagsisikap ng tao, o isang kombinasyon.
Mga sanggunian na na-check noong 17 Agosto 2026: Image SEO best practices · Image metadata · Image sitemaps · Optimize LCP · Search spam policies · AI Act Article 50 · Mermaid · Pexafy API & MCP docs. Ang mga oras ng search (147 ms, 144 ms) at bawat larawang ipinakita ay tunay na API response na nakuha sa parehong araw.
Mga madalas na tanong
Paano ko awtomatikong lalagyan ng larawan ang mga artikulong isinulat ng LLM?
GET /api/v1/search/photos, humigit-kumulang 150 ms). Ang mga entry na chart at diagram ay ipinapadala sa isang model na sumusulat ng plotting code o Mermaid, na dine-render nang deterministiko. Huwag kailanman ipapasok ang titulo ng artikulo sa isang image search: abstract ang mga titulo at walang litratong naglalarawan nito.Dapat bang gumamit ng screenshots o stock photos ang isang documentation site?
Paano ko pipigilan ang isang AI pipeline sa paglalagay ng maling numero sa isang chart?
data ng entry ng chart. Pagkatapos, i-assert ito sa code bago i-render — para sa bawat value, tingnan kung ang string nito ay lumitaw sa artikulo, kung hindi ay mag-raise ng error. Siyam na linya lang, at hindi na maaaring makarating sa mambabasa ang isang chart na sumasalungat sa sariling talata nito.Anong image markup ang dapat ilabas ng isang awtomatikong pipeline para sa SEO?
alt na isinulat batay sa konteksto ng talata — tinatawag ng Google ang alt text bilang pinakamahalagang image metadata at binabalaan laban sa keyword stuffing. width at height sa bawat larawan, na may fetchpriority="high" sa hero at hindi kailanman loading="lazy" dito, dahil hindi dapat i-lazy load ang LCP image. At ImageObject structured data na may contentUrl, creator, creditText, at license, na kung saan ito ang nagpapasilbi sa isang larawan na kwalipikado para sa Licensable badge sa Google Images.Nakakatulong ba ang paglalagay ng larawan sa AI-written articles para mag-rank ito?
Paano ko patakbuhin ang illustration step sa CI nang hindi nawawala ang editorial control?
photo_id, ang pagpapatunay na ang bawat naka-plot na numero ay lumalabas sa artikulo, at ang hard failure kapag walang photo na nakapasa sa score threshold. Mas mabuti ang walang hero kaysa sa maling hero.