spec: add metadata-role-separation module specification [AC-MRS-01~16]

This commit is contained in:
MerCry 2026-03-05 17:09:26 +08:00
parent 714dc8c480
commit 5ded0c5f75
6 changed files with 2273 additions and 0 deletions

View File

@ -0,0 +1,615 @@
# 元数据职责分层优化 - 技术设计
## 1. 系统架构
### 1.1 整体架构
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 管理端 (ai-service-admin) │
├─────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 元数据字段配置 │ │ 槽位定义配置 │ │ 按角色过滤视图 │ │
│ │ (field_roles) │ │ (SlotDefinition) │ │ (RoleFilter) │ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
└───────────┼────────────────────┼────────────────────┼───────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 后端服务 (ai-service) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ API Layer │ │
│ │ ┌──────────────────────┐ ┌──────────────────────┐ │ │
│ │ │ MetadataFieldAPI │ │ SlotDefinitionAPI │ │ │
│ │ │ - CRUD │ │ - CRUD │ │ │
│ │ │ - getByRole │ │ - getByRole │ │ │
│ │ └──────────┬───────────┘ └──────────┬───────────┘ │ │
│ └─────────────┼────────────────────────┼──────────────────────────┘ │
│ │ │ │
│ ┌─────────────┼────────────────────────┼──────────────────────────┐ │
│ │ │ Service Layer │ │ │
│ │ ┌──────────▼───────────┐ ┌────────▼──────────┐ │ │
│ │ │ MetadataFieldService │ │ SlotDefinitionSvc │ │ │
│ │ │ - create/update │ │ - create/update │ │ │
│ │ │ - getByRole │ │ - getByRole │ │ │
│ │ │ - validateRoles │ │ - linkToField │ │ │
│ │ └──────────┬───────────┘ └────────┬──────────┘ │ │
│ └─────────────┼────────────────────────┼──────────────────────────┘ │
│ │ │ │
│ ┌─────────────┼────────────────────────┼──────────────────────────┐ │
│ │ │ Tool Integration │ │ │
│ │ ┌──────────▼────────────────────────▼──────────┐ │ │
│ │ │ RoleBasedFieldProvider │ │ │
│ │ │ - getFieldsByRole(role) │ │ │
│ │ │ - getSlotDefinitionsByRole(role) │ │ │
│ │ └──────────────────────┬───────────────────────┘ │ │
│ └─────────────────────────┼──────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────┼──────────────────────────────────────┐ │
│ │ Tool Consumers │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │kb_search_ │ │memory_recall │ │intent_hint/ │ │ │
│ │ │dynamic │ │ │ │high_risk_ │ │ │
│ │ │[resource_ │ │[slot] │ │check │ │ │
│ │ │filter] │ │ │ │[routing_ │ │ │
│ │ └──────────────┘ └──────────────┘ │signal] │ │ │
│ │ └──────────────┘ │ │
│ │ ┌──────────────┐ │ │
│ │ │template_ │ │ │
│ │ │engine │ │ │
│ │ │[prompt_var] │ │ │
│ │ └──────────────┘ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 数据层 │
├─────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ metadata_field_ │ │ slot_definitions │ │
│ │ definitions │ │ │ │
│ │ - id │ │ - id │ │
│ │ - field_key │ │ - slot_key │ │
│ │ - field_roles[] │ │ - type │ │
│ │ - ... │ │ - linked_field_id │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Redis Cache │ │ PostgreSQL │ │
│ │ - field_roles:by_tenant │ - 持久化存储 │ │
│ └─────────────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 1.2 模块依赖关系
```
metadata-role-separation
├── metadata-governance (依赖)
│ └── 元数据字段定义基础能力
├── intent-driven-mid-platform (依赖)
│ └── 中台运行时工具链
└── ai-service-admin (依赖)
└── 管理端配置界面
```
---
## 2. 数据模型设计
### 2.1 MetadataFieldDefinition 扩展
在现有 `metadata_field_definitions` 表基础上新增字段:
```sql
-- 新增字段field_roles
ALTER TABLE metadata_field_definitions
ADD COLUMN field_roles JSONB DEFAULT '[]'::jsonb;
-- 创建 GIN 索引支持按角色查询
CREATE INDEX idx_metadata_field_definitions_roles
ON metadata_field_definitions USING GIN (field_roles);
-- 注释
COMMENT ON COLUMN metadata_field_definitions.field_roles IS '字段角色列表resource_filter, slot, prompt_var, routing_signal';
```
**字段定义**
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|-------|------|-----|-------|------|
| `field_roles` | JSONB | 否 | `[]` | 字段角色列表,存储字符串数组 |
**角色枚举值**
```python
class FieldRole(str, Enum):
RESOURCE_FILTER = "resource_filter" # 资源过滤
SLOT = "slot" # 运行时槽位
PROMPT_VAR = "prompt_var" # 提示词变量
ROUTING_SIGNAL = "routing_signal" # 路由信号
```
### 2.2 SlotDefinition 新增表
```sql
-- 槽位定义表
CREATE TABLE slot_definitions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
slot_key VARCHAR(100) NOT NULL,
type VARCHAR(20) NOT NULL,
required BOOLEAN NOT NULL DEFAULT FALSE,
extract_strategy VARCHAR(20),
validation_rule TEXT,
ask_back_prompt TEXT,
default_value JSONB,
linked_field_id UUID REFERENCES metadata_field_definitions(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT uk_slot_definitions_tenant_key UNIQUE (tenant_id, slot_key),
CONSTRAINT chk_slot_definitions_type CHECK (type IN ('string', 'number', 'boolean', 'enum', 'array_enum')),
CONSTRAINT chk_slot_definitions_extract_strategy CHECK (extract_strategy IS NULL OR extract_strategy IN ('rule', 'llm', 'user_input'))
);
-- 索引
CREATE INDEX idx_slot_definitions_tenant ON slot_definitions(tenant_id);
CREATE INDEX idx_slot_definitions_linked_field ON slot_definitions(linked_field_id);
-- 注释
COMMENT ON TABLE slot_definitions IS '槽位定义表';
COMMENT ON COLUMN slot_definitions.slot_key IS '槽位键名,可与元数据字段 field_key 关联';
COMMENT ON COLUMN slot_definitions.linked_field_id IS '关联的元数据字段 ID';
```
### 2.3 ER 图
```
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ metadata_field_definitions │ │ slot_definitions │
├─────────────────────────────┤ ├─────────────────────────────┤
│ id (PK) │◄──────│ linked_field_id (FK) │
│ tenant_id │ │ id (PK) │
│ field_key │ │ tenant_id │
│ label │ │ slot_key │
│ type │ │ type │
│ required │ │ required │
│ options │ │ extract_strategy │
│ default_value │ │ validation_rule │
│ scope │ │ ask_back_prompt │
│ is_filterable │ │ default_value │
│ is_rank_feature │ │ created_at │
│ status │ │ updated_at │
│ field_roles ◀── NEW │ │ │
│ version │ │ │
│ created_at │ │ │
│ updated_at │ │ │
└─────────────────────────────┘ └─────────────────────────────┘
```
---
## 3. 核心流程设计
### 3.1 字段职责配置流程
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 管理端配置流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 管理员进入元数据字段配置页面 │
│ │ │
│ ▼ │
│ 2. 创建/编辑字段定义 │
│ │ │
│ ├── 填写基本信息 (field_key, label, type, etc.) │
│ │ │
│ ├── 选择字段角色 (field_roles 多选) │
│ │ ├── [ ] resource_filter - 资源过滤 │
│ │ ├── [ ] slot - 运行时槽位 │
│ │ ├── [ ] prompt_var - 提示词变量 │
│ │ └── [ ] routing_signal - 路由信号 │
│ │ │
│ ▼ │
│ 3. 后端校验 │
│ │ │
│ ├── field_key 格式校验 (小写字母数字下划线) │
│ ├── field_roles 枚举值校验 │
│ └── 租户内唯一性校验 │
│ │ │
│ ▼ │
│ 4. 保存到数据库 │
│ │ │
│ └── field_roles 以 JSONB 格式存储 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 3.2 按角色查询流程
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 按角色查询流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 工具/模块请求字段 │
│ │ │
│ ▼ │
│ RoleBasedFieldProvider.getFieldsByRole(role, tenant_id) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ SELECT * FROM metadata_field_definitions │ │
│ │ WHERE tenant_id = :tenant_id │ │
│ │ AND status = 'active' │ │
│ │ AND field_roles ? :role -- JSONB contains 查询 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 返回字段定义列表 │
│ │ │
│ ▼ │
│ 工具按需消费字段 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### 3.3 工具协同改造流程
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 工具协同改造流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ kb_search_dynamic [AC-MRS-11] │ │
│ │ │ │
│ │ 改造前: │ │
│ │ filterable_fields = get_filterable_fields(tenant_id) │ │
│ │ WHERE is_filterable = true │ │
│ │ │ │
│ │ 改造后: │ │
│ │ filterable_fields = get_fields_by_role( │ │
│ │ tenant_id, role='resource_filter' │ │
│ │ ) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ memory_recall [AC-MRS-12] │ │
│ │ │ │
│ │ 改造前: │ │
│ │ slots = context.get('slots', {}) # 无角色过滤 │ │
│ │ │ │
│ │ 改造后: │ │
│ │ slot_fields = get_fields_by_role( │ │
│ │ tenant_id, role='slot' │ │
│ │ ) │ │
│ │ slots = {k: v for k, v in context.items() │ │
│ │ if k in slot_fields} │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ intent_hint / high_risk_check [AC-MRS-13] │ │
│ │ │ │
│ │ 改造前: │ │
│ │ routing_fields = all_metadata_fields # 全量字段 │ │
│ │ │ │
│ │ 改造后: │ │
│ │ routing_fields = get_fields_by_role( │ │
│ │ tenant_id, role='routing_signal' │ │
│ │ ) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ template_engine [AC-MRS-14] │ │
│ │ │ │
│ │ 改造前: │ │
│ │ variables = extract_all_variables(template) │ │
│ │ values = get_all_metadata_values(context) │ │
│ │ │ │
│ │ 改造后: │ │
│ │ prompt_var_fields = get_fields_by_role( │ │
│ │ tenant_id, role='prompt_var' │ │
│ │ ) │ │
│ │ values = {k: v for k, v in context.items() │ │
│ │ if k in prompt_var_fields} │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
---
## 4. 接口设计
### 4.1 后端 API 接口
| 接口 | 方法 | 说明 | AC |
|------|------|------|-----|
| `/admin/metadata-schemas` | GET | 获取字段列表(支持 role 过滤) | AC-MRS-06 |
| `/admin/metadata-schemas` | POST | 创建字段(含 field_roles | AC-MRS-01,02,03 |
| `/admin/metadata-schemas/{id}` | PUT | 更新字段(含 field_roles | AC-MRS-01 |
| `/admin/metadata-schemas/{id}` | DELETE | 删除字段(无需兼容) | AC-MRS-16 |
| `/admin/metadata-schemas/by-role` | GET | 按角色查询字段 | AC-MRS-04,05 |
| `/admin/slot-definitions` | GET | 获取槽位定义列表 | - |
| `/admin/slot-definitions` | POST | 创建槽位定义 | AC-MRS-07,08 |
| `/admin/slot-definitions/{id}` | PUT | 更新槽位定义 | - |
| `/admin/slot-definitions/{id}` | DELETE | 删除槽位定义 | AC-MRS-16 |
| `/mid/slots/by-role` | GET | 运行时按角色获取槽位 | AC-MRS-10 |
| `/mid/slots/{slot_key}` | GET | 获取运行时槽位值 | AC-MRS-09 |
### 4.2 内部服务接口
```python
class RoleBasedFieldProvider:
"""基于角色的字段提供者"""
async def get_fields_by_role(
self,
tenant_id: str,
role: FieldRole,
include_deprecated: bool = False,
) -> list[MetadataFieldDefinition]:
"""
按角色获取字段定义
Args:
tenant_id: 租户ID
role: 字段角色
include_deprecated: 是否包含已废弃字段
Returns:
字段定义列表
"""
async def get_slot_definitions_by_role(
self,
tenant_id: str,
role: FieldRole,
) -> list[SlotDefinition]:
"""
按角色获取槽位定义(包含关联字段信息)
"""
```
---
## 5. 前端设计
### 5.1 元数据字段配置页面改造
**新增组件**`FieldRolesSelector.vue`
```vue
<template>
<div class="field-roles-selector">
<label>字段角色</label>
<el-checkbox-group v-model="selectedRoles">
<el-checkbox
v-for="role in availableRoles"
:key="role.value"
:label="role.value"
>
<span>{{ role.label }}</span>
<el-tooltip :content="role.description">
<el-icon><QuestionFilled /></el-icon>
</el-tooltip>
</el-checkbox>
</el-checkbox-group>
</div>
</template>
<script setup>
const availableRoles = [
{
value: 'resource_filter',
label: '资源过滤',
description: '用于 KB 文档检索时的元数据过滤'
},
{
value: 'slot',
label: '运行时槽位',
description: '对话流程中的结构化槽位,用于信息收集'
},
{
value: 'prompt_var',
label: '提示词变量',
description: '注入到 LLM Prompt 中的变量'
},
{
value: 'routing_signal',
label: '路由信号',
description: '用于意图路由和风险判断的信号'
},
];
</script>
```
### 5.2 按角色过滤视图
**新增过滤器**:在元数据字段列表页面增加角色过滤下拉框
```vue
<template>
<div class="filter-bar">
<el-select
v-model="selectedRole"
placeholder="按角色过滤"
clearable
@change="handleRoleFilter"
>
<el-option
v-for="role in availableRoles"
:key="role.value"
:label="role.label"
:value="role.value"
/>
</el-select>
</div>
</template>
```
---
## 6. 缓存策略
### 6.1 缓存设计
```python
class FieldRoleCache:
"""字段角色缓存"""
CACHE_KEY_PREFIX = "field_roles"
CACHE_TTL = 300 # 5分钟
async def get_fields_by_role(
self,
tenant_id: str,
role: FieldRole,
) -> list[MetadataFieldDefinition]:
cache_key = f"{self.CACHE_KEY_PREFIX}:{tenant_id}:{role}"
# 尝试从缓存获取
cached = await self._redis.get(cache_key)
if cached:
return self._deserialize(cached)
# 从数据库查询
fields = await self._db_query(tenant_id, role)
# 写入缓存
await self._redis.setex(
cache_key,
self.CACHE_TTL,
self._serialize(fields),
)
return fields
async def invalidate(self, tenant_id: str):
"""失效租户所有角色缓存"""
pattern = f"{self.CACHE_KEY_PREFIX}:{tenant_id}:*"
keys = await self._redis.keys(pattern)
if keys:
await self._redis.delete(*keys)
```
### 6.2 缓存失效策略
- 字段创建/更新/删除时失效该租户所有角色缓存
- 槽位定义变更时失效相关角色缓存
---
## 7. 异常处理
### 7.1 错误码定义
| 错误码 | 说明 | HTTP 状态码 |
|-------|------|------------|
| `INVALID_ROLE` | 无效的角色参数 | 400 |
| `FIELD_KEY_EXISTS` | field_key 已存在 | 409 |
| `SLOT_KEY_EXISTS` | slot_key 已存在 | 409 |
| `LINKED_FIELD_NOT_FOUND` | 关联字段不存在 | 404 |
### 7.2 异常处理示例
```python
class InvalidRoleError(Exception):
"""无效角色异常"""
def __init__(self, role: str):
self.role = role
self.valid_roles = [r.value for r in FieldRole]
super().__init__(
f"Invalid role '{role}'. Valid roles are: {', '.join(self.valid_roles)}"
)
```
---
## 8. 测试策略
### 8.1 单元测试
- `RoleBasedFieldProvider` 按角色查询测试
- `FieldRoleCache` 缓存读写测试
- 字段角色校验测试
### 8.2 集成测试
- API 端点测试CRUD + 按角色查询)
- 工具协同改造测试(验证各工具只消费对应角色字段)
### 8.3 契约测试
- OpenAPI Schema 校验
- 响应结构验证
---
## 9. 迁移与部署
### 9.1 数据库迁移
```sql
-- 1. 新增 field_roles 字段
ALTER TABLE metadata_field_definitions
ADD COLUMN field_roles JSONB DEFAULT '[]'::jsonb;
-- 2. 创建索引
CREATE INDEX idx_metadata_field_definitions_roles
ON metadata_field_definitions USING GIN (field_roles);
-- 3. 创建 slot_definitions 表
CREATE TABLE slot_definitions (
-- ... 见 2.2 节
);
-- 4. 初始化现有字段的默认角色(可选)
-- 根据 is_filterable 推断 resource_filter 角色
UPDATE metadata_field_definitions
SET field_roles = '["resource_filter"]'::jsonb
WHERE is_filterable = true AND status = 'active';
```
### 9.2 部署顺序
1. 执行数据库迁移脚本
2. 部署后端服务向后兼容field_roles 可为空)
3. 部署前端页面
4. 配置字段角色
---
## 10. 监控与观测
### 10.1 关键指标
| 指标名 | 说明 |
|-------|------|
| `field_role_query_count` | 按角色查询次数 |
| `field_role_query_latency` | 按角色查询延迟 |
| `field_role_cache_hit_rate` | 角色缓存命中率 |
| `tool_field_consumption` | 工具字段消费统计 |
### 10.2 日志字段
```json
{
"event": "field_role_query",
"tenant_id": "xxx",
"role": "resource_filter",
"field_count": 5,
"duration_ms": 12,
"cache_hit": true
}
```

