97 lines
3.1 KiB
Rust
97 lines
3.1 KiB
Rust
use async_trait::async_trait;
|
|
use erp_core::health_provider::TimeRange;
|
|
|
|
use crate::agent::tool::{AgentTool, DisplayHint, ToolContext, ToolResult};
|
|
|
|
/// 查询患者最近体征数据(血压/血糖/心率等)
|
|
pub struct QueryPatientVitalsTool;
|
|
|
|
#[async_trait]
|
|
impl AgentTool for QueryPatientVitalsTool {
|
|
fn name(&self) -> &str {
|
|
"query_patient_vitals"
|
|
}
|
|
|
|
fn description(&self) -> &str {
|
|
"查询患者最近的体征数据(血压、血糖、心率、体重、血氧等)。需要提供天数范围(默认 7 天)。"
|
|
}
|
|
|
|
fn parameters_schema(&self) -> serde_json::Value {
|
|
serde_json::json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"days": {
|
|
"type": "integer",
|
|
"description": "查询最近多少天的数据,默认 7 天"
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
async fn execute(&self, ctx: &ToolContext, params: serde_json::Value) -> ToolResult {
|
|
let patient_id = match ctx.patient_id {
|
|
Some(id) => id,
|
|
None => {
|
|
return ToolResult {
|
|
output: "未关联患者档案,无法查询体征数据".to_string(),
|
|
display_hint: None,
|
|
};
|
|
}
|
|
};
|
|
|
|
let days = params["days"].as_i64().unwrap_or(7);
|
|
let now = chrono::Utc::now();
|
|
let start = now - chrono::Duration::days(days);
|
|
|
|
let range = TimeRange { start, end: now };
|
|
let metrics = vec![
|
|
"systolic_bp_morning".into(),
|
|
"diastolic_bp_morning".into(),
|
|
"heart_rate".into(),
|
|
"blood_sugar".into(),
|
|
];
|
|
|
|
match ctx
|
|
.health_provider
|
|
.get_vital_signs(ctx.tenant_id, patient_id, &metrics, &range)
|
|
.await
|
|
{
|
|
Ok(vitals) => {
|
|
if vitals.is_empty() {
|
|
return ToolResult {
|
|
output: "该时间段内无体征数据".to_string(),
|
|
display_hint: None,
|
|
};
|
|
}
|
|
|
|
let mut output = String::from("最近体征数据:\n");
|
|
for v in &vitals {
|
|
output.push_str(&format!("- {}:", v.metric));
|
|
let values_str: Vec<String> = v
|
|
.values
|
|
.iter()
|
|
.take(10)
|
|
.map(|(date, val)| format!("{}={}", date, val))
|
|
.collect();
|
|
output.push_str(&format!(" ({})\n", values_str.join(", ")));
|
|
}
|
|
|
|
let display_hint = vitals.first().map(|v| DisplayHint::VitalCard {
|
|
indicator_type: v.metric.clone(),
|
|
values: v.values.iter().take(10).cloned().collect(),
|
|
unit: v.unit.clone(),
|
|
});
|
|
|
|
ToolResult {
|
|
output,
|
|
display_hint,
|
|
}
|
|
}
|
|
Err(e) => ToolResult {
|
|
output: format!("查询体征数据失败: {}", e),
|
|
display_hint: None,
|
|
},
|
|
}
|
|
}
|
|
}
|