Skip to main content

mofa_plugins/tools/
medical_knowledge.rs

1use super::*;
2use serde::{Deserialize, Serialize};
3use serde_json::json;
4use std::fs;
5use std::path::PathBuf;
6use std::sync::{Arc, RwLock};
7
8/// 疾病诊断标准
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct DiseaseDiagnosis {
11    /// 疾病名称
12    pub disease_name: String,
13    /// 诊断标准
14    pub criteria: Vec<String>,
15    /// 最新更新日期
16    pub update_date: String,
17    /// 来源
18    pub source: String,
19}
20
21/// 治疗方案
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct TreatmentPlan {
24    /// 疾病名称
25    pub disease_name: String,
26    /// 治疗方案
27    pub plan: Vec<String>,
28    /// 最新更新日期
29    pub update_date: String,
30    /// 来源
31    pub source: String,
32}
33
34/// 医疗知识存储
35#[derive(Debug, Clone, Serialize, Deserialize, Default)]
36pub struct MedicalKnowledge {
37    /// 疾病诊断标准
38    pub diagnoses: Vec<DiseaseDiagnosis>,
39    /// 治疗方案
40    pub treatments: Vec<TreatmentPlan>,
41}
42
43/// 医疗知识动态注入工具
44pub struct MedicalKnowledgeTool {
45    definition: ToolDefinition,
46    knowledge: Arc<RwLock<MedicalKnowledge>>,
47    knowledge_path: Arc<RwLock<PathBuf>>,
48}
49
50impl Default for MedicalKnowledgeTool {
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56impl MedicalKnowledgeTool {
57    pub fn new() -> Self {
58        let tool_def = ToolDefinition {
59            name: "medical_knowledge".to_string(),
60            description: "Medical diagnosis knowledge management: dynamically injects and updates the latest disease diagnosis standards and treatment plans at runtime.".to_string(),
61            parameters: json!({
62                "type": "object",
63                "properties": {
64                    "action": {
65                        "type": "string",
66                        "enum": ["inject_knowledge", "query_diagnosis", "query_treatment", "refresh_knowledge"],
67                        "description": "Action to perform on medical knowledge"
68                    },
69                    "knowledge": {
70                        "type": "object",
71                        "description": "Medical knowledge data to inject (required for inject_knowledge)"
72                    },
73                    "disease": {
74                        "type": "string",
75                        "description": "Disease name (required for query_diagnosis, query_treatment)"
76                    },
77                    "file_path": {
78                        "type": "string",
79                        "description": "Path to JSON file containing medical knowledge (for inject_knowledge and refresh_knowledge)"
80                    }
81                },
82                "required": ["action"]
83            }),
84            requires_confirmation: false,
85        };
86
87        Self {
88            definition: tool_def,
89            knowledge: Arc::new(RwLock::new(MedicalKnowledge::default())),
90            knowledge_path: Arc::new(RwLock::new(PathBuf::from("medical_knowledge.json"))),
91        }
92    }
93
94    /// 从JSON文件加载医疗知识
95    async fn load_knowledge_from_file(&self, file_path: &str) -> PluginResult<MedicalKnowledge> {
96        let content = fs::read_to_string(file_path)?;
97        let knowledge: MedicalKnowledge = serde_json::from_str(&content)?;
98        Ok(knowledge)
99    }
100
101    /// 保存医疗知识到文件
102    async fn save_knowledge_to_file(&self, knowledge: &MedicalKnowledge) -> PluginResult<()> {
103        let content = serde_json::to_string_pretty(knowledge)?;
104        let path = self.knowledge_path.read().unwrap();
105        fs::write(&*path, content)?; // 解引用RwLockReadGuard
106        Ok(())
107    }
108}
109
110#[async_trait::async_trait]
111impl ToolExecutor for MedicalKnowledgeTool {
112    fn definition(&self) -> &ToolDefinition {
113        &self.definition
114    }
115
116    async fn execute(&self, arguments: serde_json::Value) -> PluginResult<serde_json::Value> {
117        let action = arguments["action"]
118            .as_str()
119            .ok_or_else(|| anyhow::anyhow!("Action is required"))?;
120
121        match action {
122            // 注入知识(支持JSON数据或文件路径)
123            "inject_knowledge" => {
124                let new_knowledge = if let Some(knowledge_json) = arguments.get("knowledge") {
125                    // 从JSON数据注入
126                    serde_json::from_value(knowledge_json.clone())?
127                } else if let Some(file_path) = arguments["file_path"].as_str() {
128                    // 从文件注入
129                    self.load_knowledge_from_file(file_path).await?
130                } else {
131                    return Err(anyhow::anyhow!(
132                        "Either knowledge JSON or file_path must be provided for inject_knowledge"
133                    ));
134                };
135
136                // 获取统计信息
137                let diagnoses_count = new_knowledge.diagnoses.len();
138                let treatments_count = new_knowledge.treatments.len();
139
140                // 保存到文件
141                self.save_knowledge_to_file(&new_knowledge).await?;
142
143                // 更新内存中的知识
144                let mut knowledge = self.knowledge.write().unwrap();
145                knowledge.diagnoses = new_knowledge.diagnoses;
146                knowledge.treatments = new_knowledge.treatments;
147
148                Ok(json!({
149                    "success": true,
150                    "message": format!("Injected medical knowledge successfully. {} diagnoses and {} treatments loaded.", diagnoses_count, treatments_count)
151                }))
152            }
153
154            // 查询诊断标准
155            "query_diagnosis" => {
156                let disease = arguments["disease"].as_str().ok_or_else(|| {
157                    anyhow::anyhow!("Disease name is required for query_diagnosis")
158                })?;
159
160                let knowledge = self.knowledge.read().unwrap();
161
162                if let Some(diagnosis) = knowledge
163                    .diagnoses
164                    .iter()
165                    .find(|d| d.disease_name.to_lowercase() == disease.to_lowercase())
166                {
167                    Ok(serde_json::to_value(diagnosis)?)
168                } else {
169                    Ok(json!({
170                        "success": false,
171                        "message": format!("No diagnosis information found for disease: {}", disease)
172                    }))
173                }
174            }
175
176            // 查询治疗方案
177            "query_treatment" => {
178                let disease = arguments["disease"].as_str().ok_or_else(|| {
179                    anyhow::anyhow!("Disease name is required for query_treatment")
180                })?;
181
182                let knowledge = self.knowledge.read().unwrap();
183
184                if let Some(treatment) = knowledge
185                    .treatments
186                    .iter()
187                    .find(|t| t.disease_name.to_lowercase() == disease.to_lowercase())
188                {
189                    Ok(serde_json::to_value(treatment)?)
190                } else {
191                    Ok(json!({
192                        "success": false,
193                        "message": format!("No treatment information found for disease: {}", disease)
194                    }))
195                }
196            }
197
198            // 刷新知识(从文件重新加载)
199            "refresh_knowledge" => {
200                // 使用当前知识文件路径
201                let file_path = if let Some(path) = arguments["file_path"].as_str() {
202                    path.to_string()
203                } else {
204                    // 使用当前知识文件路径
205                    let path = self.knowledge_path.read().unwrap();
206                    path.to_str()
207                        .unwrap_or("medical_knowledge.json")
208                        .to_string()
209                };
210
211                let new_knowledge = self.load_knowledge_from_file(&file_path).await?;
212
213                // 获取统计信息
214                let diagnoses_count = new_knowledge.diagnoses.len();
215                let treatments_count = new_knowledge.treatments.len();
216
217                // 更新内存中的知识
218                let mut knowledge = self.knowledge.write().unwrap();
219                knowledge.diagnoses = new_knowledge.diagnoses;
220                knowledge.treatments = new_knowledge.treatments;
221
222                Ok(json!({
223                    "success": true,
224                    "message": format!("Refreshed medical knowledge successfully from {}. {} diagnoses and {} treatments loaded.", file_path, diagnoses_count, treatments_count)
225                }))
226            }
227
228            _ => Err(anyhow::anyhow!("Unsupported action: {}", action)),
229        }
230    }
231}