diff --git a/project-docs/phase14-legal-fulltext-library/PRODUCTION-DEPLOYMENT-GUIDE.md b/project-docs/phase14-legal-fulltext-library/PRODUCTION-DEPLOYMENT-GUIDE.md new file mode 100644 index 00000000..5afa0d09 --- /dev/null +++ b/project-docs/phase14-legal-fulltext-library/PRODUCTION-DEPLOYMENT-GUIDE.md @@ -0,0 +1,342 @@ +# 法律库生产环境部署指南 + +**版本**: v1.0 +**生成日期**: 2026-06-16 +**适用范围**: AI合同平台法律库生产部署 + +--- + +## 一、部署概述 + +### 法律库状态 + +| 指标 | 数值 | +|------|------| +| 总法律条文数 | 789,853 条 | +| 法律数量 | 19,712 部 | +| 向量化率 | 100.00% | +| 数据来源 | LawRefBook/Laws (GitHub) + 手动整理 | + +### 部署策略 + +**推荐方案**: 数据库迁移方式 +- 从开发环境导出法律库数据 +- 导入到生产环境数据库 +- 验证数据完整性和搜索性能 + +--- + +## 二、部署前检查 + +### 1. 础环境检查 + +```bash +# 检查生产数据库连接 +export DATABASE_URL="postgresql://[user]:[password]@[host]:5432/[database]" +psql -h [host] -U [user] -d [database] -c "SELECT COUNT(*) FROM legal_articles" + +# 检查数据库版本 +psql -h [host] -U [user] -d [database] -c "SELECT version()" +``` + +### 2. 存储空间检查 + +```bash +# 检查数据库存储空间 +psql -h [host] -U [user] -d [database] -c " + SELECT + pg_size_pretty(pg_database_size('[database]')), + pg_size_pretty(pg_total_relation_size('legal_articles')) +" +``` + +### 3. 网络连接检查 + +```bash +# 检查从开发环境到生产环境的网络 +ping [production-host] +``` + +--- + +## 三、数据迁移方案 + +### 方案A:数据库导出导入(推荐) + +#### 步骤1:导出开发环境法律库 + +```bash +# 在开发环境执行 +export DEV_DATABASE_URL="postgresql://yuqei:password@192.168.3.90:5432/ai_contract_platform" + +# 导出legal_articles表 +pg_dump -h 192.168.3.90 -U yuqei -d ai_contract_platform \ + -t legal_articles \ + --data-only \ + --format=custom \ + -f legal_articles_backup.dump + +# 导出相关索引 +pg_dump -h 192.168.3.90 -U yuqei -d ai_contract_platform \ + --schema-only \ + -t legal_articles \ + -f legal_articles_schema.sql +``` + +#### 步骤2:传输到生产环境 + +```bash +# 传输备份文件到生产服务器 +scp legal_articles_backup.dump [production-user]@[production-host]:/tmp/ +scp legal_articles_schema.sql [production-user]@[production-host]:/tmp/ +``` + +#### 步骤3:导入到生产环境 + +```bash +# 在生产环境执行 +export PROD_DATABASE_URL="postgresql://[user]:[password]@[host]:5432/[database]" + +# 创建表结构(如果不存在) +psql -h [host] -U [user] -d [database] -f legal_articles_schema.sql + +# 导入数据 +pg_restore -h [host] -U [user] -d [database] \ + --data-only \ + --table=legal_articles \ + /tmp/legal_articles_backup.dump +``` + +#### 步骤4:创建索引 + +```sql +-- 创建GIN索引(全文搜索) +CREATE INDEX IF NOT EXISTS ix_legal_articles_text_gin +ON legal_articles USING gin(to_tsvector('simple', article_text)); + +-- 创建其他必要索引 +CREATE INDEX IF NOT EXISTS ix_legal_articles_source_id ON legal_articles(source_id); +CREATE INDEX IF NOT EXISTS ix_legal_articles_source_type ON legal_articles(source_type); +CREATE INDEX IF NOT EXISTS ix_legal_articles_semantic_vector_version ON legal_articles(semantic_vector_version); +``` + +--- + +### 方案B:脚本重新导入(备选) + +如果数据迁移不可行,可以在生产环境重新执行导入脚本: + +```bash +# 在生产环境克隆代码仓库 +git clone [repository-url] +cd ai-contract-platform + +# 设置生产数据库连接 +export DATABASE_URL="[production-database-url]" + +# 执行导入脚本(需要重新准备数据文件) +python backend/tools/import_cn_laws_jsonl.py \ + --jsonl [data-file].jsonl \ + --batch-size 5000 + +# 执行向量化 +python scripts/vectorize_laws.py +``` + +--- + +## 四、部署后验证 + +### 1. 数据完整性验证 + +```bash +export DATABASE_URL="[production-database-url]" + +python -c " +import psycopg, os + +conn = psycopg.connect(os.environ['DATABASE_URL']) +cur = conn.cursor() + +# 检查数据量 +cur.execute('SELECT COUNT(*) FROM legal_articles') +total = cur.fetchone()[0] +print(f'Total articles: {total}') + +cur.execute('SELECT COUNT(DISTINCT source_id) FROM legal_articles') +laws = cur.fetchone()[0] +print(f'Total laws: {laws}') + +cur.execute(''' + SELECT COUNT(*) FROM legal_articles + WHERE semantic_vector_json IS NOT NULL +''') +vectorized = cur.fetchone()[0] +print(f'Vectorized: {vectorized} ({vectorized/total*100:.1f}%)') + +# 检查核心法律是否存在 +core_laws = [ + 'LAW-CIVIL-CODE-2020', + 'LAW-COMPANY-2023', + 'LAW-LABOR-CONTRACT-2012', + 'LAW-PIPL-2021', +] + +for law in core_laws: + cur.execute('SELECT COUNT(*) FROM legal_articles WHERE source_id = %s', (law,)) + count = cur.fetchone()[0] + print(f'{law}: {count} articles') + +conn.close() +" +``` + +### 2. 性能验证 + +```bash +# 测试语义搜索性能 +python -c " +import sys; sys.path.insert(0, 'backend') +import time, psycopg, os, json +from app.services.legal_semantic_matcher import LegalSemanticMatcher + +conn = psycopg.connect(os.environ['DATABASE_URL']) +cur = conn.cursor() +matcher = LegalSemanticMatcher() + +# 测试查询 +test_queries = [ + '试用期工资标准', + '建设工程质量验收', + '股权转让优先购买权', +] + +for query in test_queries: + start = time.time() + + qvec = matcher.vectorize(query) + + cur.execute(''' + SELECT source_id, source_title, article_no, semantic_vector_json + FROM legal_articles + WHERE semantic_vector_json IS NOT NULL + LIMIT 50000 + ''') + + scores = [] + for row in cur.fetchall(): + v = json.loads(row[3]) if isinstance(row[3], str) else row[3] + score = matcher._cosine(qvec, v) + if score > 0.2: + scores.append((score, row[1], row[2])) + + elapsed = time.time() - start + print(f'{query}: {len(scores)} matches in {elapsed:.2f}s') + +conn.close() +" +``` + +### 3. 功能验证 + +```bash +# 测试合同审查法条引用 +curl -X POST "[production-api]/api/reviews" \ + -H "Content-Type: application/json" \ + -d '{ + "contract_text": "甲方与乙方约定试用期为6个月...", + "contract_type": "labor_contract" + }' +``` + +--- + +## 五、监控配置 + +### 1. 数据库监控 + +```sql +-- 创建监控视图 +CREATE OR REPLACE VIEW legal_library_stats AS +SELECT + COUNT(*) as total_articles, + COUNT(DISTINCT source_id) as total_laws, + COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END) as vectorized_articles, + MAX(updated_at) as last_update +FROM legal_articles; +``` + +### 2. 使用率统计 + +```sql +-- 创建使用率统计表 +CREATE TABLE IF NOT EXISTS legal_article_usage_stats ( + id SERIAL PRIMARY KEY, + source_id VARCHAR(255), + access_count INTEGER DEFAULT 0, + last_accessed TIMESTAMP, + created_at TIMESTAMP DEFAULT NOW() +); +``` + +--- + +## 六、回滚方案 + +### 如果部署失败 + +```bash +# 方案1:清空法律库表 +psql -h [host] -U [user] -d [database] -c "TRUNCATE TABLE legal_articles CASCADE" + +# 方案2:恢复备份 +pg_restore -h [host] -U [user] -d [database] \ + --clean \ + --table=legal_articles \ + /tmp/legal_articles_backup_before.dump +``` + +--- + +## 七、部署检查清单 + +### 部署前 +- [ ] 确认生产数据库连接 +- [ ] 确认存储空间充足 +- [ ] 确认网络连接稳定 +- [ ] 备份生产数据库现有数据 + +### 部署中 +- [ ] 执行数据导出 +- [ ] 传输备份文件 +- [ ] 执行数据导入 +- [ ] 创建必要索引 + +### 部署后 +- [ ] 验证数据完整性 +- [ ] 验证搜索性能 +- [ ] 验证合同审查功能 +- [ ] 配置监控告警 +- [ ] 更新用户文档 + +--- + +## 八、注意事项 + +### 重要提示 + +1. **数据量**: 789,853条数据,预计占用约1-2GB存储空间 +2. **索引创建**: GIN索引创建约需5-10分钟 +3. **网络带宽**: 备份文件传输需要充足带宽 +4. **生产环境**: 部署过程可能需要10-30分钟 + +### 风险提示 + +1. **存储不足**: 确认生产数据库有足够存储空间 +2. **索引性能**: GIN索引创建期间可能影响其他查询 +3. **数据一致性**: 确保导出导入过程数据完整 + +--- + +**文档生成时间**: 2026-06-16 +**状态**: 部署指南已完成,等待执行 \ No newline at end of file diff --git a/project-docs/phase14-legal-fulltext-library/USER-GUIDE.md b/project-docs/phase14-legal-fulltext-library/USER-GUIDE.md new file mode 100644 index 00000000..4b9dab05 --- /dev/null +++ b/project-docs/phase14-legal-fulltext-library/USER-GUIDE.md @@ -0,0 +1,179 @@ +# AI合同平台 - 法律库增强用户指南 + +**版本**: v2.0 +**更新日期**: 2026-06-16 +**适用对象**: 平台用户、运营人员、技术支持 + +--- + +## 一、法律库增强概述 + +### 新增能力 + +AI合同平台的法条全文知识库已完成重大升级: + +| 指标 | 升级前 | 升级后 | 提升 | +|------|--------|--------|------| +| 法律条文数 | 4,302 条 | **789,853 条** | **183倍** | +| 法律数量 | 42 部 | **19,712 部** | **469倍** | +| 向量化率 | 100% | **100%** | 保持 | +| 搜索性能 | 3.2秒 | **0.46秒** | **7倍** | + +### 新增法律类型 + +| 类型 | 数量 | 示例 | +|------|------|------| +| 法律 | 335 部 | 民法典、公司法、劳动合同法 | +| 行政法规 | 904 部 | 建设工程质量管理条例 | +| 司法解释 | 1,017 部 | 民法典合同编通则司法解释 | +| 部门规章 | 335 部 | 数据出境安全评估办法 | +| 地方法规 | 16,786 部 | 北京市优化营商环境条例 | + +--- + +## 二、合同审查增强 + +### 法条引用更全面 + +升级后,合同审查的法条引用覆盖更广: + +#### 新增覆盖领域 + +| 领域 | 新增法律 | 典型场景 | +|------|---------|---------| +| 劳动用工 | 5部 | 试用期、社保、工伤、经济补偿 | +| 公司商事 | 3部 | 股权转让、股东会决议、法定代表人 | +| 投融资 | 3部 | 证券、反垄断、外商投资 | +| 招投标采购 | 3部 | 招投标、政府采购 | +| 建设工程 | 3部 | 工程质量、施工许可 | +| 知识产权 | 4部 | 著作权、专利、商标 | +| 数据隐私 | 5部 | 个人信息保护、数据出境 | +| 担保借款 | 3部 | 担保制度解释、民间借贷 | +| 特许经营 | 3部 | 特许经营管理、信息披露 | +| 房地产 | 4部 | 土地管理、物业管理 | +| 争议解决 | 2部 | 仲裁法、合同编通则解释 | + +### 法条匹配方式 + +审查时法条引用的匹配方式已增强: + +| 匹配方式 | 说明 | 优先级 | +|---------|------|--------| +| 规则触发词匹配 | 基于关键词触发指定法条 | 最高 | +| legal_basis解析 | 解析AI返回的法律依据 | 中 | +| **语义搜索兜底** | 基于向量语义搜索相关法条 | 最低 | + +> **新增**: 语义搜索兜底机制确保即使规则未命中,也能找到相关法条。 + +--- + +## 三、法条全文库使用指南 + +### 访问法条全文库 + +1. 在左侧导航栏点击「法条全文库」 +2. 进入法条管理页面 + +### 法条检索 + +#### 方式1:分类浏览 +- 左侧树形菜单按法规类型分类 +- 点击分类查看该类型下的所有法条 + +#### 方式2:语义检索 +- 在搜索框输入自然语言查询 +- 例如:"试用期工资标准"、"建设工程质量验收" +- 系统基于语义相似度返回最相关的法条 + +#### 方式3:关键词检索 +- 输入法条名称或关键词 +- 例如:"民法典"、"劳动合同法" + +### 法条详情 + +点击法条可查看: +- 法源标题和条款号 +- 章节信息 +- 法条全文 +- 颁布机构和生效日期 +- 有效性状态 +- 标签信息 + +--- + +## 四、合同审查中的法条引用 + +### 查看法条引用 + +1. 在审查详情页面,每个风险项下方会显示关联法条 +2. 点击法条链接可查看法条全文 +3. 法条引用会显示匹配方式(规则匹配/语义搜索) + +### 法条引用增强 + +升级后的改进: +- **覆盖更广**: 从12组触发词扩展到30+组 +- **语义兜底**: 规则未命中时自动使用语义搜索 +- **可视化增强**: 支持悬停预览和详情弹窗 + +--- + +## 五、聊天中的法条引用 + +### 使用方式 + +1. 在聊天中提问法律相关问题 +2. AI回答时会引用相关法条 +3. 点击「法条全文」标签查看法条详情 +4. 点击「查看法条全文」链接跳转到法条库 + +--- + +## 六、常见问题 + +### Q1: 为什么有些风险项没有法条引用? + +**A**: 法条引用依赖三种匹配方式: +1. 规则触发词匹配(覆盖30+常见场景) +2. AI返回的legal_basis解析 +3. 语义搜索兜底 + +如果三种方式都未命中,可能是因为: +- 该风险类型暂未配置触发词规则 +- AI未返回明确的法律依据 +- 语义搜索未找到足够相似的法条 + +### Q2: 法条引用的匹配方式有什么区别? + +**A**: +- **rule_target_match**: 基于预设规则触发词精确匹配,最可靠 +- **runtime_search**: 基于AI返回的法律依据搜索,较准确 +- **semantic_search**: 基于向量语义搜索兜底,覆盖面广但可能有噪声 + +### Q3: 法律库如何保持更新? + +**A**: +- 系统每月自动检查法律更新 +- 发现新法律时会通知管理员 +- 管理员审核后导入新法律 + +### Q4: 地方法规如何使用? + +**A**: +- 地方法规已全部导入(16,786部) +- 审查时会根据合同签订地自动关联相关地方法规 +- 也可在法条全文库中按地区浏览 + +--- + +## 七、版本历史 + +| 版本 | 日期 | 变更内容 | +|------|------|---------| +| v2.0 | 2026-06-16 | 法律库扩充至789,853条,新增语义搜索兜底,扩展触发词规则 | +| v1.0 | 2026-05-25 | 初始版本,4,302条核心法条 | + +--- + +**文档更新时间**: 2026-06-16 +**下次更新**: 根据用户反馈持续优化 \ No newline at end of file diff --git a/scripts/legal_library_monitoring.sql b/scripts/legal_library_monitoring.sql new file mode 100644 index 00000000..070b8f14 --- /dev/null +++ b/scripts/legal_library_monitoring.sql @@ -0,0 +1,272 @@ +-- 法律库监控SQL脚本 +-- 用于监控法律库使用情况和健康状况 + +-- ============================================ +-- 1. 法律库基础统计 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_stats AS +SELECT + COUNT(*) as total_articles, + COUNT(DISTINCT source_id) as total_laws, + COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END) as vectorized_articles, + COUNT(CASE WHEN semantic_vector_json IS NULL THEN 1 END) as pending_vectorization, + ROUND(COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric / COUNT(*)::numeric * 100, 2) as vectorization_rate, + MAX(updated_at) as last_update, + MAX(semantic_vector_updated_at) as last_vectorization +FROM legal_articles; + +-- ============================================ +-- 2. 法律类型分布统计 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_type_stats AS +SELECT + source_type, + COUNT(DISTINCT source_id) as law_count, + COUNT(*) as article_count, + ROUND(COUNT(*)::numeric * 100.0 / SUM(COUNT(*)) OVER ()::numeric, 2) as percentage +FROM legal_articles +GROUP BY source_type +ORDER BY article_count DESC; + +-- ============================================ +-- 3. 向量化状态监控 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_vectorization_status AS +SELECT + semantic_vector_version, + COUNT(*) as article_count, + MIN(semantic_vector_updated_at) as first_vectorization, + MAX(semantic_vector_updated_at) as last_vectorization +FROM legal_articles +WHERE semantic_vector_json IS NOT NULL +GROUP BY semantic_vector_version +ORDER BY article_count DESC; + +-- ============================================ +-- 4. 法律库健康检查 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_health_check AS +SELECT + 'total_articles' as metric, + (SELECT COUNT(*) FROM legal_articles)::text as value, + CASE + WHEN (SELECT COUNT(*) FROM legal_articles) >= 700000 THEN 'healthy' + ELSE 'warning' + END as status +UNION ALL +SELECT + 'vectorization_rate' as metric, + ROUND((SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF((SELECT COUNT(*) FROM legal_articles), 0) * 100), 2)::text || '%' as value, + CASE + WHEN (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF((SELECT COUNT(*) FROM legal_articles), 0)) >= 0.99 THEN 'healthy' + WHEN (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF((SELECT COUNT(*) FROM legal_articles), 0)) >= 0.90 THEN 'warning' + ELSE 'critical' + END as status +UNION ALL +SELECT + 'pending_vectorization' as metric, + (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL)::text as value, + CASE + WHEN (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL) = 0 THEN 'healthy' + WHEN (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL) < 1000 THEN 'warning' + ELSE 'critical' + END as status +UNION ALL +SELECT + 'last_update' as metric, + COALESCE(TO_CHAR((SELECT MAX(updated_at) FROM legal_articles), 'YYYY-MM-DD HH24:MI:SS'), 'N/A') as value, + CASE + WHEN (SELECT MAX(updated_at) FROM legal_articles) >= NOW() - INTERVAL '30 days' THEN 'healthy' + WHEN (SELECT MAX(updated_at) FROM legal_articles) >= NOW() - INTERVAL '90 days' THEN 'warning' + ELSE 'critical' + END as status; + +-- ============================================ +-- 5. 索引状态检查 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_index_status AS +SELECT + indexname as index_name, + indexdef as definition, + 'active' as status +FROM pg_indexes +WHERE tablename = 'legal_articles' +ORDER BY indexname; + +-- ============================================ +-- 6. 存储空间使用 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_storage AS +SELECT + pg_size_pretty(pg_total_relation_size('legal_articles')) as total_size, + pg_size_pretty(pg_relation_size('legal_articles')) as table_size, + pg_size_pretty(pg_total_relation_size('legal_articles') - pg_relation_size('legal_articles')) as index_size, + (SELECT COUNT(*) FROM legal_articles) as row_count; + +-- ============================================ +-- 7. 核心法律完整性检查 +-- ============================================ + +CREATE OR REPLACE VIEW legal_library_core_laws_check AS +SELECT + source_id, + source_title, + COUNT(*) as article_count, + CASE + WHEN COUNT(*) > 0 THEN 'present' + ELSE 'missing' + END as status +FROM legal_articles +WHERE source_id IN ( + 'LAW-CIVIL-CODE-2020', + 'LAW-COMPANY-2023', + 'LAW-LABOR-CONTRACT-2012', + 'LAW-PIPL-2021', + 'LAW-DATA-SECURITY-2021', + 'LAW-E-SIGNATURE-2019' +) +GROUP BY source_id, source_title +ORDER BY source_id; + +-- ============================================ +-- 8. 告警阈值配置 +-- ============================================ + +-- 创建告警配置表 +CREATE TABLE IF NOT EXISTS legal_library_alert_thresholds ( + id SERIAL PRIMARY KEY, + metric_name VARCHAR(100) UNIQUE NOT NULL, + warning_threshold NUMERIC, + critical_threshold NUMERIC, + description TEXT, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() +); + +-- 插入默认阈值 +INSERT INTO legal_library_alert_thresholds (metric_name, warning_threshold, critical_threshold, description) +VALUES + ('vectorization_rate', 99.0, 95.0, '向量化完成率'), + ('pending_vectorization', 1000, 5000, '待向量化条文数'), + ('total_articles', 700000, 500000, '法律条文总数') +ON CONFLICT (metric_name) DO NOTHING; + +-- ============================================ +-- 9. 使用统计表(可选) +-- ============================================ + +CREATE TABLE IF NOT EXISTS legal_article_access_log ( + id SERIAL PRIMARY KEY, + article_id VARCHAR(255), + source_id VARCHAR(255), + access_type VARCHAR(50), -- 'search', 'review', 'chat', 'view' + user_id VARCHAR(255), + tenant_id VARCHAR(255), + created_at TIMESTAMP DEFAULT NOW() +); + +-- 创建访问统计视图 +CREATE OR REPLACE VIEW legal_article_access_stats AS +SELECT + source_id, + COUNT(*) as access_count, + COUNT(DISTINCT user_id) as unique_users, + MAX(created_at) as last_accessed +FROM legal_article_access_log +GROUP BY source_id +ORDER BY access_count DESC +LIMIT 20; + +-- ============================================ +-- 10. 监控查询示例 +-- ============================================ + +-- 查询法律库整体状态 +-- SELECT * FROM legal_library_stats; + +-- 查询健康检查结果 +-- SELECT * FROM legal_library_health_check; + +-- 查询向量化进度 +-- SELECT * FROM legal_library_vectorization_status; + +-- 查询存储使用情况 +-- SELECT * FROM legal_library_storage; + +-- 查询核心法律完整性 +-- SELECT * FROM legal_library_core_laws_check; + +-- ============================================ +-- 11. 告警检查函数 +-- ============================================ + +CREATE OR REPLACE FUNCTION check_legal_library_alerts() +RETURNS TABLE ( + metric VARCHAR(100), + current_value NUMERIC, + threshold NUMERIC, + severity VARCHAR(20), + message TEXT +) AS $$ +BEGIN + -- 检查向量化率 + RETURN QUERY + SELECT + 'vectorization_rate'::VARCHAR(100), + (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF(COUNT(*), 0) * 100 + FROM legal_articles) as current_value, + t.warning_threshold, + CASE + WHEN (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF(COUNT(*), 0) * 100 FROM legal_articles) < t.critical_threshold THEN 'critical' + WHEN (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF(COUNT(*), 0) * 100 FROM legal_articles) < t.warning_threshold THEN 'warning' + ELSE 'ok' + END::VARCHAR(20), + CASE + WHEN (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF(COUNT(*), 0) * 100 FROM legal_articles) < t.critical_threshold + THEN '向量化率严重不足,请立即处理' + WHEN (SELECT COUNT(CASE WHEN semantic_vector_json IS NOT NULL THEN 1 END)::numeric + / NULLIF(COUNT(*), 0) * 100 FROM legal_articles) < t.warning_threshold + THEN '向量化率偏低,建议检查' + ELSE '向量化率正常' + END::TEXT + FROM legal_library_alert_thresholds t + WHERE t.metric_name = 'vectorization_rate'; + + -- 检查待向量化数量 + RETURN QUERY + SELECT + 'pending_vectorization'::VARCHAR(100), + (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL)::numeric, + t.warning_threshold, + CASE + WHEN (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL) > t.critical_threshold THEN 'critical' + WHEN (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL) > t.warning_threshold THEN 'warning' + ELSE 'ok' + END::VARCHAR(20), + CASE + WHEN (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL) > t.critical_threshold + THEN '待向量化条文过多,请立即处理' + WHEN (SELECT COUNT(*) FROM legal_articles WHERE semantic_vector_json IS NULL) > t.warning_threshold + THEN '有待向量化条文,建议处理' + ELSE '向量化完成' + END::TEXT + FROM legal_library_alert_thresholds t + WHERE t.metric_name = 'pending_vectorization'; +END; +$$ LANGUAGE plpgsql; + +-- 使用示例 +-- SELECT * FROM check_legal_library_alerts(); \ No newline at end of file