feat: add production deployment guide and monitoring tools

Production deployment:
- Add deployment guide with data migration steps
- Add deployment checklist and rollback plan
- Add performance verification steps

User documentation:
- Add user guide for law library enhancement
- Document new features and coverage areas
- Add FAQ section

Monitoring and alerts:
- Add monitoring SQL script with health checks
- Add alert thresholds configuration
- Add storage and access statistics

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-16 22:31:38 +08:00
parent 4f22e2965c
commit 182a1ba663
3 changed files with 793 additions and 0 deletions
@@ -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
**状态**: 部署指南已完成,等待执行
@@ -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
**下次更新**: 根据用户反馈持续优化
+272
View File
@@ -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();