feat(intraday): add discovery and verification watch pipeline

This commit is contained in:
phamnazage-jpg
2026-05-27 18:54:32 +08:00
parent 32858bfec4
commit 475401bcbe
21 changed files with 2444 additions and 13 deletions

View File

@@ -0,0 +1,106 @@
-- 日内新闻候选与验证持久化结构
CREATE TABLE IF NOT EXISTS intraday_news_candidate (
id BIGSERIAL PRIMARY KEY,
candidate_date DATE NOT NULL,
discovered_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
event_type TEXT NOT NULL,
provider_name TEXT NOT NULL,
model_name TEXT,
provider_country TEXT,
title TEXT NOT NULL,
summary TEXT,
candidate_urls JSONB NOT NULL DEFAULT '[]'::jsonb,
discovery_source TEXT NOT NULL,
discovery_query TEXT,
discovery_evidence JSONB NOT NULL DEFAULT '{}'::jsonb,
normalized_key TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'candidate',
verification_confidence TEXT NOT NULL DEFAULT 'candidate',
verification_notes TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'chk_intraday_news_candidate_status'
) THEN
ALTER TABLE intraday_news_candidate
ADD CONSTRAINT chk_intraday_news_candidate_status
CHECK (status IN ('candidate', 'verifying', 'verified', 'rejected', 'stale'));
END IF;
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'chk_intraday_news_candidate_confidence'
) THEN
ALTER TABLE intraday_news_candidate
ADD CONSTRAINT chk_intraday_news_candidate_confidence
CHECK (verification_confidence IN ('candidate', 'secondary_confirmed', 'official_confirmed'));
END IF;
END
$$;
CREATE UNIQUE INDEX IF NOT EXISTS idx_intraday_news_candidate_normalized_key
ON intraday_news_candidate(normalized_key);
CREATE INDEX IF NOT EXISTS idx_intraday_news_candidate_date
ON intraday_news_candidate(candidate_date DESC, discovered_at DESC);
CREATE INDEX IF NOT EXISTS idx_intraday_news_candidate_status
ON intraday_news_candidate(status);
CREATE INDEX IF NOT EXISTS idx_intraday_news_candidate_provider_event
ON intraday_news_candidate(provider_name, event_type, candidate_date DESC);
COMMENT ON TABLE intraday_news_candidate IS '搜索引擎与 LLM 发现的日内新闻候选池,尚未直接进入正式日报事实层';
COMMENT ON COLUMN intraday_news_candidate.candidate_urls IS '候选来源 URL 数组,按发现层输出原样保留';
COMMENT ON COLUMN intraday_news_candidate.discovery_evidence IS '发现阶段原始证据 JSONB例如搜索命中、LLM 归纳结果';
COMMENT ON COLUMN intraday_news_candidate.normalized_key IS '同日同事件的去重键,避免重复发现候选';
CREATE TABLE IF NOT EXISTS intraday_news_verification (
id BIGSERIAL PRIMARY KEY,
candidate_id BIGINT NOT NULL REFERENCES intraday_news_candidate(id) ON DELETE CASCADE,
verified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
verifier_source TEXT NOT NULL,
verifier_url TEXT,
verifier_status TEXT NOT NULL,
extracted_facts JSONB NOT NULL DEFAULT '{}'::jsonb,
notes TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'chk_intraday_news_verification_status'
) THEN
ALTER TABLE intraday_news_verification
ADD CONSTRAINT chk_intraday_news_verification_status
CHECK (verifier_status IN ('matched', 'contradicted', 'insufficient', 'error'));
END IF;
END
$$;
CREATE INDEX IF NOT EXISTS idx_intraday_news_verification_candidate_verified_at
ON intraday_news_verification(candidate_id, verified_at DESC);
CREATE INDEX IF NOT EXISTS idx_intraday_news_verification_source
ON intraday_news_verification(verifier_source);
CREATE INDEX IF NOT EXISTS idx_intraday_news_verification_status
ON intraday_news_verification(verifier_status);
COMMENT ON TABLE intraday_news_verification IS '日内新闻候选的验证轨迹,记录验证来源、状态和提取事实';
COMMENT ON COLUMN intraday_news_verification.extracted_facts IS '验证阶段提取出的结构化事实 JSONB';
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM pg_trigger
WHERE tgname = 'intraday_news_candidate_updated_at'
) THEN
CREATE TRIGGER intraday_news_candidate_updated_at
BEFORE UPDATE ON intraday_news_candidate
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
END IF;
END
$$;