View File

@ -0,0 +1,272 @@
openapi: 3.0.3
info:
title: 元数据职责分层模块 - 外部依赖
description: |
本模块依赖的外部 API 契约,用于生成 Mock/SDK。
## 依赖说明
- metadata-governance: 元数据字段定义基础能力
- intent-driven-mid-platform: 中台运行时工具链
version: 0.1.0
x-contract-level: L1
contact:
name: AI Robot Core Team
servers:
- url: /api
description: API Server
tags:
- name: MetadataGovernance
description: 元数据治理模块依赖
- name: MidPlatform
description: 中台模块依赖
paths:
/admin/metadata-schemas:
get:
summary: 获取元数据字段定义列表(依赖)
description: 依赖 metadata-governance 模块的元数据字段列表查询能力
operationId: depsListMetadataSchemas
tags:
- MetadataGovernance
parameters:
- name: status
in: query
schema:
type: string
enum:
- draft
- active
- deprecated
- name: scope
in: query
schema:
type: string
enum:
- kb_document
- intent_rule
- script_flow
- prompt_template
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 成功返回字段定义列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/MetadataFieldDefinition'
/admin/kb/documents:
get:
summary: 获取 KB 文档列表(依赖)
description: 依赖 KB 文档管理能力,用于验证字段使用情况
operationId: depsListKbDocuments
tags:
- MetadataGovernance
parameters:
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
- name: kb_id
in: query
schema:
type: string
format: uuid
responses:
'200':
description: 成功返回文档列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/KbDocument'
/mid/dialogue/respond:
post:
summary: 中台对话响应(依赖)
description: 依赖中台对话响应能力,用于工具协同改造验证
operationId: depsRespondDialogue
tags:
- MidPlatform
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DialogueRequest'
responses:
'200':
description: 成功返回对话响应
content:
application/json:
schema:
$ref: '#/components/schemas/DialogueResponse'
components:
schemas:
MetadataFieldStatus:
type: string
enum:
- draft
- active
- deprecated
MetadataScope:
type: string
enum:
- kb_document
- intent_rule
- script_flow
- prompt_template
MetadataFieldType:
type: string
enum:
- string
- number
- boolean
- enum
- array_enum
MetadataFieldDefinition:
type: object
properties:
id:
type: string
format: uuid
tenant_id:
type: string
format: uuid
field_key:
type: string
label:
type: string
type:
$ref: '#/components/schemas/MetadataFieldType'
required:
type: boolean
options:
type: array
items:
type: string
default_value:
type: object
scope:
type: array
items:
$ref: '#/components/schemas/MetadataScope'
is_filterable:
type: boolean
is_rank_feature:
type: boolean
status:
$ref: '#/components/schemas/MetadataFieldStatus'
version:
type: integer
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
KbDocument:
type: object
properties:
id:
type: string
format: uuid
tenant_id:
type: string
format: uuid
kb_id:
type: string
format: uuid
title:
type: string
content:
type: string
metadata:
type: object
additionalProperties: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
DialogueRequest:
type: object
required:
- tenant_id
- user_id
- session_id
- user_message
properties:
tenant_id:
type: string
format: uuid
user_id:
type: string
format: uuid
session_id:
type: string
format: uuid
user_message:
type: string
context:
type: object
additionalProperties: true
description: 会话上下文,包含槽位信息
DialogueResponse:
type: object
properties:
session_id:
type: string
format: uuid
request_id:
type: string
format: uuid
segments:
type: array
items:
type: object
properties:
segment_id:
type: string
text:
type: string
delay_after:
type: integer
trace:
type: object
properties:
mode:
type: string
enum:
- agent
- micro_flow
- fixed
- transfer
intent:
type: string
tool_calls:
type: array
items:
type: object
fallback_reason_code:
type: string

