feat(ai): 添加知识库 trait 和 DTO — KnowledgeSource/PatientSummary/Reference
Phase 3 Task 19: 定义统一知识获取接口,支持未来向量检索扩展
This commit is contained in:
116
crates/erp-ai/src/knowledge/mod.rs
Normal file
116
crates/erp-ai/src/knowledge/mod.rs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::error::AiResult;
|
||||||
|
|
||||||
|
/// 知识源 trait — 统一结构化和未来向量检索的知识获取接口
|
||||||
|
#[async_trait]
|
||||||
|
pub trait KnowledgeSource: Send + Sync {
|
||||||
|
/// 根据查询获取知识上下文
|
||||||
|
async fn get_context(&self, query: &KnowledgeQuery) -> AiResult<KnowledgeContext>;
|
||||||
|
|
||||||
|
/// 知识源类型标识
|
||||||
|
fn source_type(&self) -> &str;
|
||||||
|
|
||||||
|
/// 健康检查
|
||||||
|
async fn health_check(&self) -> AiResult<bool>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 知识查询参数
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct KnowledgeQuery {
|
||||||
|
pub tenant_id: Uuid,
|
||||||
|
pub analysis_type: String,
|
||||||
|
pub patient_context: Option<PatientSummary>,
|
||||||
|
pub query_text: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 脱敏患者摘要(不含 PII)
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct PatientSummary {
|
||||||
|
pub age: Option<i32>,
|
||||||
|
pub gender: Option<String>,
|
||||||
|
pub tags: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 知识上下文(返回给 Prompt 注入)
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct KnowledgeContext {
|
||||||
|
pub source: String,
|
||||||
|
pub context_text: String,
|
||||||
|
pub references: Vec<Reference>,
|
||||||
|
pub confidence: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 参考引用
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Reference {
|
||||||
|
pub title: String,
|
||||||
|
pub source: String,
|
||||||
|
pub relevance_score: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn knowledge_query_construction() {
|
||||||
|
let query = KnowledgeQuery {
|
||||||
|
tenant_id: Uuid::now_v7(),
|
||||||
|
analysis_type: "lab_report".into(),
|
||||||
|
patient_context: Some(PatientSummary {
|
||||||
|
age: Some(65),
|
||||||
|
gender: Some("male".into()),
|
||||||
|
tags: vec!["高血压".into(), "糖尿病".into()],
|
||||||
|
}),
|
||||||
|
query_text: Some("血红蛋白偏低".into()),
|
||||||
|
};
|
||||||
|
assert_eq!(query.analysis_type, "lab_report");
|
||||||
|
assert_eq!(query.patient_context.as_ref().unwrap().tags.len(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn knowledge_context_serde_roundtrip() {
|
||||||
|
let ctx = KnowledgeContext {
|
||||||
|
source: "structured".into(),
|
||||||
|
context_text: "【规则】血压 >140 需关注".into(),
|
||||||
|
references: vec![Reference {
|
||||||
|
title: "高血压指南".into(),
|
||||||
|
source: "system".into(),
|
||||||
|
relevance_score: 0.95,
|
||||||
|
}],
|
||||||
|
confidence: 0.9,
|
||||||
|
};
|
||||||
|
let json = serde_json::to_string(&ctx).unwrap();
|
||||||
|
let back: KnowledgeContext = serde_json::from_str(&json).unwrap();
|
||||||
|
assert_eq!(back.source, "structured");
|
||||||
|
assert_eq!(back.references.len(), 1);
|
||||||
|
assert!((back.confidence - 0.9).abs() < 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn patient_summary_serde() {
|
||||||
|
let summary = PatientSummary {
|
||||||
|
age: Some(70),
|
||||||
|
gender: Some("female".into()),
|
||||||
|
tags: vec![],
|
||||||
|
};
|
||||||
|
let json = serde_json::to_string(&summary).unwrap();
|
||||||
|
let back: PatientSummary = serde_json::from_str(&json).unwrap();
|
||||||
|
assert_eq!(back.age, Some(70));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn truncate_context_text() {
|
||||||
|
let long_text: String = "x".repeat(10000);
|
||||||
|
let max_chars = 8000;
|
||||||
|
let truncated = if long_text.len() > max_chars {
|
||||||
|
long_text[..max_chars].to_string()
|
||||||
|
} else {
|
||||||
|
long_text
|
||||||
|
};
|
||||||
|
assert_eq!(truncated.len(), max_chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ pub mod dto;
|
|||||||
pub mod entity;
|
pub mod entity;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
|
pub mod knowledge;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
pub mod prompt;
|
pub mod prompt;
|
||||||
pub mod provider;
|
pub mod provider;
|
||||||
|
|||||||
Reference in New Issue
Block a user