Files
GovAI/docs/add-domain-guide.md
2026-06-15 23:48:37 +08:00

1039 lines
37 KiB
Markdown
Raw Permalink 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.
# 新增行业领域配置指南
本文档描述如何为政智通平台新增一个行业领域的完整 AI 应用配置。
> 本指南严格遵循 [APP-TYPE-STANDARD.md](./APP-TYPE-STANDARD.md) 和 [UI-STYLE-GUIDE.md](./UI-STYLE-GUIDE.md) 的规范要求。
---
## 整体流程
```
1. 新增机构 → 2. 创建用户 → 3. 新增分类 → 4. 注册分类图标与颜色
→ 5. 编写应用种子数据 → 6. 创建知识库与文档 → 7. 关联知识库到应用
→ 8. 配置 Embedding 服务 → 9. 部署 SQL → 10. 文档分片与索引
→ 11. 前端注册(如需特殊UI) → 12. 更新 run.md → 13. 验证
```
> **重要提醒:** 步骤 8(Embedding 配置)必须在步骤 10(分片索引)之前完成,否则分片后无法生成向量,知识库语义检索将失效。
---
## 步骤 1:新增机构
`organizations` 表中注册新机构。参照 `server/migrations/000013_organizations.up.sql` 中的已有机构。
```sql
INSERT INTO organizations (id, name, slug, short_name, description, sort_order) VALUES
('a0000000-0000-0000-0000-0000000000XX', '机构全称', 'slug缩写', '简称', '机构职能描述', )
ON CONFLICT (id) DO NOTHING;
```
**字段说明:**
| 字段 | 说明 | 约束 |
|------|------|------|
| `id` | 机构UUID | 使用 `a0000000-0000-0000-0000-0000000000XX` 前缀,序号递增 |
| `name` | 机构全称 | 如「律师事务所」 |
| `slug` | URL 标识 | 英文缩写,如 `lvsuo``gongan``fagai` |
| `short_name` | 简称 | 如「律所」 |
| `sort_order` | 排序号 | 整数,现有机构已占用 1-10 |
**已有机构(000013_organizations.up.sql):**
| 序号 | 机构 | slug | UUID 后缀 |
|------|------|------|----------|
| 1 | 科学技术局 | `keji` | `01` |
| 2 | 公安局 | `gongan` | `02` |
| 3 | 发展和改革局 | `fagai` | `03` |
| 4 | 教育局 | `jiaoyu` | `04` |
| 5 | 人力资源和社会保障局 | `renshe` | `05` |
| 6 | 财政局 | `caizheng` | `06` |
| 7 | 住房和城乡建设局 | `zhujian` | `07` |
| 8 | 市场监督管理局 | `shijianju` | `08` |
| **9** | **律师事务所** | **`lvsuo`** | **`09`** |
| **10** | **信访局** | **`xinfang`** | **`10`** |
---
## 步骤 2:创建用户
为新机构创建用户账号。密码统一使用 `admin123`,通过已有用户获取密码 hash。
参照 `server/migrations/seed_multi_tenant_users.sql`
```sql
DO $$
DECLARE
pwd_hash TEXT;
new_org UUID := 'a0000000-0000-0000-0000-0000000000XX';
BEGIN
-- 获取已有用户的密码hashadmin123
SELECT password_hash INTO pwd_hash FROM users WHERE email = 'admin@govai.gov.cn';
INSERT INTO users (id, name, email, password_hash, role, status, org_id) VALUES
(gen_random_uuid(), '机构管理员', 'xx-admin@govai.gov.cn', pwd_hash, 'admin', 'active', new_org),
(gen_random_uuid(), '张三', 'zhangsan@govai.gov.cn', pwd_hash, 'creator', 'active', new_org),
(gen_random_uuid(), '李四', 'lisi@govai.gov.cn', pwd_hash, 'user', 'active', new_org)
ON CONFLICT (email) DO NOTHING;
END $$;
```
**用户角色说明:**
| 角色 | 说明 | 每机构建议数量 |
|------|------|---------------|
| `admin` | 机构管理员,可管理本机构应用和用户 | 1 个 |
| `creator` | 应用创建者,可创建和编辑应用 | 1-2 个 |
| `user` | 普通用户,仅使用应用 | 1-2 个 |
**邮箱命名规范:**
- 管理员:`{机构缩写}-admin@govai.gov.cn`,如 `ls-admin@govai.gov.cn`
- 其他用户:`{姓名拼音}@govai.gov.cn`,如 `linlv@govai.gov.cn`
---
## 步骤 3:新增分类
`server/migrations/` 下新建迁移文件(如 `seed_<领域>.sql`),插入分类。
**每个领域建议 3-4 个分类**,分类通过 `org_id` 绑定机构:
```sql
INSERT INTO categories (name, slug, icon, sort_order, org_id) VALUES
('信访受理', 'xinfang-accept', 'inbox', 10, 'a0000000-0000-0000-0000-000000000010'),
('政策答复', 'xinfang-reply', 'message-square-reply', 20, 'a0000000-0000-0000-0000-000000000010'),
('矛盾调解', 'xinfang-mediate', 'handshake', 30, 'a0000000-0000-0000-0000-000000000010'),
('督查督办', 'xinfang-supervise', 'clipboard-check', 40, 'a0000000-0000-0000-0000-000000000010')
ON CONFLICT (slug) DO NOTHING;
```
**字段说明:**
| 字段 | 说明 | 约束 |
|------|------|------|
| `name` | 分类显示名(中文) | 不超过50字 |
| `slug` | URL 标识(英文,唯一) | 格式 `{领域缩写}-{功能}`,如 `legal-service` |
| `icon` | **Lucide 图标名**(严禁 emoji | 如 `scale``gavel``file-text` |
| `sort_order` | 排序权重,数字越小越靠前 | 整数 |
| `org_id` | 所属机构 UUID | 可选,用于按机构过滤分类 |
> 已有分类见 `000002_categories_and_applications.up.sql`slug 不要重复。
---
## 步骤 4:注册分类图标与颜色
`apps/web/src/lib/category-config.ts` 中注册新分类的图标和颜色。
**必须遵守 UI-STYLE-GUIDE.md 规范:**
- 使用 **Lucide React 线条图标**stroke),不用填充图标
- 颜色以 **蓝色系为主色调**,辅助色参照下表
- **严禁使用 emoji 字符**
| 分类类型 | 图标 | 颜色 |
|---------|------|------|
| 已有:公文写作 | `FileSignature` | `bg-blue-100 text-blue-800` |
| 已有:政策解读 | `Scale` | `bg-indigo-100 text-indigo-800` |
| 已有:数据分析 | `BarChartBig` | `bg-emerald-100 text-emerald-700` |
| 已有:便民服务 | `HeadphonesIcon` | `bg-amber-100 text-amber-700` |
| 已有:组织人事 | `UserCog` | `bg-sky-100 text-sky-700` |
| 已有:招商引资 | `TrendingUp` | `bg-violet-100 text-violet-700` |
| 已有:翻译外事 | `Languages` | `bg-teal-100 text-teal-700` |
| 已有:综合应用 | `LayoutGrid` | `bg-gray-100 text-gray-700` |
| **律所-案件代理** | `Gavel` | `bg-blue-100 text-blue-800` |
| **律所-合同服务** | `FileCheck` | `bg-indigo-100 text-indigo-800` |
| **律所-法律研究** | `Search` | `bg-emerald-100 text-emerald-700` |
| **律所-合规风控** | `ShieldCheck` | `bg-amber-100 text-amber-700` |
| **信访-信访受理** | `Inbox` | `bg-blue-100 text-blue-800` |
| **信访-政策答复** | `MessageSquareReply` | `bg-indigo-100 text-indigo-800` |
| **信访-矛盾调解** | `Handshake` | `bg-amber-100 text-amber-700` |
| **信访-督查督办** | `ClipboardCheck` | `bg-emerald-100 text-emerald-700` |
---
## 步骤 5:编写应用种子数据
平台支持 **6 种应用类型**,配置方式各异。以下严格遵循 APP-TYPE-STANDARD.md。
### 通用字段规范
| 字段 | 说明 | 重要约束 |
|------|------|----------|
| `icon_url` | **必须使用 Lucide 图标名**,严禁 emoji | 如 `scale``file-text` |
| `slug` | 英文标识,全局唯一 | 格式 `{领域}-{功能}`,如 `legal-research` |
| `temperature` | 准确性要求高的领域用低值 | 法律/医疗 0.2-0.4,公文 0.5,创意 0.7+ |
| `long_description` | Markdown 格式详情 | **必须包含"功能介绍"和"使用方法"两节** |
| `app_config` | JSONB 配置 | `system_prompt` 为必填字段 |
### long_description 标准格式
```markdown
## 功能介绍
简要描述功能:
- 功能点1
- 功能点2
- 功能点3
## 使用方法
使用说明文字。
```
### 命名规范(摘自 APP-TYPE-STANDARD.md
- 新机构分类 slug 格式:`{机构缩写}-{功能}`,如 `fagai-writing``gongan-policy`
- 应用名统一使用"XX助手"或"XX生成"格式
- 同类应用跨机构使用相同名称
---
### 3.1 对话型 (chatbot)
**UI 模式:** 左侧对话历史列表 + 中间对话区域 + 底部输入框
**适用场景:** 政策问答、法规咨询、通用问答类应用
**必填字段(参照 APP-TYPE-STANDARD.md):**
| 字段 | 必填 | 说明 |
|------|------|------|
| `dify_app_type` | 必填 | 值为 `chatbot` |
| `welcome_message` | 必填 | 首次进入时的欢迎语,如"您好!我是XXX助手。" |
| `suggested_prompts` | 必填 | JSON数组,3-4条推荐提问,显示为可点击按钮 |
| `app_config.system_prompt` | 必填 | 系统提示词,定义AI角色和回答风格 |
| `app_config.model` | 可选 | 模型名称,默认 `qwen-plus` |
| `app_config.temperature` | 可选 | 温度参数,问答类建议 0.2-0.4 |
| `app_config.max_tokens` | 可选 | 最大输出token数 |
**SQL 模板:**
```sql
INSERT INTO applications (
id, name, slug, description, long_description, icon_url,
category_id, creator_id, status, visibility,
dify_app_type, dify_api_key,
welcome_message, suggested_prompts, app_config,
temperature, max_tokens
) VALUES (
'<UUID>',
'应用名称',
'app-slug',
'一句话描述(50字内)',
'## 功能介绍\n\n详细描述...\n\n## 使用方法\n\n说明文字。',
'scale', -- Lucide 图标名,严禁 emoji
(SELECT id FROM categories WHERE slug = '<分类slug>' LIMIT 1),
'00000000-0000-0000-0000-000000000001',
'approved', 'public',
'chatbot', 'app-placeholder',
'欢迎语,用户打开应用时显示',
'["建议提问1","建议提问2","建议提问3"]',
'{"system_prompt":"系统提示词","model":"qwen-plus","temperature":0.3,"max_tokens":4000}',
0.3, 8192
) ON CONFLICT (id) DO NOTHING;
```
**示例配置(参照 APP-TYPE-STANDARD.md):**
```json
{
"app_config": {
"system_prompt": "你是一个政策法规智能问答助手,熟悉中国各级政府的法律法规和政策文件。请准确、严谨地回答用户的政策法规相关问题。",
"model": "qwen-plus",
"temperature": 0.3,
"max_tokens": 4000
},
"welcome_message": "您好!我是政策法规智能问答助手。您可以向我咨询各类法律法规和政策条款。",
"suggested_prompts": [
"最新的行政处罚法有哪些变化?",
"营商环境优化相关政策有哪些?",
"政府信息公开条例的适用范围?"
]
}
```
**UI 要素(参照 UI-STYLE-GUIDE.md):**
- 顶部:应用图标(Lucide)+ 应用名称 + 描述 + 右侧类型标签(`text-blue-800 bg-blue-100 rounded-full font-medium`
- 左侧:`+ 新对话` 按钮(`bg-blue-900 hover:bg-blue-800 text-white`+ 对话历史列表
- 中间:欢迎消息气泡 + 推荐提问按钮
- 底部:输入框(`rounded-lg`+ 发送按钮
- 所有 hover 效果使用 `transition-all duration-200`
---
### 3.2 公文写作型 (chatbot + DOC_WRITER_SLUGS)
**UI 模式:** 公文类型卡片网格 + 底部输入框
**适用场景:** 公文拟稿、公文写作助手
**触发条件:** `slug` 必须注册到前端 `DOC_WRITER_SLUGS` 集合
**必填字段:**
| 字段 | 必填 | 说明 |
|------|------|------|
| `dify_app_type` | 必填 | 值为 `chatbot` |
| `slug` | 必填 | 必须注册到前端 `DOC_WRITER_SLUGS` |
| `app_config.system_prompt` | 必填 | 包含《党政机关公文格式》(GB/T 9704) 相关指引 |
| `welcome_message` | 必填 | 如"您好!我是公文写作助手" |
| `suggested_prompts` | 必填 | 公文写作相关的推荐提问 |
**SQL 模板(数据库配置与 chatbot 相同):**
```sql
INSERT INTO applications (...) VALUES (
...
'chatbot', 'app-placeholder',
'您好!我是公文写作助手。',
'["帮我起草一份工作通知","拟一份年度总结报告"]',
'{"system_prompt":"你是一个专业的公文写作助手,精通《党政机关公文格式》国家标准(GB/T 9704..."}',
0.5, 8192
) ON CONFLICT (id) DO NOTHING;
```
**前端注册(必须):**`apps/web/src/app/(portal)/chat/[appId]/page.tsx` 中添加 slug
```typescript
const DOC_WRITER_SLUGS = new Set(["official-doc-writer", "fagai-doc-writer", "<新slug>"]);
```
**UI 要素:**
- 左侧:`+ 新建公文` 按钮 + 历史记录
- 中间:**选择公文类型**标题 + 12种公文类型卡片网格
- 底部:输入框 + 发送按钮
---
### 3.3 补全型 (completion)
**UI 模式:** 左侧输入区 + 右侧输出区
**适用场景:** 文本处理、摘要提取、翻译等单次输入输出型应用
**必填字段(参照 APP-TYPE-STANDARD.md):**
| 字段 | 必填 | 说明 |
|------|------|------|
| `dify_app_type` | 必填 | 值为 `completion` |
| `app_config.input_label` | 必填 | 输入区域标题,如"案情描述" |
| `app_config.output_label` | 必填 | 输出区域标题,如"法律文书" |
| `app_config.input_placeholder` | 必填 | 输入框占位文本 |
| `app_config.system_prompt` | 必填 | 系统提示词 |
**SQL 模板:**
```sql
INSERT INTO applications (...) VALUES (
...
'completion', 'app-placeholder',
NULL, -- completion 不需要 welcome_message
'{"system_prompt":"你是一个XX专家...",
"input_label":"案情描述",
"output_label":"法律文书",
"input_placeholder":"请输入案情要素..."
}',
0.5, 8192
) ON CONFLICT (id) DO NOTHING;
```
**示例配置:**
```json
{
"app_config": {
"input_label": "文件内容",
"output_label": "核心摘要",
"system_prompt": "你是一个政务文件分析专家。请对提供的文件进行分析,输出包含:一句话概要、核心要点、关键数据摘录、政策影响分析、行动建议。",
"input_placeholder": "粘贴需要提取摘要的文件内容..."
}
}
```
**UI 要素:**
- 顶部:应用名称 + 描述 + 右侧类型标签(`text-blue-800 bg-blue-100 rounded-full`
- 左侧:输入标签 + 大文本输入框(`rounded-lg`
- 右侧:输出标签 + 结果展示区域
- 底部:提交按钮(`bg-blue-900 hover:bg-blue-800 text-white`
---
### 3.4 工作流型 (workflow)
**UI 模式:** 步骤进度条 + 分步表单 + 上一步/下一步按钮
**适用场景:** 按步骤收集信息后生成报告/方案的应用
**必填字段(参照 APP-TYPE-STANDARD.md):**
| 字段 | 必填 | 说明 |
|------|------|------|
| `dify_app_type` | 必填 | 值为 `workflow` |
| `app_config.app_type` | 必填 | 值为 `workflow` |
| `app_config.steps` | 必填 | JSON数组,定义每个步骤的表单字段 |
| `app_config.system_prompt` | 必填 | 系统提示词 |
| `welcome_message` | 可选 | 步骤开始前的提示语 |
**steps 字段格式(参照 APP-TYPE-STANDARD.md):**
```json
{
"key": "字段标识",
"label": "步骤标题",
"type": "text | textarea | select",
"description": "步骤描述(可选)",
"placeholder": "输入提示",
"required": true,
"options": ["选项1", "选项2"]
}
```
**SQL 模板:**
```sql
INSERT INTO applications (...) VALUES (
...
'workflow', 'app-placeholder',
NULL,
'{"system_prompt":"你是XX评估专家...",
"app_type":"workflow",
"model":"qwen-plus",
"temperature":0.3,
"max_tokens":6000,
"steps":[
{"key":"case_type","label":"案件类型","type":"select",
"options":["民事纠纷","刑事案件","行政诉讼","合同纠纷"],"required":true},
{"key":"case_desc","label":"案情描述","type":"textarea",
"placeholder":"请详细描述案件事实...","required":true},
{"key":"evidence","label":"证据情况","type":"textarea",
"placeholder":"列出现有证据材料...","required":true},
{"key":"report_type","label":"报告类型","type":"select",
"options":["初步评估","详细分析","完整报告"],"required":true}
]
}',
0.3, 8192
) ON CONFLICT (id) DO NOTHING;
```
**UI 要素:**
- 顶部:返回按钮 + 应用图标 + 名称 + 描述 + 右侧"工作流"标签
- 步骤条:圆形标记 + 步骤名称 + 箭头连接,完成步骤用 `emerald-700`
- select 选项:彩色卡片网格 `grid-cols-2 md:grid-cols-3 lg:grid-cols-4`
- 选中状态:`ring-2 ring-purple-400 ring-offset-2 shadow-md`
- 底部:上一步/下一步按钮(`bg-blue-900 hover:bg-blue-800 text-white`
---
### 3.5 智能体型 (agent)
**UI 模式:** 类似 chatbot,但带有工具调用能力展示
**适用场景:** 需要调用多个工具进行综合分析的应用
**必填字段(参照 APP-TYPE-STANDARD.md):**
| 字段 | 必填 | 说明 |
|------|------|------|
| `dify_app_type` | 必填 | 值为 `agent` |
| `app_config.tools` | 必填 | 可用工具列表,如 `["法条检索","案例对比"]` |
| `app_config.system_prompt` | 必填 | 包含工具调用说明的系统提示词 |
| `welcome_message` | 必填 | 说明具备的能力 |
| `suggested_prompts` | 必填 | 推荐提问 |
**SQL 模板:**
```sql
INSERT INTO applications (...) VALUES (
...
'agent', 'app-placeholder',
'欢迎语,说明具备的能力...',
'["建议提问1","建议提问2"]',
'{"system_prompt":"你是一个XX智能体,具备以下工具能力:1.xxx 2.xxx。在回复中使用 [工具调用: 工具名] 和 [工具结果: 工具名] 标记。",
"tools":["法条检索","案例对比","风险评估","策略建议"]
}',
0.5, 8192
) ON CONFLICT (id) DO NOTHING;
```
**示例配置:**
```json
{
"app_config": {
"tools": ["数据检索", "趋势分析", "对比分析", "报告生成"],
"system_prompt": "你是一个综合研判智能体,服务于政府部门的数据分析和决策支持。你具备以下工具能力:1.数据检索 2.趋势分析 3.对比分析 4.报告生成。"
},
"welcome_message": "您好!我是综合研判智能助手。我具备数据检索、趋势分析、对比分析和报告生成等能力。",
"suggested_prompts": [
"分析本季度经济运行数据",
"对比去年同期各项指标变化"
]
}
```
**UI 要素:**
- 顶部:应用图标 + 名称 + 描述 + 右侧"智能体"标签
- 左侧:`+ 新对话` 按钮 + 对话历史
- 中间:欢迎消息(含能力说明)+ 推荐提问 + 工具调用标记展示
- 底部:输入框 + 发送按钮
**特殊 UI — 研判分析型:** 如果需要研判分析 UI(左侧会话列表 + 模板选择 + 向导步骤),slug 需注册到前端:
```typescript
// apps/web/src/app/(portal)/chat/[appId]/page.tsx
const ANALYSIS_SLUGS = new Set(["analysis-agent", "<新slug>"]);
```
---
### 3.6 PPT 生成型 (ppt_generator)
**UI 模式:** 文件上传/文本输入 + PPT预览
**适用场景:** 将文档/文本内容转换为PPT
**必填字段(参照 APP-TYPE-STANDARD.md):**
| 字段 | 必填 | 说明 |
|------|------|------|
| `dify_app_type` | 必填 | 值为 `ppt_generator` |
| `app_config.app_type` | 必填 | 值为 `ppt_generator` |
| `app_config.default_config` | 必填 | PPT默认配置(风格、格式、页数等) |
| `welcome_message` | 必填 | 说明支持的输入方式 |
**SQL 模板:**
```sql
INSERT INTO applications (...) VALUES (
...
'ppt_generator', 'app-placeholder',
'您好!我是PPT生成助手。请上传源文件或粘贴文本内容。',
NULL,
'{"app_type":"ppt_generator",
"system_prompt":"你是一个专业的演示文稿设计专家。",
"default_config":{"style":"general","format":"ppt169","page_count":10,"with_images":true}
}',
0.7, 8192
) ON CONFLICT (id) DO NOTHING;
```
---
## 步骤 6:创建知识库与文档
> **提示:** 步骤 5 和步骤 6-7 通常写在两个独立的 SQL 文件中:
> - `seed_<领域>.sql` — 机构、分类、应用
> - `seed_<领域>_full.sql` — 用户、知识库、文档、知识库关联
为新领域创建专业知识库和文档数据。参照 `server/migrations/seed_gongan_knowledge.sql`
### 知识库表结构
```sql
INSERT INTO knowledge_bases (id, name, description, owner_id, org_id, visibility, doc_count, total_chars, status)
VALUES (
'dX000000-0000-0000-0000-00000000000Y', -- 知识库UUID
'知识库名称',
'知识库描述',
creator_id, -- 创建者用户ID(通过 SELECT 获取)
org_id, -- 所属机构ID
'department', -- 可见性:private/department/public
,
,
'active'
) ON CONFLICT (id) DO NOTHING;
```
**知识库 UUID 命名规则:**
| 领域 | 知识库 UUID 前缀 | 文档 UUID 前缀 |
|------|-----------------|----------------|
| **信访局** | **`a1000000-...`** | **`a1100000-...` / `a1200000-...`** |
| 公安局 | `c0000000-...` | `c1000000-...` / `c2000000-...` |
| **律师** | **`d0000000-...`** | **`d1000000-...` / `d2000000-...` / `d3000000-...` / `d4000000-...`** |
| 医疗(预留) | `e0000000-...` | `e1000000-...` |
| 教育(预留) | `f0000000-...` | `f1000000-...` |
### 文档表结构
```sql
INSERT INTO knowledge_documents (id, kb_id, name, file_type, char_count, indexing_status, uploader_id, content)
VALUES (
'dX000000-0000-0000-0000-00000000000Z', -- 文档UUID
kb_id, -- 所属知识库ID
'文档名称',
'txt', -- 文件类型:pdf/docx/txt/md/csv/xlsx
,
'completed', -- 索引状态:pending/indexing/completed/failed
creator_id,
'文档全文内容...'
) ON CONFLICT (id) DO NOTHING;
```
### 知识库规划模板
每个领域建议规划 2-4 个知识库:
| 知识库类型 | 说明 | 示例 |
|-----------|------|------|
| 法规/政策库 | 领域相关法律法规 | 法律法规库、公安法规库 |
| 业务规程库 | 操作规范、业务流程 | 操作规程、业务标准 |
| 模板库 | 文书、合同等模板 | 合同模板库、文书模板库 |
| 案例/参考库 | 典型案例、司法解释 | 司法解释库、指导案例库 |
### 示例:律师领域知识库
| 知识库 | UUID | 文档数 | 内容 |
|--------|------|--------|------|
| 法律法规库 | `d0000000-...-001` | 6 | 民法典、公司法、劳动法、民诉法、侵权责任编、行政诉讼法 |
| 司法解释库 | `d0000000-...-002` | 4 | 民间借贷解释、劳动争议解释、人身损害赔偿解释、合同纠纷案例 |
| 合同模板库 | `d0000000-...-003` | 5 | 买卖合同、劳动合同、服务合同等范本 |
| 文书模板库 | `d0000000-...-004` | 4 | 起诉状、法律意见书、代理词等模板 |
> 完整示例参见 `server/migrations/seed_legal_full.sql`
---
## 步骤 7:关联知识库到应用
将知识库关联到对应的应用,使应用可以检索知识库内容:
```sql
-- 在 DO $$ 块内执行(已获取知识库 ID 变量)
UPDATE applications SET knowledge_base_id = kb_law_id WHERE slug = 'legal-research';
UPDATE applications SET knowledge_base_id = kb_contract_id WHERE slug = 'contract-review';
UPDATE applications SET knowledge_base_id = kb_doc_id WHERE slug = 'legal-doc-gen';
```
**关联原则:**
- 问答/检索类应用 → 关联法规/政策知识库
- 文书/模板生成类 → 关联模板知识库
- 审查/评估类 → 关联法规知识库 + 案例知识库
- 一个应用目前只能关联一个知识库,选择最相关的
---
## 步骤 8:配置 Embedding 服务
**这是知识库检索能否命中的关键步骤!** 如果不配置 Embedding,分片后没有向量数据,向量语义检索将完全失效,只能退化为关键词匹配。
### 环境变量配置
在服务器 `/opt/govai/.env` 中添加以下配置:
```bash
# Embedding 向量化服务(必须配置,否则知识库检索退化为关键词匹配)
EMBEDDING_API_KEY=<你的API密钥> # 千问使用与 OPENAI_API_KEY 相同的密钥
EMBEDDING_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 # 默认值,可不填
EMBEDDING_MODEL=text-embedding-v3 # 默认值,可不填
```
> **千问用户:** `EMBEDDING_API_KEY` 与 `OPENAI_API_KEY` 使用同一个密钥即可。
### 验证 Embedding 配置
添加配置后重启服务:
```bash
ssh agents "systemctl restart govai-api && sleep 2 && systemctl is-active govai-api"
```
查看服务日志确认 embedding 客户端初始化成功:
```bash
ssh agents "journalctl -u govai-api --since '5 min ago' | grep -i embed"
```
### 常见问题
| 问题 | 原因 | 解决方案 |
|------|------|----------|
| 知识库检索无结果 | `EMBEDDING_API_KEY` 未配置 | 添加到 `.env` 并重启服务 |
| 分片成功但检索不到 | 分片时未配置 embedding,需要重新分片 | 删除旧 chunks,重置 chunk_count=0,重新触发 reindex |
| embedding 调用报错 | API 密钥无效或配额不足 | 检查密钥有效性 |
---
## 步骤 9(原8):文档分片与索引
**关键步骤!** 种子数据插入的知识库文档只是原文存储,必须经过**分片(Chunking)**才能被知识库检索命中。未分片的文档 `chunk_count = 0`,检索时无法匹配。
### 分片原理
```
原始文档 content(数百~数千字)
↓ chunker.ChunkText()
多个 chunk(每块 ≤500 字,重叠 50 字)
↓ embedding.GetEmbedding()
向量化存入 knowledge_chunks 表
检索时:向量语义搜索 + 关键词搜索
```
### 触发分片
部署 SQL 后,调用 reindex 接口对所有未分片文档执行分片和向量化:
```bash
# 在本地执行(通过 ssh 访问服务器)
TOKEN=$(ssh agents "curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{\"email\":\"<机构管理员邮箱>\",\"password\":\"admin123\"}' " \
| python3 -c "import sys,json; print(json.load(sys.stdin)['data']['access_token'])")
ssh agents "curl -s -X POST http://localhost:8080/api/v1/knowledge/reindex \
-H 'Authorization: Bearer $TOKEN'" | python3 -m json.tool
```
> **重要:** 确保 **步骤 8Embedding 配置)** 已完成,否则分片后没有向量数据!
### 验证分片结果
```sql
-- 检查文档分片状态(必须 chunk_count > 0
SELECT kd.name, kd.chunk_count,
(SELECT COUNT(*) FROM knowledge_chunks kc WHERE kc.doc_id = kd.id) as actual_chunks
FROM knowledge_documents kd
JOIN knowledge_bases kb ON kd.kb_id = kb.id
WHERE kb.org_id = '<机构UUID>';
-- ⚠️ 关键验证:检查 embedding 是否生成(必须全部为 true)
SELECT kb.name,
COUNT(kc.id) as chunks,
COUNT(kc.embedding) as with_embed
FROM knowledge_bases kb
JOIN knowledge_documents kd ON kd.kb_id = kb.id
JOIN knowledge_chunks kc ON kc.doc_id = kd.id
WHERE kb.org_id = '<机构UUID>'
GROUP BY kb.name;
-- 如果 with_embed = 0,说明 Embedding 未配置,需要:
-- 1. 配置 EMBEDDING_API_KEY(步骤 8
-- 2. 删除旧 chunksDELETE FROM knowledge_chunks WHERE kb_id IN (SELECT id FROM knowledge_bases WHERE org_id = '<机构UUID>');
-- 3. 重置 chunk_countUPDATE knowledge_documents SET chunk_count = 0 WHERE kb_id IN (SELECT id FROM knowledge_bases WHERE org_id = '<机构UUID>');
-- 4. 重新触发 reindex
```
### 注意事项
- 分片参数:每块最大 500 字,重叠 50 字(见 `server/pkg/chunker/chunker.go`
- **必须配置 Embedding 服务**(步骤 8),否则知识库检索退化为关键词匹配,准确率大幅下降
- 混合检索策略:优先向量语义搜索(余弦相似度 > 0.3),然后关键词搜索补充
- 上传新文档时会自动触发分片和向量化,此步骤仅用于**种子数据补充分片**
- 如果先分片后才配置 Embedding,需要**删除旧 chunks 并重新索引**
---
## 步骤 9(原9):部署 SQL
部署顺序很重要,需按依赖关系执行:
```bash
# 1. 先部署机构、分类和应用
psql -d govai -f server/migrations/seed_<领域>.sql
# 2. 再部署用户、知识库、文档、关联(依赖应用数据)
psql -d govai -f server/migrations/seed_<领域>_full.sql
```
### 本地测试
```bash
# 使用 Postgres.app 的 psql
/Applications/Postgres.app/Contents/Versions/18/bin/psql "postgres://freedak@localhost:5432/govai_portal?sslmode=disable" -f server/migrations/seed_<领域>.sql
/Applications/Postgres.app/Contents/Versions/18/bin/psql "postgres://freedak@localhost:5432/govai_portal?sslmode=disable" -f server/migrations/seed_<领域>_full.sql
```
### 服务器部署(推荐方式)
```bash
# 从本地传输 SQL 文件到服务器
scp server/migrations/seed_<领域>.sql agents:/tmp/
scp server/migrations/seed_<领域>_full.sql agents:/tmp/
# 在服务器执行
ssh agents "PGPASSWORD='GovAI@2024Secure' psql -h localhost -U govai -d govai_portal -f /tmp/seed_<领域>.sql"
ssh agents "PGPASSWORD='GovAI@2024Secure' psql -h localhost -U govai -d govai_portal -f /tmp/seed_<领域>_full.sql"
```
### 数据验证
```sql
-- 检查机构
SELECT name, slug FROM organizations WHERE slug = '<机构slug>';
-- 检查用户
SELECT name, email, role FROM users WHERE org_id = '<机构UUID>';
-- 检查应用
SELECT name, slug, dify_app_type FROM applications WHERE id::text LIKE '<UUID前缀>%';
-- 检查知识库
SELECT name, doc_count FROM knowledge_bases WHERE org_id = '<机构UUID>';
-- 检查知识库关联
SELECT a.name, a.slug, kb.name as kb_name
FROM applications a LEFT JOIN knowledge_bases kb ON a.knowledge_base_id = kb.id
WHERE a.id::text LIKE '<UUID前缀>%';
```
---
## 步骤 10(原9续):部署前后端
### 部署后端(如有代码修改)
```bash
# 交叉编译
cd server && GOOS=linux GOARCH=amd64 go build -o govai-server-linux ./cmd/server
# 上传并替换
scp govai-server-linux agents:/opt/govai/server/server.new
ssh agents "mv /opt/govai/server/server.new /opt/govai/server/server && systemctl restart govai-api"
```
### 部署前端
```bash
# 编译
cd apps/web && npm run build
# 同步并重启
ssh agents "systemctl stop govai-web"
rsync -az --delete apps/web/.next/ agents:/opt/govai/web/.next/
ssh agents "systemctl start govai-web"
```
---
## 步骤 11:前端注册(仅特殊 UI 类型需要)
仅当应用使用**公文写作 UI** 或**研判分析 UI** 时,需修改前端路由。
编辑 `apps/web/src/app/(portal)/chat/[appId]/page.tsx`
```typescript
// 公文写作型:slug 加入此集合 → 使用 DocWriterUI
const DOC_WRITER_SLUGS = new Set(["official-doc-writer", "fagai-doc-writer"]);
// 研判分析型:slug 加入此集合 → 使用 AnalysisUI
const ANALYSIS_SLUGS = new Set(["analysis-agent"]);
```
> 普通的 chatbot / completion / workflow / agent 无需修改前端,系统根据 `dify_app_type` 自动匹配 UI。
---
## 步骤 12:更新 run.md
在项目根目录的 `run.md` 中添加新机构的用户信息和知识库信息,便于团队查阅。
```markdown
### 新机构名
| 姓名 | 邮箱 | 角色 |
|------|------|------|
| 机构管理员 | xx-admin@govai.gov.cn | admin |
| 张三 | zhangsan@govai.gov.cn | creator |
| 李四 | lisi@govai.gov.cn | user |
### 新机构知识库
| 知识库 | 文档数 | 关联应用 |
|--------|--------|----------|
| XX法规库 | N | 应用1、应用2 |
| XX模板库 | N | 应用3 |
```
> 同时更新种子脚本说明行,记录新增的 SQL 文件路径。
---
## 步骤 13:验证
```bash
# 检查应用列表
curl -s https://gov.opc8ai.com/api/v1/store/apps | python3 -m json.tool | grep "slug"
# 浏览器测试
# https://gov.opc8ai.com/chat/<应用slug>
```
**验证清单:**
**数据完整性:**
- [ ] 机构出现在 organizations 表
- [ ] 用户可以使用邮箱 + `admin123` 登录
- [ ] 用户 org_id 正确关联到机构
- [ ] 应用 org_id 正确关联到机构
- [ ] 知识库 org_id 正确关联到机构
- [ ] 知识库文档数量正确
- [ ] 知识库文档已分片(`chunk_count > 0`
- [ ] `knowledge_chunks` 表中有对应的 chunk 记录
- [ ] **关键:** chunk 记录有 embedding 向量(`embedding IS NOT NULL`
- [ ] 应用 knowledge_base_id 正确关联到知识库
**前端展示:**
- [ ] 应用出现在应用商店
- [ ] 分类图标和颜色正确显示(Lucide 图标,非 emoji
- [ ] 点击进入正确的 UI 模式(chatbot/completion/workflow/agent/doc-writer/analysis
- [ ] 欢迎语和推荐提问正常显示
- [ ] 对话/补全/工作流功能正常
- [ ] 切换到新机构后只看到该机构的应用和知识库
**UI 样式:**
- [ ] 应用类型标签样式:`text-blue-800 bg-blue-100 rounded-full font-medium`
- [ ] 主要按钮样式:`bg-blue-900 hover:bg-blue-800 text-white`
- [ ] 所有 hover 效果使用 `transition-all duration-200`
- [ ] 卡片 hover:左侧蓝线 `bg-blue-700` + `hover:border-blue-300` + `hover:-translate-y-0.5`
- [ ] 无 emoji 字符出现在 UI 中
- [ ] 无彩虹色/荧光色/非蓝色主操作按钮
**知识库检索验证:**
- [ ] 使用关联知识库的应用提问,AI 回复中出现 `[[知识库:文献名称]]` 引用标记
- [ ] 引用内容与知识库文档内容一致
**文档同步:**
- [ ] `run.md` 已更新用户账号和知识库信息
- [ ] `add-domain-guide.md` 已更新机构列表和 UUID 命名规则
---
## 附录 Asystem_prompt 编写规范
```
你是一个[角色定位],专注于[能力范围]。
## 能力
- 能力1
- 能力2
## 输出格式
- 使用 Markdown 格式
- 引用法条使用标准格式:《法律名》第X条
## 限制
- 不提供超出[范围]的建议
- 所有输出末尾附免责声明
## 免责声明
本内容由AI生成,仅供参考,不构成正式法律意见。
```
---
## 附录 Btemperature 参考
| 场景 | temperature | 说明 |
|------|-------------|------|
| 法律/医疗/财务 | 0.2-0.3 | 高准确性 |
| 公文/报告/政策解读 | 0.3-0.5 | 平衡 |
| 创意/营销/宣传 | 0.7-0.9 | 高创造性 |
---
## 附录 CUUID 命名规则
### 应用 UUID
```
领域前缀-0000-0000-0000-序号
10000000-... 政务(已占用)
20000000-... 法律(已占用)
a0XX0000-... 信访局(已占用,应用UUID在seed SQL中定义)
30000000-... 医疗
40000000-... 教育
```
### 机构 UUID
```
a0000000-0000-0000-0000-0000000000XX
01 科技局(已占用)
02 公安局(已占用)
03 发改局(已占用)
04-08 教育/人社/财政/住建/市监(已占用)
09 律师事务所(已占用)
10 信访局(已占用)
11 下一个新领域
```
### 知识库 UUID
```
知识库:{前缀}0000000-0000-0000-0000-00000000000Y
文档: {前缀}X000000-0000-0000-0000-00000000000Z
a1.. 信访局(已占用)
c... 公安局(已占用)
d... 律师(已占用)
e... 医疗(预留)
f... 教育(预留)
```
---
## 附录 DUI 规范速查(摘自 UI-STYLE-GUIDE.md
| 元素 | 样式 |
|------|------|
| 主色调 | 政务蓝 `blue-900/950` |
| 主要按钮 | `bg-blue-900 hover:bg-blue-800 text-white` |
| 类型标签 | `text-blue-800 bg-blue-100 rounded-full font-medium` |
| 输入框 | `rounded-lg` |
| 卡片 Hover | 左侧蓝线 `bg-blue-700` + `hover:border-blue-300` + `hover:-translate-y-0.5` |
| Section 标题 | 左侧竖线 `w-1 h-5 bg-blue-800 rounded-full` + Lucide 图标 `h-5 w-5 text-blue-700` |
| 过渡动画 | `transition-all duration-200`,避免过度动画 |
| 图标规范 | **Lucide React 线条图标**,导航 `h-4 w-4`,标题 `h-5 w-5`,小标签 `h-3 w-3` |
| Workflow 选中 | `ring-2 ring-purple-400 ring-offset-2 shadow-md` |
| 完成步骤 | `emerald-700` |
| 金色点缀 | `amber-400`Logo 盾牌、星级评分) |
**禁止事项(摘自 UI-STYLE-GUIDE.md):**
1. 使用 emoji 字符
2. 使用彩虹色/荧光色
3. 过度圆角(不超过 `rounded-xl`
4. 大面积动画效果
5. 非蓝色系的主操作按钮
6. 花哨的渐变文字(Logo 区域除外)
---
## 完整示例
### 示例一:律师行业
| 文件 | 内容 |
|------|------|
| `server/migrations/seed_legal.sql` | 4个分类 + 10个应用(3 chatbot + 3 completion + 2 workflow + 2 agent |
| `server/migrations/seed_legal_full.sql` | 1个机构 + 3个用户 + 4个知识库 + 17篇文档 + 7个知识库关联 |
| 项目 | 数量 | 详情 |
|------|------|------|
| 机构 | 1 | 律师事务所 (`lvsuo`, org_id=`...09`) |
| 用户 | 3 | 律所管理员 / 林律师 / 黄助理 |
| 分类 | 4 | 案件代理 / 合同服务 / 法律研究 / 合规风控 |
| 应用 | 10 | 法律法规检索、法律咨询助手、合同条款审查、法律文书生成、案情摘要提取、合同条款生成、案件风险评估、尽职调查报告、诉讼策略助手、合规审查助手 |
| 知识库 | 4 | 法律法规库(6)、司法解释库(4)、合同模板库(5)、文书模板库(4) |
| 文档 | 17 | 民法典、公司法、劳动法、民诉法、侵权责任编、行政诉讼法、司法解释、合同模板、文书模板 |
> 详细配置方案参见 [domain-legal.md](./domain-legal.md)
### 示例二:信访局
| 文件 | 内容 |
|------|------|
| `server/migrations/seed_xinfang.sql` | 1个机构 + 4个分类 + 10个应用(2 chatbot + 4 completion + 2 workflow + 2 agent |
| `server/migrations/seed_xinfang_full.sql` | 3个用户 + 4个知识库 + 16篇文档 + 知识库关联 |
| 项目 | 数量 | 详情 |
|------|------|------|
| 机构 | 1 | 信访局 (`xinfang`, org_id=`...10`) |
| 用户 | 3 | 信访管理员 / 王主任 / 赵科员 |
| 分类 | 4 | 信访受理 / 政策答复 / 矛盾调解 / 督查督办 |
| 应用 | 10 | 信访政策咨询、来信来访登记、信访件分类、信访答复生成、政策法规检索、矛盾纠纷分析、调解文书生成、督查报告生成、信访数据分析、信访风险评估 |
| 推荐应用 | 4 | 信访政策咨询(chatbot)、信访答复生成(completion)、矛盾纠纷分析(workflow)、督查报告生成(workflow) |
| 知识库 | 4 | 信访法规库(5)、政策答复模板库(4)、调解规程库(4)、督查督办制度库(3) |
| 文档 | 16 | 信访工作条例、行政复议法、行政诉讼法、人民调解法、各类模板和规程 |
### 两个示例的对比
| 维度 | 律师行业 | 信访局 |
|------|---------|--------|
| UUID 前缀(应用) | `20000000-...` | 写在 seed SQL 中 |
| UUID 前缀(知识库) | `d0000000-...` | `a1000000-...` |
| 分类数 | 4 | 4 |
| 应用类型分布 | 3C+3Comp+2W+2A | 2C+4Comp+2W+2A |
| 知识库 | 法律法规+司法解释+合同模板+文书模板 | 信访法规+答复模板+调解规程+督查制度 |