View File

@ -0,0 +1,774 @@
openapi: 3.0.3
info:
title: 元数据职责分层 API
description: |
提供元数据字段职责分层配置、槽位定义管理及按角色查询能力。
## 字段角色定义
- `resource_filter`: 资源过滤角色,用于 KB 文档检索
- `slot`: 运行时槽位角色,用于对话信息收集
- `prompt_var`: 提示词变量角色,用于 Prompt 注入
- `routing_signal`: 路由信号角色,用于意图路由判断
version: 0.1.0
x-contract-level: L1
contact:
name: AI Robot Core Team
servers:
- url: /api
description: API Server
tags:
- name: MetadataSchema
description: 元数据字段定义管理(扩展 field_roles
- name: SlotDefinition
description: 槽位定义管理
- name: RuntimeSlot
description: 运行时槽位查询
paths:
/admin/metadata-schemas:
get:
summary: 获取元数据字段定义列表
description: |-
[AC-MRS-06] 支持按状态、范围、角色过滤查询元数据字段定义列表。
operationId: listMetadataSchemas
tags:
- MetadataSchema
parameters:
- name: status
in: query
description: 字段状态过滤
schema:
$ref: '#/components/schemas/MetadataFieldStatus'
- name: scope
in: query
description: 适用范围过滤
schema:
$ref: '#/components/schemas/MetadataScope'
- name: field_role
in: query
description: 字段角色过滤
schema:
$ref: '#/components/schemas/FieldRole'
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 成功返回字段定义列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/MetadataFieldDefinition'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
post:
summary: 创建元数据字段定义
description: |-
[AC-MRS-01][AC-MRS-02][AC-MRS-03] 创建新的元数据字段定义,支持 field_roles 多选配置。
operationId: createMetadataSchema
tags:
- MetadataSchema
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MetadataFieldDefinitionCreate'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/MetadataFieldDefinition'
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: field_key 已存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/admin/metadata-schemas/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: 获取单个元数据字段定义
operationId: getMetadataSchema
tags:
- MetadataSchema
responses:
'200':
description: 成功返回字段定义
content:
application/json:
schema:
$ref: '#/components/schemas/MetadataFieldDefinition'
'404':
$ref: '#/components/responses/NotFound'
put:
summary: 更新元数据字段定义
description: |-
[AC-MRS-01] 更新元数据字段定义,支持修改 field_roles。
operationId: updateMetadataSchema
tags:
- MetadataSchema
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MetadataFieldDefinitionUpdate'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/MetadataFieldDefinition'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
delete:
summary: 删除元数据字段定义
description: |-
[AC-MRS-16] 删除元数据字段定义,无需考虑历史数据兼容性。
operationId: deleteMetadataSchema
tags:
- MetadataSchema
responses:
'204':
description: 删除成功
'404':
$ref: '#/components/responses/NotFound'
/admin/metadata-schemas/by-role:
get:
summary: 按角色查询元数据字段定义
description: |-
[AC-MRS-04][AC-MRS-05] 按指定角色查询所有包含该角色的活跃字段定义。
operationId: getMetadataSchemasByRole
tags:
- MetadataSchema
parameters:
- name: role
in: query
required: true
description: 字段角色
schema:
$ref: '#/components/schemas/FieldRole'
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
- name: include_deprecated
in: query
description: 是否包含已废弃字段
schema:
type: boolean
default: false
responses:
'200':
description: 成功返回字段定义列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/MetadataFieldDefinition'
'400':
description: 无效的角色参数
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error_code: INVALID_ROLE
message: "Invalid role 'invalid_role'. Valid roles are: resource_filter, slot, prompt_var, routing_signal"
/admin/slot-definitions:
get:
summary: 获取槽位定义列表
operationId: listSlotDefinitions
tags:
- SlotDefinition
parameters:
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
- name: required
in: query
description: 是否必填槽位过滤
schema:
type: boolean
responses:
'200':
description: 成功返回槽位定义列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SlotDefinition'
post:
summary: 创建槽位定义
description: |-
[AC-MRS-07][AC-MRS-08] 创建新的槽位定义,可关联已有元数据字段。
operationId: createSlotDefinition
tags:
- SlotDefinition
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SlotDefinitionCreate'
responses:
'201':
description: 创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/SlotDefinition'
'400':
$ref: '#/components/responses/BadRequest'
/admin/slot-definitions/{id}:
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
get:
summary: 获取单个槽位定义
operationId: getSlotDefinition
tags:
- SlotDefinition
responses:
'200':
description: 成功返回槽位定义
content:
application/json:
schema:
$ref: '#/components/schemas/SlotDefinition'
'404':
$ref: '#/components/responses/NotFound'
put:
summary: 更新槽位定义
operationId: updateSlotDefinition
tags:
- SlotDefinition
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SlotDefinitionUpdate'
responses:
'200':
description: 更新成功
content:
application/json:
schema:
$ref: '#/components/schemas/SlotDefinition'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
delete:
summary: 删除槽位定义
description: |-
[AC-MRS-16] 删除槽位定义,无需考虑历史数据兼容性。
operationId: deleteSlotDefinition
tags:
- SlotDefinition
responses:
'204':
description: 删除成功
'404':
$ref: '#/components/responses/NotFound'
/mid/slots/by-role:
get:
summary: 运行时按角色获取槽位定义
description: |-
[AC-MRS-10] 运行时接口,按角色获取槽位定义及关联的元数据字段信息。
operationId: getSlotsByRole
tags:
- RuntimeSlot
parameters:
- name: role
in: query
required: true
schema:
$ref: '#/components/schemas/FieldRole'
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 成功返回槽位定义列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SlotDefinitionWithField'
'400':
$ref: '#/components/responses/BadRequest'
/mid/slots/{slot_key}:
parameters:
- name: slot_key
in: path
required: true
schema:
type: string
get:
summary: 获取运行时槽位值
description: |-
[AC-MRS-09] 获取指定槽位的运行时值,包含来源、置信度、更新时间。
operationId: getSlotValue
tags:
- RuntimeSlot
parameters:
- name: tenant_id
in: query
required: true
schema:
type: string
format: uuid
- name: user_id
in: query
required: true
schema:
type: string
format: uuid
- name: session_id
in: query
required: true
schema:
type: string
format: uuid
responses:
'200':
description: 成功返回槽位值
content:
application/json:
schema:
$ref: '#/components/schemas/RuntimeSlotValue'
'404':
description: 槽位不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
FieldRole:
type: string
enum:
- resource_filter
- slot
- prompt_var
- routing_signal
description: |
字段角色类型:
- resource_filter: 资源过滤角色
- slot: 运行时槽位角色
- prompt_var: 提示词变量角色
- routing_signal: 路由信号角色
MetadataFieldStatus:
type: string
enum:
- draft
- active
- deprecated
MetadataScope:
type: string
enum:
- kb_document
- intent_rule
- script_flow
- prompt_template
MetadataFieldType:
type: string
enum:
- string
- number
- boolean
- enum
- array_enum
MetadataFieldDefinition:
type: object
required:
- id
- tenant_id
- field_key
- label
- type
- status
- field_roles
properties:
id:
type: string
format: uuid
tenant_id:
type: string
format: uuid
field_key:
type: string
pattern: '^[a-z][a-z0-9_]*$'
description: 字段键名,仅允许小写字母数字下划线
label:
type: string
description: 显示名称
type:
$ref: '#/components/schemas/MetadataFieldType'
required:
type: boolean
default: false
options:
type: array
items:
type: string
description: 选项列表enum/array_enum 类型必填)
default_value:
description: 默认值
scope:
type: array
items:
$ref: '#/components/schemas/MetadataScope'
description: 适用范围
is_filterable:
type: boolean
default: false
is_rank_feature:
type: boolean
default: false
field_roles:
type: array
items:
$ref: '#/components/schemas/FieldRole'
description: 字段角色列表
status:
$ref: '#/components/schemas/MetadataFieldStatus'
version:
type: integer
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
MetadataFieldDefinitionCreate:
type: object
required:
- tenant_id
- field_key
- label
- type
properties:
tenant_id:
type: string
format: uuid
field_key:
type: string
pattern: '^[a-z][a-z0-9_]*$'
label:
type: string
minLength: 1
maxLength: 100
type:
$ref: '#/components/schemas/MetadataFieldType'
required:
type: boolean
default: false
options:
type: array
items:
type: string
default_value:
type: object
scope:
type: array
items:
$ref: '#/components/schemas/MetadataScope'
is_filterable:
type: boolean
default: false
is_rank_feature:
type: boolean
default: false
field_roles:
type: array
items:
$ref: '#/components/schemas/FieldRole'
description: 字段角色列表,可为空
MetadataFieldDefinitionUpdate:
type: object
properties:
label:
type: string
minLength: 1
maxLength: 100
required:
type: boolean
options:
type: array
items:
type: string
default_value:
type: object
scope:
type: array
items:
$ref: '#/components/schemas/MetadataScope'
is_filterable:
type: boolean
is_rank_feature:
type: boolean
field_roles:
type: array
items:
$ref: '#/components/schemas/FieldRole'
status:
$ref: '#/components/schemas/MetadataFieldStatus'
ExtractStrategy:
type: string
enum:
- rule
- llm
- user_input
description: |
槽位提取策略:
- rule: 规则提取
- llm: LLM 推断
- user_input: 用户输入
SlotSource:
type: string
enum:
- user_confirmed
- rule_extracted
- llm_inferred
- default
SlotDefinition:
type: object
required:
- id
- tenant_id
- slot_key
- type
- required
properties:
id:
type: string
format: uuid
tenant_id:
type: string
format: uuid
slot_key:
type: string
pattern: '^[a-z][a-z0-9_]*$'
description: 槽位键名
type:
$ref: '#/components/schemas/MetadataFieldType'
required:
type: boolean
description: 是否必填槽位
extract_strategy:
$ref: '#/components/schemas/ExtractStrategy'
validation_rule:
type: string
description: 校验规则(正则或 JSON Schema
ask_back_prompt:
type: string
description: 追问提示语模板
default_value:
description: 默认值
linked_field_id:
type: string
format: uuid
description: 关联的元数据字段 ID
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
SlotDefinitionCreate:
type: object
required:
- tenant_id
- slot_key
- type
- required
properties:
tenant_id:
type: string
format: uuid
slot_key:
type: string
pattern: '^[a-z][a-z0-9_]*$'
type:
$ref: '#/components/schemas/MetadataFieldType'
required:
type: boolean
extract_strategy:
$ref: '#/components/schemas/ExtractStrategy'
validation_rule:
type: string
ask_back_prompt:
type: string
default_value:
type: object
linked_field_id:
type: string
format: uuid
SlotDefinitionUpdate:
type: object
properties:
type:
$ref: '#/components/schemas/MetadataFieldType'
required:
type: boolean
extract_strategy:
$ref: '#/components/schemas/ExtractStrategy'
validation_rule:
type: string
ask_back_prompt:
type: string
default_value:
type: object
linked_field_id:
type: string
format: uuid
SlotDefinitionWithField:
type: object
description: 槽位定义与关联字段信息
allOf:
- $ref: '#/components/schemas/SlotDefinition'
- type: object
properties:
linked_field:
$ref: '#/components/schemas/MetadataFieldDefinition'
RuntimeSlotValue:
type: object
required:
- key
- value
- source
- confidence
properties:
key:
type: string
description: 槽位键名
value:
description: 槽位值
source:
$ref: '#/components/schemas/SlotSource'
description: 槽位来源
confidence:
type: number
format: float
minimum: 0.0
maximum: 1.0
description: 置信度
updated_at:
type: string
format: date-time
description: 最后更新时间
ErrorResponse:
type: object
required:
- error_code
- message
properties:
error_code:
type: string
message:
type: string
details:
type: object
additionalProperties: true
responses:
BadRequest:
description: 请求参数错误
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error_code: BAD_REQUEST
message: "Invalid request parameters"
Unauthorized:
description: 未授权
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error_code: UNAUTHORIZED
message: "Authentication required"
NotFound:
description: 资源不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error_code: NOT_FOUND
message: "Resource not found"

View File

@ -0,0 +1,156 @@
---
feature_id: "MRS"
title: "元数据职责分层优化"
status: "draft"
version: "0.1.0"
active_version: "0.1.0"
version_history:
- version: "0.1.0"
ac_range: "AC-MRS-01~16"
description: "元数据字段职责分层、槽位模型独立化、工具协同改造与管理端配置能力"
owners:
- "product"
- "backend"
- "frontend"
last_updated: "2026-03-05"
source:
type: "conversation"
ref: "元数据职责过载问题优化需求"
---
# 元数据职责分层优化MRS
## 1. 背景与目标
### 1.1 背景
当前系统中元数据字段承担了多种隐式职责,导致以下问题:
1. **职责混淆**:同一字段(如 `grade`)同时用于资源过滤、运行时槽位、提示词变量和路由信号,但系统无法区分其具体用途
2. **工具耦合**`kb_search_dynamic`、`memory_recall`、`intent_hint`、`high_risk_check` 等工具全量消费元数据字段,无法按需筛选
3. **槽位语义模糊**:槽位与元数据字段概念混淆,缺少独立的槽位定义模型
4. **配置不可视**:管理端无法按职责视角查看和配置字段
### 1.2 目标
- 为元数据字段引入显式的 `field_roles` 职责分层
- 建立独立的槽位定义模型,与元数据字段解耦但可复用
- 改造工具链按职责角色消费字段,实现精准消费
- 提供管理端按角色配置和查看的能力
### 1.3 非目标Out of Scope
- 不处理历史数据迁移,允许删除重建配置
- 不新增元数据字段类型(保持 string/number/boolean/enum/array_enum
- 不替换向量引擎或 LLM 供应商
- 不覆盖渠道端具体实现
## 2. 模块边界Scope
- 覆盖:元数据字段职责分层、槽位定义模型、工具协同改造、管理端配置能力
- 不覆盖:历史数据迁移、向量引擎替换、模型切换、渠道端实现
## 3. 依赖盘点Dependencies
- `metadata-governance` 模块:元数据字段定义基础能力
- `intent-driven-mid-platform` 模块:中台运行时工具链
- `ai-service-admin` 前端:管理端配置界面
## 4. 用户故事User Stories
- [US-MRS-01] 作为系统架构师,我希望元数据字段有明确的职责角色标记,以便工具能按需消费。
- [US-MRS-02] 作为后端开发者,我希望通过接口按角色查询字段定义,以便精准获取所需字段。
- [US-MRS-03] 作为运营配置人员,我希望在管理端按角色过滤查看字段,以便快速定位配置。
- [US-MRS-04] 作为对话系统开发者,我希望槽位有独立的定义模型,以便管理运行时槽位语义。
- [US-MRS-05] 作为工具开发者,我希望 `kb_search_dynamic` 只消费资源过滤角色字段,以便避免无关字段干扰。
- [US-MRS-06] 作为工具开发者,我希望 `memory_recall` 只消费槽位角色字段,以便精准管理对话槽位。
- [US-MRS-07] 作为工具开发者,我希望 `intent_hint/high_risk_check` 只消费路由信号角色字段,以便精准路由决策。
- [US-MRS-08] 作为提示词工程师,我希望 prompt 渲染只消费提示词变量角色字段,以便控制注入范围。
## 5. 验收标准Acceptance Criteria, EARS
### 5.1 字段职责分层
- [AC-MRS-01] WHEN 管理员创建或编辑元数据字段 THEN 系统 SHALL 支持 `field_roles` 多选配置,可选值为 `resource_filter`、`slot`、`prompt_var`、`routing_signal`。
- [AC-MRS-02] WHEN 保存字段定义时 `field_roles` 为空 THEN 系统 SHALL 允许保存(默认无职责)。
- [AC-MRS-03] WHEN 字段定义包含多个 `field_roles` THEN 系统 SHALL 正确存储并返回所有角色。
### 5.2 分层视图能力
- [AC-MRS-04] WHEN 调用 `GET /admin/metadata-schemas/by-role?role=resource_filter` THEN 系统 SHALL 返回所有 `field_roles` 包含 `resource_filter` 的活跃字段定义。
- [AC-MRS-05] WHEN 调用按角色查询接口且角色参数无效 THEN 系统 SHALL 返回 400 错误并提示有效角色列表。
- [AC-MRS-06] WHEN 管理端请求字段列表 THEN 系统 SHALL 支持按 `field_roles` 过滤展示。
### 5.3 槽位模型
- [AC-MRS-07] WHEN 管理员创建槽位定义 THEN 系统 SHALL 支持 `slot_key`、`type`、`required`、`extract_strategy`、`validation_rule`、`ask_back_prompt` 属性配置。
- [AC-MRS-08] WHEN 槽位定义的 `slot_key` 与已有元数据字段 `field_key` 相同 THEN 系统 SHALL 允许创建并建立关联关系。
- [AC-MRS-09] WHEN 运行时读取槽位值 THEN 系统 SHALL 返回 `source`(来源)、`confidence`(置信度)、`updated_at`(更新时间)属性。
- [AC-MRS-10] WHEN 调用 `GET /mid/slots/by-role?role=slot` THEN 系统 SHALL 返回所有 `field_roles` 包含 `slot` 的字段定义及关联的槽位定义。
### 5.4 工具协同改造
- [AC-MRS-11] WHEN `kb_search_dynamic` 构建过滤器 THEN 系统 SHALL 仅使用 `field_roles` 包含 `resource_filter` 的字段。
- [AC-MRS-12] WHEN `memory_recall` 召回槽位 THEN 系统 SHALL 仅使用 `field_roles` 包含 `slot` 的字段。
- [AC-MRS-13] WHEN `intent_hint``high_risk_check` 进行路由判断 THEN 系统 SHALL 仅使用 `field_roles` 包含 `routing_signal` 的字段。
- [AC-MRS-14] WHEN 模板引擎渲染 prompt THEN 系统 SHALL 仅使用 `field_roles` 包含 `prompt_var` 的字段。
### 5.5 管理端可配置能力
- [AC-MRS-15] WHEN 管理员在元数据字段编辑界面 THEN 系统 SHALL 显示 `field_roles` 多选配置组件。
- [AC-MRS-16] WHEN 管理员删除字段或槽位定义 THEN 系统 SHALL 允许删除且无需考虑历史数据兼容性。
## 6. 追踪映射Traceability
| AC ID | Endpoint | 方法 | operationId | 备注 |
|------|----------|------|-------------|------|
| AC-MRS-01 | /admin/metadata-schemas | POST | createMetadataSchema | field_roles 配置 |
| AC-MRS-01 | /admin/metadata-schemas/{id} | PUT | updateMetadataSchema | field_roles 配置 |
| AC-MRS-02 | /admin/metadata-schemas | POST | createMetadataSchema | 空角色允许 |
| AC-MRS-03 | /admin/metadata-schemas | POST | createMetadataSchema | 多角色存储 |
| AC-MRS-04 | /admin/metadata-schemas/by-role | GET | getMetadataSchemasByRole | 按角色查询 |
| AC-MRS-05 | /admin/metadata-schemas/by-role | GET | getMetadataSchemasByRole | 无效角色校验 |
| AC-MRS-06 | /admin/metadata-schemas | GET | listMetadataSchemas | 按角色过滤 |
| AC-MRS-07 | /admin/slot-definitions | POST | createSlotDefinition | 槽位定义创建 |
| AC-MRS-08 | /admin/slot-definitions | POST | createSlotDefinition | 关联元数据字段 |
| AC-MRS-09 | /mid/slots/{slot_key} | GET | getSlotValue | 运行时槽位值 |
| AC-MRS-10 | /mid/slots/by-role | GET | getSlotsByRole | 按角色获取槽位 |
| AC-MRS-11 | 内部调用 | - | kb_search_dynamic | resource_filter 消费 |
| AC-MRS-12 | 内部调用 | - | memory_recall | slot 消费 |
| AC-MRS-13 | 内部调用 | - | intent_hint/high_risk_check | routing_signal 消费 |
| AC-MRS-14 | 内部调用 | - | template_engine | prompt_var 消费 |
| AC-MRS-15 | 前端页面 | - | - | field_roles 配置组件 |
| AC-MRS-16 | /admin/metadata-schemas/{id} | DELETE | deleteMetadataSchema | 删除无需兼容 |
| AC-MRS-16 | /admin/slot-definitions/{id} | DELETE | deleteSlotDefinition | 删除无需兼容 |
## 7. 字段角色定义
| 角色标识 | 中文名称 | 用途说明 | 消费工具 |
|---------|---------|---------|---------|
| `resource_filter` | 资源过滤 | 用于 KB 文档检索时的元数据过滤 | `kb_search_dynamic` |
| `slot` | 运行时槽位 | 对话流程中的结构化槽位,用于信息收集 | `memory_recall` |
| `prompt_var` | 提示词变量 | 注入到 LLM Prompt 中的变量 | `template_engine` |
| `routing_signal` | 路由信号 | 用于意图路由和风险判断的信号 | `intent_hint`, `high_risk_check` |
## 8. 槽位定义属性
| 属性 | 类型 | 必填 | 说明 |
|-----|------|-----|------|
| `slot_key` | string | 是 | 槽位键名,可与 field_key 关联 |
| `type` | enum | 是 | 槽位类型string/number/boolean/enum/array_enum |
| `required` | boolean | 是 | 是否必填槽位 |
| `extract_strategy` | enum | 否 | 提取策略rule/llm/user_input |
| `validation_rule` | string | 否 | 校验规则(正则或 JSON Schema |
| `ask_back_prompt` | string | 否 | 追问提示语模板 |
| `default_value` | any | 否 | 默认值 |
| `linked_field_id` | uuid | 否 | 关联的元数据字段 ID |
## 9. 运行时槽位值属性
| 属性 | 类型 | 说明 |
|-----|------|------|
| `key` | string | 槽位键名 |
| `value` | any | 槽位值 |
| `source` | enum | 来源user_confirmed/rule_extracted/llm_inferred/default |
| `confidence` | float | 置信度 0.0~1.0 |
| `updated_at` | datetime | 最后更新时间 |

View File

@ -0,0 +1,145 @@
# 元数据职责分层模块边界Scope
## 1. 模块边界说明
### 1.1 覆盖范围
本模块聚焦于**元数据字段的职责分层与运行时消费解耦**,具体包括:
1. **字段职责分层**
- 为元数据字段引入 `field_roles` 多选属性
- 支持四种职责角色:`resource_filter`、`slot`、`prompt_var`、`routing_signal`
- 单个字段可同时承担多种职责
2. **分层视图能力**
- 后端提供按 role 查询字段的能力
- 工具与模块按 role 消费,不再全量混用
3. **槽位模型增强**
- 引入独立的槽位定义模型(可复用元数据字段但有独立运行时语义)
- 支持 `slot_key/type/required/extract_strategy/validation_rule/ask_back_prompt`
- 运行时值包含 `source/confidence/updated_at`
4. **工具协同改造**
- `kb_search_dynamic` 只消费 `resource_filter` 角色
- `memory_recall` 只消费 `slot` 角色
- `intent_hint/high_risk_check` 只消费 `routing_signal` 角色
- prompt 渲染只消费 `prompt_var` 角色
5. **管理端可配置能力**
- 元数据字段编辑界面增加 `field_roles` 配置
- 提供"按 role 过滤查看"能力
- 允许删除重建配置(无需迁移兼容)
### 1.2 不覆盖范围
- **历史数据迁移**:本迭代不负责历史数据的自动迁移,允许删除重建配置
- **向量引擎替换**:不涉及 Qdrant 或其他向量引擎的替换
- **LLM 模型切换**:不涉及模型供应商或模型选型的变更
- **渠道端实现**:不覆盖渠道侧 SegmentDispatcher/InterruptManager 等具体实现
- **元数据字段类型扩展**不新增字段类型string/number/boolean/enum/array_enum 保持不变)
---
## 2. 依赖盘点
### 2.1 内部依赖
| 依赖模块 | 用途说明 | 接口 |
|---------|---------|------|
| `metadata-governance` | 元数据字段定义基础能力 | `/admin/metadata-schemas` |
| `intent-driven-mid-platform` | 中台运行时工具链 | `kb_search_dynamic`, `memory_recall`, `intent_hint`, `high_risk_check` |
| `ai-service-admin` | 管理端前端页面 | 元数据配置界面 |
### 2.2 外部依赖
| 依赖服务 | 用途说明 |
|---------|---------|
| PostgreSQL | 元数据字段定义、槽位定义存储 |
| Redis | 运行时缓存 |
---
## 3. 依赖接口清单
### 3.1 本模块依赖的外部接口Consumer
| 接口 | 来源模块 | 用途 |
|------|---------|------|
| `GET /admin/metadata-schemas` | metadata-governance | 获取元数据字段列表 |
| `POST /admin/metadata-schemas` | metadata-governance | 创建元数据字段 |
| `PUT /admin/metadata-schemas/{id}` | metadata-governance | 更新元数据字段 |
| `DELETE /admin/metadata-schemas/{id}` | metadata-governance | 删除元数据字段 |
### 3.2 本模块对外提供的接口Provider
| 接口 | 用途 |
|------|------|
| `GET /admin/metadata-schemas/by-role` | 按 role 查询字段定义 |
| `GET /admin/slot-definitions` | 获取槽位定义列表 |
| `POST /admin/slot-definitions` | 创建槽位定义 |
| `PUT /admin/slot-definitions/{id}` | 更新槽位定义 |
| `DELETE /admin/slot-definitions/{id}` | 删除槽位定义 |
| `GET /mid/slots/by-role` | 运行时按 role 获取槽位定义 |
---
## 4. 数据模型边界
### 4.1 新增模型
| 模型名 | 说明 |
|-------|------|
| `SlotDefinition` | 槽位定义表(独立于 MetadataFieldDefinition |
### 4.2 扩展模型
| 模型名 | 扩展字段 |
|-------|---------|
| `MetadataFieldDefinition` | 新增 `field_roles: list[str]` 字段 |
---
## 5. 工具消费关系
```
┌─────────────────────────────────────────────────────────────────┐
│ 元数据字段职责分层 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ MetadataFieldDefinition │
│ └── field_roles: [resource_filter, slot, prompt_var, │
│ routing_signal] │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│resource_filter│ │ slot │ │ prompt_var │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│kb_search_ │ │memory_recall │ │template_engine│
│dynamic │ │ │ │ │
└───────────────┘ └───────────────┘ └───────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ routing_signal │
└───────┬─────────────────────────────────────────────────────────┘
├───────────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│intent_hint │ │high_risk_check│
└───────────────┘ └───────────────┘
```
---
## 6. 版本与迭代
- 当前版本:`v0.1.0`
- AC 范围:`AC-MRS-01 ~ AC-MRS-16`
- 迭代策略:允许删除重建配置,不考虑历史数据迁移

View File

@ -0,0 +1,311 @@
# 元数据职责分层优化 - 任务清单
## 任务概览
| 阶段 | 任务数 | 状态 |
|------|-------|------|
| Phase 1: 数据模型扩展 | 4 | ✅ 已完成 |
| Phase 2: 后端服务实现 | 6 | ✅ 已完成 |
| Phase 3: 工具协同改造 | 4 | ✅ 已完成 |
| Phase 4: 前端页面改造 | 3 | ⏳ 待开始 |
| Phase 5: 测试与验收 | 3 | ⏳ 待开始 |
---
## Phase 1: 数据模型扩展
### Task 1.1: 扩展 MetadataFieldDefinition 模型
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-01, AC-MRS-02, AC-MRS-03
- **描述**: 在现有 `MetadataFieldDefinition` 模型中新增 `field_roles` 字段
- **产出**:
- 修改 `ai-service/app/models/entities.py` 中的 `MetadataFieldDefinition`
- 新增 `FieldRole` 枚举类
- **验收标准**:
- `field_roles` 字段类型为 `list[str]`
- 支持存储多个角色
- 允许空列表
### Task 1.2: 创建 SlotDefinition 模型
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-07, AC-MRS-08
- **描述**: 创建独立的槽位定义模型
- **产出**:
- 在 `ai-service/app/models/entities.py` 中新增 `SlotDefinition`
- 新增 `ExtractStrategy` 枚举类
- **验收标准**:
- 包含所有必需字段slot_key, type, required, extract_strategy, validation_rule, ask_back_prompt
- 支持 linked_field_id 关联元数据字段
### Task 1.3: 编写数据库迁移脚本
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-01, AC-MRS-07
- **描述**: 编写 PostgreSQL 迁移脚本
- **产出**:
- 创建 `ai-service/scripts/migrations/007_add_field_roles_and_slot_definitions.sql`
- **验收标准**:
- 为 `metadata_field_definitions` 表新增 `field_roles`
- 创建 `slot_definitions`
- 创建必要的索引
### Task 1.4: 更新 Pydantic Schema
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-01, AC-MRS-07
- **描述**: 更新请求/响应 Schema
- **产出**:
- 创建 `ai-service/app/schemas/metadata.py`
- 新增 `SlotDefinitionCreate/Update/Response` Schema
- **验收标准**:
- Schema 与 OpenAPI 契约一致
- 包含完整的字段校验规则
---
## Phase 2: 后端服务实现
### Task 2.1: 实现 RoleBasedFieldProvider 服务
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-04, AC-MRS-05, AC-MRS-10
- **描述**: 实现按角色查询字段的核心服务
- **产出**:
- 创建 `ai-service/app/services/mid/role_based_field_provider.py`
- **验收标准**:
- `get_fields_by_role()` 方法正确查询指定角色的字段
- 无效角色返回 400 错误
- 支持缓存机制
### Task 2.2: 扩展 MetadataFieldDefinitionService
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-01, AC-MRS-02, AC-MRS-03, AC-MRS-06
- **描述**: 扩展现有服务支持 field_roles
- **产出**:
- 修改 `ai-service/app/services/metadata_field_definition_service.py`
- **验收标准**:
- 创建/更新时支持 field_roles 字段
- 支持按 role 过滤查询
- field_roles 校验正确
### Task 2.3: 实现 SlotDefinitionService
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-07, AC-MRS-08
- **描述**: 实现槽位定义管理服务
- **产出**:
- 创建 `ai-service/app/services/slot_definition_service.py`
- **验收标准**:
- CRUD 操作正确
- 支持关联元数据字段
- slot_key 租户内唯一
### Task 2.4: 扩展 MetadataFieldDefinition API
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-01, AC-MRS-04, AC-MRS-05, AC-MRS-06, AC-MRS-16
- **描述**: 扩展现有 API 端点
- **产出**:
- 修改 `ai-service/app/api/admin/metadata_field_definition.py`
- 新增 `/by-role` 端点
- **验收标准**:
- 所有端点符合 OpenAPI 契约
- 包含 AC 注释
### Task 2.5: 实现 SlotDefinition API
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-07, AC-MRS-08, AC-MRS-16
- **描述**: 实现槽位定义管理 API
- **产出**:
- 创建 `ai-service/app/api/admin/slot_definition.py`
- **验收标准**:
- CRUD 端点符合 OpenAPI 契约
- 包含 AC 注释
### Task 2.6: 实现运行时槽位 API
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-09, AC-MRS-10
- **描述**: 实现运行时槽位查询 API
- **产出**:
- 创建 `ai-service/app/api/mid/slots.py`
- **验收标准**:
- `/mid/slots/by-role` 端点正确返回槽位定义
- `/mid/slots/{slot_key}` 端点正确返回运行时值
---
## Phase 3: 工具协同改造
### Task 3.1: 改造 kb_search_dynamic 工具
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-11
- **描述**: 改造 KB 动态检索工具,只消费 resource_filter 角色
- **产出**:
- 修改 `ai-service/app/services/mid/kb_search_dynamic_tool.py`
- 修改 `ai-service/app/services/mid/metadata_filter_builder.py`
- **验收标准**:
- 只使用 field_roles 包含 resource_filter 的字段
- 不影响现有功能
### Task 3.2: 改造 memory_recall 工具
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-12
- **描述**: 改造记忆召回工具,只消费 slot 角色
- **产出**:
- 修改 `ai-service/app/services/mid/memory_recall_tool.py`
- **验收标准**:
- 只使用 field_roles 包含 slot 的字段
- 槽位合并逻辑正确
### Task 3.3: 改造 intent_hint 和 high_risk_check 工具
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-13
- **描述**: 改造意图提示和高风险检测工具,只消费 routing_signal 角色
- **产出**:
- 修改 `ai-service/app/services/mid/intent_hint_tool.py`
- 修改 `ai-service/app/services/mid/high_risk_check_tool.py`
- **验收标准**:
- 只使用 field_roles 包含 routing_signal 的字段
- 路由判断逻辑正确
### Task 3.4: 改造 template_engine
- [x] **状态**: ✅ 已完成
- **AC**: AC-MRS-14
- **描述**: 改造模板引擎,只消费 prompt_var 角色
- **产出**:
- 修改 `ai-service/app/services/flow/template_engine.py`
- **验收标准**:
- 只使用 field_roles 包含 prompt_var 的字段
- 模板渲染正确
---
## Phase 4: 前端页面改造
### Task 4.1: 元数据字段配置页面增加 field_roles
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-15
- **描述**: 在元数据字段编辑表单中增加角色选择组件
- **产出**:
- 创建 `ai-service-admin/src/components/metadata/FieldRolesSelector.vue`
- 修改 `ai-service-admin/src/views/admin/metadata-schema/index.vue`
- **验收标准**:
- 支持多选角色
- 显示角色说明
- 保存时正确提交
### Task 4.2: 增加按角色过滤视图
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-06
- **描述**: 在元数据字段列表页面增加角色过滤功能
- **产出**:
- 修改 `ai-service-admin/src/views/admin/metadata-schema/index.vue`
- **验收标准**:
- 下拉框选择角色
- 过滤结果正确
### Task 4.3: 槽位定义管理页面
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-07, AC-MRS-08, AC-MRS-16
- **描述**: 创建槽位定义管理页面
- **产出**:
- 创建 `ai-service-admin/src/views/admin/slot-definition/index.vue`
- 创建 `ai-service-admin/src/api/slot-definition.ts`
- **验收标准**:
- 支持 CRUD 操作
- 支持关联元数据字段
---
## Phase 5: 测试与验收
### Task 5.1: 单元测试
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-01~16
- **描述**: 编写单元测试
- **产出**:
- `ai-service/tests/test_role_based_field_provider.py`
- `ai-service/tests/test_slot_definition_service.py`
- `ai-service/tests/test_field_roles.py`
- **验收标准**:
- 覆盖核心逻辑
- 测试通过
### Task 5.2: 集成测试
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-01~16
- **描述**: 编写 API 集成测试
- **产出**:
- `ai-service/tests/api/test_metadata_field_roles.py`
- `ai-service/tests/api/test_slot_definition.py`
- **验收标准**:
- 覆盖所有 API 端点
- 测试通过
### Task 5.3: 契约测试
- [ ] **状态**: ⏳ 待开始
- **AC**: AC-MRS-01~16
- **描述**: 验证 API 符合 OpenAPI 契约
- **产出**:
- 运行契约测试
- 修复不一致
- **验收标准**:
- Provider 契约达到 L2 级别
- 所有响应符合 Schema
---
## 任务依赖关系
```
Phase 1 (数据模型)
├── Task 1.1 (扩展 MetadataFieldDefinition)
├── Task 1.2 (创建 SlotDefinition)
├── Task 1.3 (迁移脚本) ← 依赖 1.1, 1.2
└── Task 1.4 (更新 Schema) ← 依赖 1.1, 1.2
Phase 2 (后端服务)
├── Task 2.1 (RoleBasedFieldProvider) ← 依赖 1.4
├── Task 2.2 (扩展 MetadataFieldService) ← 依赖 1.4
├── Task 2.3 (SlotDefinitionService) ← 依赖 1.4
├── Task 2.4 (扩展 MetadataField API) ← 依赖 2.2
├── Task 2.5 (SlotDefinition API) ← 依赖 2.3
└── Task 2.6 (运行时槽位 API) ← 依赖 2.1, 2.3
Phase 3 (工具改造)
├── Task 3.1 (kb_search_dynamic) ← 依赖 2.1
├── Task 3.2 (memory_recall) ← 依赖 2.1
├── Task 3.3 (intent_hint/high_risk_check) ← 依赖 2.1
└── Task 3.4 (template_engine) ← 依赖 2.1
Phase 4 (前端改造)
├── Task 4.1 (field_roles 组件) ← 依赖 2.4
├── Task 4.2 (角色过滤视图) ← 依赖 2.4
└── Task 4.3 (槽位定义页面) ← 依赖 2.5
Phase 5 (测试验收)
├── Task 5.1 (单元测试) ← 依赖 Phase 2
├── Task 5.2 (集成测试) ← 依赖 Phase 2, 3, 4
└── Task 5.3 (契约测试) ← 依赖 5.2
```
---
## 执行顺序建议
1. **Phase 1****Phase 2****Phase 3****Phase 4** → **Phase 5**
2. Phase 3 和 Phase 4 可并行执行
3. 每个 Task 完成后需更新状态并提交
---
## 变更记录
| 日期 | 变更内容 | 变更人 |
|------|---------|-------|
| 2026-03-05 | 初始创建 | AI Agent |
| 2026-03-05 | 完成 Phase 3 工具协同改造 (Task 3.1-3.4) [AC-MRS-11~14] | AI Agent |