Files
llm-intelligence/db/migrations/017_intraday_news_candidates.sql

107 lines
4.3 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 日内新闻候选与验证持久化结构
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
$$;