Ngày: 2026-07-14 Dựa trên: Brand Monitoring Brief V3 (đã duyệt) Link brief: https://vmi3427693.tail8c1aaf.ts.net/files/root/.hermes/kanban/boards/brand-monitoring/workspaces/t_7f5461eb/brand-monitoring-brief.md Link file này: https://vmi3427693.tail8c1aaf.ts.net/files/opt/ai-os/products/ceo/brand-monitoring/docs/brand-monitoring-architecture-v3.md
| # | Nguyên tắc | Giải thích |
|---|---|---|
| 1 | Public data only | Chỉ dùng nguồn public, không phụ thuộc page API hoặc nội dung đăng nhập |
| 2 | Crisis-first | Mọi luồng dữ liệu đều ưu tiên phát hiện rủi ro trước, coverage sau |
| 3 | Multi-brand by design | Hệ thống hỗ trợ nhiều brand, mỗi brand có config riêng |
| 4 | Fulbright là MỘT brand | FUV, FSPPM là entity con của Fulbright, KHÔNG phải brand riêng |
| 5 | Graceful degradation | Nguồn tạm mất vẫn không làm sập pipeline |
Pipeline thu thập chia làm 4 lớp:
[Layer 1: Discovery] → [Layer 2: Normalize] → [Layer 3: Triage] → [Layer 4: Store & Report]
Thu thập bài từ nguồn public. Mỗi nguồn có 1 trong 3 trạng thái:
| Trạng thái | Cách thu thập | Ví dụ |
|---|---|---|
| Public RSS | Tự động qua RSS/Atom feed | Google News RSS, VnExpress RSS |
| Public page scrape | Crawl công khai, tag page, topic page | Tuổi Trẻ tag page, Dân Trí search |
| Search only | Monitor qua search engine query | Google News search query |
Nguồn ưu tiên V1:
| Nhóm | Nguồn | Loại |
|---|---|---|
| Tổng hợp | Google News | Search RSS |
| Báo VN tier 1 | VnExpress, Tuổi Trẻ, Thanh Niên | RSS + Page scrape |
| Báo VN tier 2 | Dân Trí, VietnamPlus, VietnamNews | RSS + Search |
| Chuyên mục | Tag page, topic page, newsroom | Page scrape |
| Quốc tế | Chỉ khi có mention rõ ràng | Search only |
| Social public | YouTube (public video/comment), Facebook public page, X (public) | API public / scrape |
| Academic | OpenAlex, SSRN | API/Search |
| Forum | Diễn đàn public | Scrape |
Nguồn LOẠI BỎ khỏi scope V1: - Page API cần quyền share riêng - Private group - Nội dung cần đăng nhập - Bất kỳ nguồn nào không có quyền public rõ ràng
| Bước | Việc làm |
|---|---|
| 2.1 | Chuẩn hóa tiêu đề (strip HTML, normalize unicode) |
| 2.2 | Chuẩn hóa ngày giờ (ISO 8601, timezone VN) |
| 2.3 | Chuẩn hóa nguồn (source_id canonical) |
| 2.4 | Canonical URL (bỏ tracking params, resolve redirects) |
| 2.5 | Gắn brand_id (map entity keyword → brand) |
| 2.6 | Language detection (vi / en) |
| Loại trùng | Cách xử lý |
|---|---|
| Cùng URL | Giữ 1 bản |
| Cùng bài khác URL | Title similarity + snippet similarity > 85% → merge |
| Cùng nội dung repost | Giữ nguồn gốc, gắn alias cho bản repost |
Relevance Score (0-100):
| Thành phần | Điểm |
|---|---|
| Core entity trong title | +30 |
| Core entity trong body | +15 |
| Crisis trigger keyword | +25 |
| Brand variant match | +15 |
| Policy context match | +10 |
| Source tier A/B | +5 |
Sentiment Score: positive / neutral / negative / ambiguous
Crisis Gate:
| Điều kiện | Hành động |
|---|---|
| Negative + Relevance >= 70 | HOT ALERT → gửi ngay |
| Negative + engagement bất thường | HOT ALERT → gửi ngay |
| Crisis trigger keyword xuất hiện | HOT ALERT → gửi ngay |
| Ambiguous + source lớn (tier A) | → review thủ công |
| Neutral / Positive | → vào báo cáo tuần |
brand-monitoring/
├── brands/
│ └── fulbright/ ← MỘT brand duy nhất
│ ├── brand.yaml ← tên, mô tả, ngôn ngữ, thị trường
│ ├── keywords.yaml ← core, variant, crisis, entity children (FUV, FSPPM)
│ ├── sources.yaml ← nguồn ưu tiên + tier
│ ├── rules.yaml ← relevance, sentiment, crisis threshold
│ └── report.yaml ← kênh báo cáo, cadence, template
├── shared/
│ ├── sources/ ← nguồn dùng chung (không riêng brand nào)
│ ├── taxonomy/ ← topic tag, sentiment rule, crisis rule
│ ├── workflows/ ← quy trình thu thập, xử lý, cảnh báo
│ └── templates/ ← template báo cáo
├── runs/
│ ├── raw/ ← dữ liệu thô theo ngày
│ ├── processed/ ← dữ liệu đã normalize + dedupe
│ ├── alerts/ ← crisis alerts đã gửi
│ └── reports/ ← báo cáo đã tạo
└── dashboard/ ← giao diện đọc dữ liệu
Fulbright (brand)
├── FUV (entity con — Fulbright University Vietnam)
└── FSPPM (entity con — Fulbright School of Public Policy and Management)
FUV và FSPPM KHÔNG phải brand riêng. Chúng là entity children nằm trong keywords.yaml của brand Fulbright.
| Nhóm keyword | Mục đích | Ví dụ (Fulbright) |
|---|---|---|
| Core entity | Xác định brand chính | Fulbright, Đại học Fulbright |
| Variant entity | Biến thể tên | FUV, Fulbright VN, Fulbright Việt Nam |
| Program entity | Chương trình, khoa, school | FSPPM, Chính sách Công, MPP |
| Crisis trigger | Từ khóa rủi ro | scandal, tranh cãi, chỉ trích, bê bối, học phí, kiểm định |
| Policy context | Chính sách liên quan | giáo dục đại học, kiểm định, học bổng |
| Sentinel phrases | Bật cảnh báo nóng | "khủng hoảng Fulbright", "Fulbright bê bối" |
| Tầng | Công nghệ | Lý do |
|---|---|---|
| Raw event store | SQLite DB | Đơn giản, không cần server, backup dễ |
| Processed mentions | SQLite DB (bảng riêng) | Relational, query tốt, dedup hiệu quả |
| Alert log | SQLite DB + JSON | Track mọi alert đã gửi |
| Weekly report | Markdown + optional Google Sheets view | Dễ đọc, dễ chia sẻ |
| Archive | Compressed JSON (daily .jsonl.gz) | Lưu trữ dài hạn, tái phân tích |
-- Bài thô thu thập
CREATE TABLE raw_items (
id INTEGER PRIMARY KEY,
source_id TEXT NOT NULL,
url TEXT NOT NULL UNIQUE,
title TEXT,
snippet TEXT,
published TEXT, -- ISO 8601
fetched_at TEXT,
brand_id TEXT,
lang TEXT,
raw_json TEXT -- toàn bộ payload gốc
);
-- Bài đã normalize + score
CREATE TABLE mentions (
id INTEGER PRIMARY KEY,
raw_item_id INTEGER REFERENCES raw_items(id),
brand_id TEXT NOT NULL,
url_canonical TEXT,
title_clean TEXT,
published TEXT,
source_tier TEXT, -- A, B, C, D
relevance_score INTEGER,
sentiment TEXT, -- positive, neutral, negative, ambiguous
is_crisis INTEGER DEFAULT 0,
crisis_reason TEXT,
dedup_hash TEXT,
processed_at TEXT
);
-- Alert log
CREATE TABLE alerts (
id INTEGER PRIMARY KEY,
mention_id INTEGER REFERENCES mentions(id),
brand_id TEXT,
alert_type TEXT, -- hot_alert, review_manual
sent_at TEXT,
channel TEXT, -- telegram, email, etc.
status TEXT -- sent, failed, acknowledged
);
-- Weekly report metadata
CREATE TABLE reports (
id INTEGER PRIMARY KEY,
brand_id TEXT,
report_type TEXT, -- daily, weekly
period_start TEXT,
period_end TEXT,
generated_at TEXT,
file_path TEXT,
hot_alert_count INTEGER,
negative_count INTEGER,
neutral_count INTEGER,
positive_count INTEGER
);
/opt/ai-os/products/ceo/brand-monitoring/
├── data/
│ └── brand-monitoring.db ← SQLite chính
├── archive/
│ └── 2026/07/14.jsonl.gz ← archive theo ngày
├── reports/
│ └── 2026-W29-fulbright.md ← report tuần
└── docs/
└── brand-monitoring-architecture-v3.md ← file này
| Job | Schedule | Mô tả |
|---|---|---|
collect-rss |
Mỗi 6 giờ (0 /6 * * ) | Thu thập RSS feeds (Google News, báo VN) |
collect-scrape |
Mỗi 12 giờ (0 /12 * * ) | Crawl tag pages, topic pages |
collect-social |
Mỗi 12 giờ (0 6,18 * * *) | Thu thập YouTube, Facebook public |
sentinel-check |
Mỗi 1 giờ (0 * * * *) | Check nhanh crisis keywords trên Google News |
| Job | Schedule | Mô tả |
|---|---|---|
normalize-dedupe |
Sau mỗi collection (event-driven hoặc cron 30 phút sau collect) | Normalize + dedupe raw items |
score-triage |
Sau normalize | Relevance + sentiment + crisis gate |
alert-dispatch |
Real-time sau crisis gate | Gửi hot alert nếu crisis detected |
| Job | Schedule | Mô tả |
|---|---|---|
daily-summary |
Hàng ngày 21:00 VN (0 14 * * * UTC) | Tổng kết ngày, highlight crisis nếu có |
weekly-digest |
Thứ Hai 08:00 VN (0 1 * * 1 UTC) | Báo cáo tuần đầy đủ |
archive-daily |
Hàng ngày 23:00 VN (0 16 * * * UTC) | Compress raw data thành .jsonl.gz |
| Job | Schedule | Mô tả |
|---|---|---|
cleanup-raw |
Mỗi tuần (0 3 * * 0 UTC) | Xóa raw items > 90 ngày (đã archive) |
db-vacuum |
Mỗi tháng (0 4 1 * * UTC) | SQLite VACUUM |
mentions (DB) → filter by brand + period → group by sentiment →
sort by crisis priority → render template → output markdown →
optional: push to Google Sheets → deliver via Telegram/email
| Thứ tự | Section | Nội dung |
|---|---|---|
| 1 | Crisis & Risk Summary | Số crisis alerts, top items nguy hiểm nhất |
| 2 | Negative Items | Danh sách nội dung tiêu cực, nguồn, relevance |
| 3 | Neutral Coverage | Tin nhắc đến brand nhưng trung lập |
| 4 | Positive Signals | Tín hiệu tốt |
| 5 | Topic Clusters | Nhóm chủ đề nổi bật, chủ đề lặp lại |
| 6 | Recommended Actions | Đề xuất hành động dựa trên dữ liệu |
brand: fulbright
report_date: 2026-07-14
period: 2026-07-07 to 2026-07-14
hot_alert_count: 2
negative_count: 5
neutral_count: 23
positive_count: 8
top_sources:
- VnExpress (7 mentions)
- Tuổi Trẻ (4 mentions)
- Google News (12 mentions)
recommended_actions:
- "Theo dõi bài tiêu cực trên Tuổi Trẻ về học phí"
- "Phản hồi bài viết sai thông tin trên Dân Trí"
| Kênh | Dùng cho |
|---|---|
| Telegram (hot alert) | Crisis alert → gửi ngay vào group/topic |
| Telegram (weekly) | Báo cáo tuần → gửi vào topic riêng |
| Markdown file | Lưu tại /opt/ai-os/products/ceo/brand-monitoring/reports/ |
| Google Sheets (optional) | View cho stakeholders không dùng Telegram |
Raw items (SQLite) → daily export → compress → /archive/YYYY/MM/DD.jsonl.gz
Processed mentions → keep in DB forever (lightweight)
Alerts → keep in DB forever (audit trail)
Reports → keep as markdown files → organized by year-week
| Dữ liệu | Giữ ở DB | Giữ ở archive |
|---|---|---|
| Raw items | 90 ngày | Vĩnh viễn (compressed) |
| Processed mentions | Vĩnh viễn | N/A (đã ở DB) |
| Alerts | Vĩnh viễn | N/A |
| Reports | Vĩnh viễn (file) | N/A |
Mỗi ngày tạo 1 file archive:
archive/2026/07/14.jsonl.gz
Mỗi dòng là 1 JSON record chứa raw item + processed mention + alert (nếu có).
Quyết định: V1 dùng Markdown reports + optional Google Sheets view.
Lý do: 1. Chưa có đủ dữ liệu để justify dashboard riêng 2. Markdown report đọc được trên Tailscale Funnel 3. Google Sheets view cho stakeholders không kỹ thuật 4. Giảm complexity vận hành
Khi đạt 1 trong các điều kiện: - Chạy ổn > 4 tuần liên tục - > 100 mentions/tuần cần browse - > 2 brands cùng lúc - CEO yêu cầu real-time view
Khi upgrade, ưu tiên: 1. Static HTML generated từ data (simple, hostable trên Tailscale Funnel) 2. Hoặc Notion/Airtable view (nếu team đã dùng) 3. Không dùng tool phức tạp (Grafana, Metabase) ở V1
┌─────────────────────────────────────────────────────────┐
│ COLLECTION (Cron) │
│ RSS Feeds ──┐ │
│ Page Scrape ├──→ Raw Items → SQLite raw_items table │
│ Social ──┘ │
│ Sentinel ───→ Quick crisis keyword check (hourly) │
└──────────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ PROCESSING (Cron) │
│ Normalize → Dedupe → Relevance Score → Sentiment Score │
│ │ │
│ ▼ │
│ Crisis Gate │
│ ╱ ╲ │
│ YES NO │
│ │ │ │
│ Hot Alert Weekly Queue │
└──────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ DELIVERY (Cron) │
│ Hot Alert → Telegram ngay lập tức │
│ Daily Summary → 21:00 VN │
│ Weekly Digest → Thứ Hai 08:00 VN │
└──────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ ARCHIVE (Cron) │
│ Daily: raw → .jsonl.gz │
│ Weekly: cleanup raw > 90 ngày │
│ Monthly: DB VACUUM │
└─────────────────────────────────────────────────────────┘
File kiến trúc này được lưu cố định tại:
/opt/ai-os/products/ceo/brand-monitoring/docs/brand-monitoring-architecture-v3.md
Truy cập qua Tailscale Funnel:
https://vmi3427693.tail8c1aaf.ts.net/files/opt/ai-os/products/ceo/brand-monitoring/docs/brand-monitoring-architecture-v3.md
| Vấn đề ở draft cũ | Sửa ở V3 |
|---|---|
| Thiếu multi-brand structure chi tiết | Có folder layout + entity hierarchy đầy đủ |
| FUV/FSPPM mơ hồ | Ghi rõ: entity con, KHÔNG phải brand riêng |
| Storage chỉ liệt kê option | Quyết định rõ: SQLite + JSON archive |
| Thiếu cron schedule | Có bảng cron cụ thể với schedule, timezone |
| Thiếu report flow | Có pipeline + template + delivery channels |
| Thiếu archive flow | Có retention policy + format + path |
| Dashboard chưa quyết | Quyết định V1: Markdown + optional Google Sheets |
| File ở workspace tạm | File cố định ở /opt/ai-os/products/ceo/brand-monitoring/docs/ |