feat(ai): Phase 3A RAG 知识库 — CRUD API + Agent Tool + 向量知识源 + 前端管理页

- 知识库 REST API: 10 个端点 (references/guides CRUD + re-embed)
- search_medical_knowledge Agent Tool: 语义检索参考资料和临床指南
- VectorKnowledgeSource: 实现 KnowledgeSource trait,自动降级
- 沙箱配置: Patient/MedicalStaff 允许使用知识库检索
- 前端 AiKnowledgePage: Tabs(参考资料/临床指南) + Table + Modal CRUD
- 权限码 seed 迁移: ai.knowledge.list + ai.knowledge.manage + 菜单
This commit is contained in:
iven
2026-05-19 09:10:53 +08:00
parent c0570dfbfc
commit 8b88cb4a50
18 changed files with 1389 additions and 5 deletions

View File

@@ -138,6 +138,19 @@ impl ErpModule for AiModule {
description: "查看 AI 客服会话消息历史".into(),
module: "ai".into(),
},
// 知识库权限
PermissionDescriptor {
code: "ai.knowledge.list".into(),
name: "查看知识库".into(),
description: "查看 AI 知识库(参考资料和临床指南)".into(),
module: "ai".into(),
},
PermissionDescriptor {
code: "ai.knowledge.manage".into(),
name: "管理知识库".into(),
description: "创建/编辑/删除 AI 知识库条目".into(),
module: "ai".into(),
},
]
}
@@ -502,6 +515,47 @@ impl AiModule {
"/ai/suggestions/{id}/feedback",
axum::routing::post(crate::handler::suggestion_handler::submit_feedback),
)
// 知识库路由
.route(
"/ai/knowledge/references",
axum::routing::get(crate::handler::knowledge_handler::list_references),
)
.route(
"/ai/knowledge/references",
axum::routing::post(crate::handler::knowledge_handler::create_reference),
)
.route(
"/ai/knowledge/references/{id}",
axum::routing::put(crate::handler::knowledge_handler::update_reference),
)
.route(
"/ai/knowledge/references/{id}",
axum::routing::delete(crate::handler::knowledge_handler::delete_reference),
)
.route(
"/ai/knowledge/references/{id}/re-embed",
axum::routing::post(crate::handler::knowledge_handler::re_embed_reference),
)
.route(
"/ai/knowledge/guides",
axum::routing::get(crate::handler::knowledge_handler::list_guides),
)
.route(
"/ai/knowledge/guides",
axum::routing::post(crate::handler::knowledge_handler::create_guide),
)
.route(
"/ai/knowledge/guides/{id}",
axum::routing::put(crate::handler::knowledge_handler::update_guide),
)
.route(
"/ai/knowledge/guides/{id}",
axum::routing::delete(crate::handler::knowledge_handler::delete_guide),
)
.route(
"/ai/knowledge/guides/{id}/re-embed",
axum::routing::post(crate::handler::knowledge_handler::re_embed_guide),
)
.route(
"/ai/dialysis/risk-assessment",
axum::routing::post(crate::handler::assess_dialysis_risk),