Files
GEOAgentArticleOptimizer/docs/superpowers/specs/2026-06-16-geo-agent-article-optimizer-design.md
T
2026-06-24 10:37:24 +08:00

688 lines
21 KiB
Markdown

# GEO Agent Article Optimizer MVP Design
## Goal
Build a lightweight internal web tool for optimizing pasted GEO-related articles while preventing the issues observed in `GEO生成文章改动点(0422).docx`: industry drift, image-text mismatch, third-party voice in official articles, platform mismatch, incomplete company names, title/body grammar issues, hallucinated claims, inconsistent claims, context-insensitive sensitive-word handling, and useless content.
The first version validates the content quality loop before investing in batching, permissions, publishing integrations, or complex document parsing.
## MVP Scope
The MVP is a local web application:
1. User pastes title, body, image descriptions or image links, and selects the target platform.
2. System extracts a candidate fact card.
3. User confirms or edits the fact card.
4. Confirmed fact card is saved as a reusable local brand template.
5. System optimizes the article under fact-card constraints.
6. System runs quality gates.
7. Failed checks trigger targeted rewriting for up to two rounds.
8. User previews optimized content and QA report.
9. User downloads Markdown and a basic Word document.
10. User can optionally register where an optimized revision was published and later record real performance data for calibration.
## Explicitly Out Of Scope
- Account permissions.
- Multi-user collaboration.
- Publishing platform APIs.
- Batch queues.
- Direct `.docx` upload parsing.
- Complex Word template layout.
- Automatic use of unconfirmed facts.
- Automatic platform performance adapters in the first calibration release. The first release records performance manually while keeping an adapter interface for later.
## User Flow
```mermaid
flowchart TD
A["Input Article"] --> B["Auto Analyze"]
B --> C["Confirm Fact Card"]
C --> D["Optimize Article"]
D --> E["Quality Check"]
E -->|Pass| F["Preview Result"]
E -->|Fail| G["Targeted Rewrite"]
G --> D
F --> H["Download Markdown / Word"]
```
## Page Areas
### Article Input
Fields:
- Title.
- Body.
- Image description or image link.
- Target platform: official site, media article, comparison review, recommendation list.
- User instructions.
The first version accepts pasted text instead of `.docx` upload to avoid early complexity around Word layout parsing.
### Fact Card Confirmation
The system extracts candidate facts, but they are not treated as truth until the user confirms them.
Fields:
- Company full name.
- Company short names.
- Brand names.
- Product names.
- Target industry.
- Target audience.
- Experience years.
- Core claims.
- Forbidden claims.
- Image topics.
- Uncertain items.
The user must resolve uncertain items before optimization starts.
### Optimized Result
Display:
- Optimized title.
- Summary.
- Optimized body.
- Image suggestions.
- Changed sections.
The UI should mark content that needs user confirmation.
### Quality Report
Display each gate as pass, warn, or fail, with evidence, reason, suggested fix, and target rewrite module.
### Export
Downloads:
- `optimized.md`
- `optimized.docx`
- `qa_report.json`
## Internal Agent Nodes
The product is delivered as a simple web app, but the internals are split into explicit workflow nodes.
```mermaid
flowchart LR
A["InputNormalizer"] --> B["FactExtractor"]
B --> C["UserConfirmedFactCard"]
C --> D["ArticleOptimizer"]
D --> E["QualityInspector"]
E -->|fail| F["TargetedRewriter"]
F --> E
E -->|pass/warn| G["Exporter"]
```
### LLM Provider Integration
Workflow nodes use a local LLM client abstraction instead of calling a vendor API directly. The first implementation uses DeepSeek by default, while keeping the provider boundary open for later OpenAI-compatible providers.
Environment variables:
```text
LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-v4-pro
DEEPSEEK_THINKING=disabled
```
Rules:
- `src/lib/llm/client.ts` exposes `generateText`, `generateJson<T>`, `isLlmConfigured`, and `getLlmProviderStatus`.
- `LLM_PROVIDER` defaults to `deepseek` when unset.
- DeepSeek is accessed through the OpenAI-compatible SDK with `baseURL` set to `https://api.deepseek.com`.
- `generateJson<T>` must use JSON output mode and prompts that explicitly require valid JSON only.
- Thinking mode is disabled by default for deterministic article rewrites and structured QA output.
- Missing credentials use deterministic local fallbacks so the MVP remains testable and usable without a live API key.
- Provider errors are normalized inside the LLM client before they reach workflow nodes or API routes.
### InputNormalizer
Purpose: normalize page input into clean structured data.
Input:
- Title.
- Body.
- Image descriptions or links.
- Target platform.
- User instructions.
Output:
- `article_draft`
- `image_assets`
- `publish_context`
This node does not optimize content.
### FactExtractor
Purpose: extract candidate facts from the source article.
Output:
- `company_full_name`
- `company_short_name`
- `brand_names`
- `product_names`
- `target_industry`
- `target_audience`
- `experience_years`
- `core_claims`
- `forbidden_claims`
- `image_topics`
- `uncertain_items`
Low-confidence facts must go into `uncertain_items`.
### UserConfirmedFactCard
Purpose: provide hard constraints for all downstream nodes.
Rules:
- No downstream node may invent numbers, qualifications, clients, cases, or experience years outside the confirmed fact card.
- Company and product names must follow the fact card.
- Industry and audience must not drift from the fact card.
- Sensitive words must be handled by context, not removed mechanically.
### ArticleOptimizer
Purpose: improve title, summary, body, structure, and image suggestions under fact-card constraints.
Allowed:
- Improve fluency.
- Fix grammar.
- Adjust structure.
- Improve platform fit.
- Remove useless content.
- Improve transitions.
Forbidden:
- Invent claims.
- Change company or product names.
- Change industry.
- Add exaggerated marketing promises.
### QualityInspector
Purpose: convert the document's issue list into executable quality gates.
Each check returns:
- `status`: `pass`, `warn`, or `fail`.
- `evidence`: source or optimized text snippet.
- `reason`: why the check passed or failed.
- `suggested_fix`: how to fix it.
- `target_agent`: rewrite target when failed.
### TargetedRewriter
Purpose: fix only failed checks.
Examples:
- Rewrite only the title for title quality failures.
- Adjust only the affected paragraph for body quality failures.
- Normalize company names for fact consistency failures.
- Delete or mark unsupported claims for hallucination risk.
- Warn instead of rewriting when image-text confidence is low.
### PerformanceCalibrator
Purpose: turn exported GEO articles into a measurable quality-improvement loop after publication.
This node is optional and runs after the optimization/export workflow. It does not rewrite the article, does not change the confirmed fact card, and does not block export. It records a pre-publication scoring snapshot, a publication record, post-publication performance snapshots, and calibration observations that can later improve GEO scoring rubrics.
Inputs:
- Optimized article revision.
- QA report for the same revision.
- Publish platform and optional URL.
- Manual performance data in the first release.
Outputs:
- `scoring_run`
- `publication_record`
- `performance_snapshot`
- `calibration_event`
Rules:
- Calibration is append-only for a published revision. Later data imports create new snapshots instead of overwriting earlier ones.
- The first release uses manual data entry only.
- The service boundary must support future adapters that return the same `PerformanceSnapshot` shape.
- Adapter code must never store platform cookies, tokens, or login state in the public repository.
- Calibration observations can recommend rubric changes, but rubric changes require a separate reviewed migration or plan.
## Quality Gates
| Rule ID | Issue Prevented | First Version Behavior |
| --- | --- | --- |
| `industry_alignment` | Industry drift | Compare article against fact-card industry and audience. |
| `image_text_match` | Image-text mismatch | Compare image descriptions/topics with nearby article sections. |
| `voice_consistency` | Third-party voice in official articles | Enforce platform-specific tone. |
| `platform_fit` | Wrong article type for platform | Compare style and structure against target platform. |
| `company_name_integrity` | Incomplete company name | Compare against confirmed company full name and allowed short names. |
| `title_quality` | Title grammar issues | Detect awkward, keyword-stuffed, or semantically broken titles. |
| `body_quality` | Body grammar issues | Detect long sentences, unclear references, and broken logic. |
| `hallucination_risk` | Fabricated or misleading claims | Reject claims not traceable to the confirmed fact card. |
| `claim_consistency` | Inconsistent years/products/services | Scan and normalize repeated factual claims. |
| `context_sensitive_terms` | Blind sensitive-word deletion | Warn when wording needs context-aware handling. |
### Hard Fail
- Incomplete or inconsistent company name.
- New numbers, qualifications, customer cases, or other claims outside the fact card.
- Clear industry drift.
- Severe title grammar failure.
- Conflicting experience years, product names, or service names.
### Warn
- Low-confidence image-text match.
- Uncertain sensitive-word context.
- Weak platform fit.
- Overly promotional or low-density paragraphs.
### Auto Fix
- Body grammar.
- Useless content.
- Third-party voice when platform is official site.
## Publication Performance Calibration
The project can borrow the useful part of `cheat-on-content`: content quality should become a measurable loop, not a one-time rewrite. GEO's version keeps the web app and database model, and adds a productized calibration layer instead of copying the external skill's file-based workflow.
First-release flow:
```mermaid
flowchart LR
A["Optimized Article Revision"] --> B["Pre-Publish Scoring"]
B --> C["Publication Record"]
C --> D["Manual Performance Snapshot"]
D --> E["Calibration Event"]
E --> F["Rubric Improvement Backlog"]
```
### Pre-Publish Scoring
Before or after export, the system can score an optimized revision against a GEO rubric. The first rubric should focus on business article quality rather than viral-video prediction.
Suggested first dimensions:
| Dimension | Meaning |
| --- | --- |
| `fact_integrity` | Whether names, products, years, cases, and claims stay inside the confirmed fact card. |
| `platform_fit` | Whether the output matches official site, media article, comparison review, or recommendation list expectations. |
| `search_intent_fit` | Whether the article answers the likely GEO/search intent behind the topic. |
| `answer_density` | Whether the article gives useful, specific information instead of vague promotional filler. |
| `trust_signal_quality` | Whether credibility signals are specific, sourced, and not exaggerated. |
| `readability` | Whether title, summary, and body are clear enough for customers and AI answer engines. |
The score is stored as a snapshot. It is not a replacement for QA gates. QA gates protect factual safety; scoring provides a baseline for later performance learning.
### Publication Records
A publication record links one optimized article revision to where it was published.
Fields:
- Job ID.
- Optimized revision.
- Platform.
- URL.
- Published at.
- Publication notes.
- Status: draft, published, archived.
The same optimized revision may have multiple publication records if a user republishes it on multiple channels.
### Manual Performance Snapshots
The first release records post-publication performance manually. This avoids platform login, anti-scraping, and credential risk while validating the calibration loop.
Baseline fields:
- Views or reads.
- Impressions, when available.
- Clicks or inquiry actions, when available.
- Likes, comments, shares, saves, when available.
- Average ranking or citation position, when the user can observe it.
- Snapshot window, such as T+1d, T+3d, T+7d, or custom.
- Comment or feedback summary.
- Data source: `manual`.
Manual snapshots should allow missing metrics. Different platforms expose different numbers, and forcing fake zeroes would corrupt later calibration.
### Adapter Boundary
Future adapters must write the same performance shape as manual entry:
```ts
interface PerformanceAdapter {
source: string;
fetch(input: AdapterFetchInput): Promise<PerformanceSnapshot>;
}
```
Adapter output is normalized before storage:
- `source`: `manual`, `adapter:xhs`, `adapter:bilibili`, `adapter:wechat`, or similar.
- `metrics`: sparse numeric metrics.
- `snapshot_at`: ISO timestamp.
- `window_label`: human label such as `T+3d`.
- `raw_reference`: optional safe reference to adapter output, never raw cookies or credentials.
The first implementation should include a `manual` adapter only. Platform adapters are later work and must keep credentials out of Git, D1, logs, and public artifacts.
### Calibration Events
A calibration event compares the pre-publish scoring snapshot, QA report, and performance snapshot.
Examples:
- High `fact_integrity` and high `answer_density` correlate with stronger inquiry clicks.
- Weak `platform_fit` correlates with poor engagement on media articles.
- QA warning on `hallucination_risk` did not affect traffic but increased manual review burden.
- Articles with high readability but low trust-signal quality received views but no inquiries.
Calibration events should be written as observations, not automatic rubric changes. A later rubric update must be reviewed separately and applied through migrations/tests so historical data remains interpretable.
## Data Model
The first version uses local SQLite plus an export folder. Cloudflare deployments use D1/R2 bindings with migration-only schema changes; local and online data remain explicitly separated.
```text
data/
app.db
exports/
job_xxx/
original.md
optimized.md
optimized.docx
qa_report.json
```
### `brand_template`
Reusable confirmed brand facts.
```json
{
"id": "brand_xxx",
"brand_name": "Brand",
"company_full_name": "Company Ltd.",
"company_short_names": ["Company"],
"product_names": ["Product"],
"target_industries": ["GEO optimization"],
"target_audience": ["Marketing teams"],
"verified_claims": ["More than ten years of industry experience"],
"forbidden_claims": ["Do not claim industry first without proof"],
"tone_rules": {
"official_site": "brand first-person or official voice",
"media": "objective third-party voice"
},
"updated_at": "2026-06-16T10:00:00+08:00"
}
```
### `article_job`
One optimization task.
```json
{
"id": "job_xxx",
"brand_template_id": "brand_xxx",
"source_title": "Original title",
"source_body": "Original body",
"image_inputs": [
{
"type": "description",
"content": "Product dashboard screenshot"
}
],
"publish_platform": "official_site",
"status": "qa_failed",
"created_at": "2026-06-16T10:05:00+08:00"
}
```
### `fact_card`
Confirmed facts for one job.
```json
{
"job_id": "job_xxx",
"source": "auto_extract_then_user_confirmed",
"company_full_name": "Company Ltd.",
"product_names": ["Product"],
"target_industry": "GEO optimization",
"publish_intent": "official article",
"locked_claims": ["More than ten years of industry experience"],
"uncertain_items": [],
"confirmed_by_user": true
}
```
### `optimized_article`
One revision of optimized content.
```json
{
"job_id": "job_xxx",
"revision": 2,
"title": "Optimized title",
"summary": "Optimized summary",
"body_markdown": "Optimized body in Markdown",
"image_suggestions": [
{
"source": "image_1",
"suggestion": "Use product dashboard screenshot; avoid unrelated people photos"
}
],
"changed_sections": ["title", "first paragraph"]
}
```
### `qa_report`
Quality checks for one revision.
```json
{
"job_id": "job_xxx",
"revision": 2,
"overall_status": "warn",
"checks": [
{
"rule_id": "hallucination_risk",
"status": "pass",
"evidence": "No new unsupported factual claims found",
"reason": "All factual claims are traceable to the confirmed fact card",
"target_agent": null
}
]
}
```
### `rubric_version`
A versioned scoring rubric for GEO article performance calibration.
```json
{
"id": "rubric_geo_v1",
"version": "v1",
"name": "GEO article performance rubric",
"dimensions": [
{
"id": "fact_integrity",
"label": "事实一致性",
"weight": 2,
"description": "事实、公司名、产品名和经验年限是否遵守事实卡"
}
],
"formula": "weighted_average_0_to_10",
"is_active": true,
"created_at": "2026-06-24T10:00:00+08:00"
}
```
### `scoring_run`
A scoring snapshot for one optimized article revision.
```json
{
"id": "score_xxx",
"job_id": "job_xxx",
"revision": 2,
"rubric_version_id": "rubric_geo_v1",
"dimension_scores": {
"fact_integrity": 5,
"platform_fit": 4,
"search_intent_fit": 4,
"answer_density": 3,
"trust_signal_quality": 3,
"readability": 4
},
"composite_score": 7.8,
"rationale": "事实一致性强,平台适配较好,但信任信号仍偏泛。",
"created_at": "2026-06-24T10:05:00+08:00"
}
```
### `publication_record`
A publication instance for an optimized revision.
```json
{
"id": "pub_xxx",
"job_id": "job_xxx",
"revision": 2,
"platform": "official_site",
"url": "https://example.com/articles/geo-optimization",
"published_at": "2026-06-24T12:00:00+08:00",
"status": "published",
"notes": "官网文章首发"
}
```
### `performance_snapshot`
One post-publication performance measurement.
```json
{
"id": "perf_xxx",
"publication_id": "pub_xxx",
"source": "manual",
"window_label": "T+7d",
"metrics": {
"views": 1200,
"impressions": 4300,
"clicks": 86,
"inquiries": 7,
"likes": 18,
"comments": 3,
"shares": 5,
"saves": 11
},
"feedback_summary": "用户主要询问服务流程和案例真实性。",
"snapshot_at": "2026-07-01T12:00:00+08:00"
}
```
### `calibration_event`
An observation linking scoring, QA, and real performance.
```json
{
"id": "cal_xxx",
"publication_id": "pub_xxx",
"scoring_run_id": "score_xxx",
"performance_snapshot_id": "perf_xxx",
"direction": "better_than_expected",
"observations": [
"高 answer_density 的段落带来更多服务流程咨询。",
"trust_signal_quality 偏低,用户仍追问案例依据。"
],
"recommended_action": "后续 rubric 提高 trust_signal_quality 权重前,先积累至少 5 篇同类样本。",
"created_at": "2026-07-01T12:10:00+08:00"
}
```
## Error Handling
### Fact Extraction
Optimization is disabled until the user resolves uncertain facts.
Examples:
- Only a company short name is found.
- Multiple product names appear.
- Multiple experience-year claims appear.
- Target industry is unclear.
- Image description is missing.
### QA Failure
QA failures do not hide exports. Hard failures and warnings are surfaced as risk signals with visible confirmation prompts, so the user can still download artifacts for review or customer handoff.
Failed checks trigger targeted rewrite for up to two rounds. After two failed rounds, the app stops rewriting and shows manual review fields.
### Performance Data
Manual performance snapshots accept sparse metrics. Missing metrics are stored as absent values, not zeroes.
Adapter failures must degrade to manual entry. The app should show the source and failure reason, but it must not block the user from recording performance data manually.
Calibration events never rewrite published articles automatically. They create a reviewable backlog for future rubric changes.
## Acceptance Criteria
The MVP is complete when:
1. User can paste title, body, image descriptions, and target platform.
2. System can extract a fact card and require user confirmation.
3. Confirmed fact card can be saved and reused as a local brand template.
4. System can generate an optimized article without changing confirmed facts.
5. System can generate a structured QA report for the 10 quality gates.
6. Hard failures and warnings are visible in the QA report without hiding export links.
7. User can download Markdown and a basic Word document.
8. User can create a publication record for an optimized revision.
9. User can manually record a post-publication performance snapshot.
10. System can create a calibration event that compares score, QA findings, and performance.
11. The performance collection boundary can later support platform adapters without changing the stored snapshot shape.
## Minimum Test Samples
Prepare at least five sample articles:
1. Industry drift sample.
2. Incorrect or incomplete company name sample.
3. Title grammar sample.
4. Conflicting experience-year sample.
5. Image-text mismatch sample.
These samples cover the most important risks from the source document and keep the first validation loop focused.