Spring AI Alibaba 医疗信息系统集成实战教程

项目地址​:https://github.com/crablduck/springbootAI-alibaba-learn
技术栈​:Spring Boot 3.2.0 + Spring AI 1.0.0-M1 + 通义千问
项目名称​:spring-ai-his-demo


第一章:快速入门

1.1 项目结构

spring-ai-his-demo/
├── src/main/java/com/etong/ai/his/
│   ├── HisAiApplication.java          # 启动类
│   ├── config/
│   │   └── ChatConfig.java            # ChatClient配置
│   ├── controller/
│   │   └── HisAiController.java       # REST控制器
│   ├── service/
│   │   └── AiService.java             # 业务逻辑
│   └── model/
│       ├── DiagnosisRequest.java      # 请求模型
│       └── AiResponse.java            # 响应模型
├── src/main/resources/
│   ├── application.yml                # 配置文件
│   └── prompts/
│       └── his_qa_prompt.yaml         # 提示词模板
└── pom.xml                            # Maven配置

1.2 Maven 依赖配置

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>

    <groupId>com.etong.ai</groupId>
    <artifactId>spring-ai-his-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-ai.version>1.0.0-M1</spring-ai.version>
    </properties>

    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring AI Core -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-core</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <!-- Spring AI OpenAI (通义千问兼容) -->
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Actuator 监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Validation -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>

    <!-- Spring Milestone仓库 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

1.3 配置文件

src/main/resources/application.yml

server:
  port: 8080

spring:
  application:
    name: spring-ai-his-demo

  ai:
    openai:
      api-key: ${DASHSCOPE_API_KEY}  # 通义千问API Key
      base-url: https://dashscope.aliyuncs.com/compatible-mode
      chat:
        options:
          model: qwen-turbo
          temperature: 0.7
          max-tokens: 1000

# 日志配置
logging:
  level:
    com.etong.ai.his: DEBUG
    org.springframework.ai: DEBUG
  file:
    name: logs/spring-ai-his-demo.log

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics

1.4 核心代码

启动类

HisAiApplication.java

package com.etong.ai.his;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootApplication
public class HisAiApplication {
    public static void main(String[] args) {
        log.info("正在启动Spring AI HIS系统...");
        SpringApplication.run(HisAiApplication.class, args);
        log.info("系统启动完成");
    }
}

配置类

ChatConfig.java

package com.etong.ai.his.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ChatConfig {

    @Bean
    public ChatClient chatClient(ChatClient.Builder builder) {
        return builder.build();
    }
}

数据模型

DiagnosisRequest.java

package com.etong.ai.his.model;

import lombok.Data;
import org.hibernate.validator.constraints.Length;

@Data
public class DiagnosisRequest {
    
    @Length(min = 1, message = "症状描述不能为空")
    private String symptom;
    
    private String patientId;
    private String age;
    private String gender;
    private String medicalHistory;
}

AiResponse.java

package com.etong.ai.his.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AiResponse {
    private String result;
    private boolean success;
    private String message;
    private long timestamp;

    public AiResponse(String result, boolean success, String message) {
        this.result = result;
        this.success = success;
        this.message = message;
        this.timestamp = System.currentTimeMillis();
    }
}

控制器层

HisAiController.java

package com.etong.ai.his.controller;

import com.etong.ai.his.service.AiService;
import com.etong.ai.his.model.DiagnosisRequest;
import com.etong.ai.his.model.AiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/ai")
@Slf4j
public class HisAiController {

    @Autowired
    private AiService aiService;

    /**
     * 诊断建议
     */
    @PostMapping("/diagnosis")
    public ResponseEntity<AiResponse> askDiagnosis(@RequestBody DiagnosisRequest request) {
        log.info("收到诊断请求: {}", request.getSymptom());
        
        try {
            String result = aiService.askDiagnosis(request.getSymptom());
            return ResponseEntity.ok(new AiResponse(result, true, "诊断成功"));
        } catch (Exception e) {
            log.error("诊断失败", e);
            return ResponseEntity.internalServerError()
                .body(new AiResponse(null, false, "诊断失败: " + e.getMessage()));
        }
    }

    /**
     * 病历摘要
     */
    @PostMapping("/summarize")
    public ResponseEntity<AiResponse> summarizeMedicalRecord(@RequestBody DiagnosisRequest request) {
        log.info("收到病历摘要请求");
        
        try {
            String result = aiService.summarizeMedicalRecord(request.getSymptom());
            return ResponseEntity.ok(new AiResponse(result, true, "摘要生成成功"));
        } catch (Exception e) {
            log.error("摘要生成失败", e);
            return ResponseEntity.internalServerError()
                .body(new AiResponse(null, false, "摘要失败: " + e.getMessage()));
        }
    }

    /**
     * 健康咨询
     */
    @PostMapping("/consultation")
    public ResponseEntity<AiResponse> healthConsultation(@RequestBody DiagnosisRequest request) {
        log.info("收到健康咨询: {}", request.getSymptom());
        
        try {
            String result = aiService.healthConsultation(request.getSymptom());
            return ResponseEntity.ok(new AiResponse(result, true, "咨询完成"));
        } catch (Exception e) {
            log.error("咨询失败", e);
            return ResponseEntity.internalServerError()
                .body(new AiResponse(null, false, "咨询失败: " + e.getMessage()));
        }
    }

    /**
     * 健康检查
     */
    @GetMapping("/health")
    public ResponseEntity<String> health() {
        return ResponseEntity.ok("系统运行正常");
    }
}

业务逻辑层

AiService.java

package com.etong.ai.his.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class AiService {

    @Autowired
    private ChatClient chatClient;

    /**
     * 诊断建议
     */
    public String askDiagnosis(String symptom) {
        log.info("开始诊断,症状: {}", symptom);
        
        try {
            String prompt = buildDiagnosisPrompt(symptom);
            log.debug("提示词: {}", prompt);
            
            String response = chatClient.prompt()
                    .user(prompt)
                    .call()
                    .content();
            
            log.info("诊断完成");
            return response;
        } catch (Exception e) {
            log.error("AI调用失败", e);
            throw new RuntimeException("AI服务暂时不可用", e);
        }
    }

    /**
     * 病历摘要
     */
    public String summarizeMedicalRecord(String medicalRecord) {
        log.info("开始生成病历摘要");
        
        try {
            String prompt = buildSummaryPrompt(medicalRecord);
            
            String response = chatClient.prompt()
                    .user(prompt)
                    .call()
                    .content();
            
            log.info("摘要生成完成");
            return response;
        } catch (Exception e) {
            log.error("AI调用失败", e);
            throw new RuntimeException("摘要服务暂时不可用", e);
        }
    }

    /**
     * 健康咨询
     */
    public String healthConsultation(String question) {
        log.info("健康咨询: {}", question);
        
        try {
            String prompt = buildHealthPrompt(question);
            
            String response = chatClient.prompt()
                    .user(prompt)
                    .call()
                    .content();
            
            log.info("咨询完成");
            return response;
        } catch (Exception e) {
            log.error("AI调用失败", e);
            throw new RuntimeException("咨询服务暂时不可用", e);
        }
    }

    /**
     * 构建诊断提示词
     */
    private String buildDiagnosisPrompt(String symptom) {
        return String.format("""
            你是医院问诊助手,根据症状给出初步诊断建议。
            
            患者症状:%s
            
            请分析:
            1. 可能的疾病
            2. 建议检查项目
            3. 临时缓解措施
            4. 何时需立即就医
            
            注意:
            - 这是初步建议,不能替代医生诊断
            - 症状严重请及时就医
            - 回答要专业、清晰、易懂
            
            用中文回答。
            """, symptom);
    }

    /**
     * 构建病历摘要提示词
     */
    private String buildSummaryPrompt(String medicalRecord) {
        return String.format("""
            你是医疗信息专家,请生成结构化病历摘要。
            
            病历内容:%s
            
            按以下格式整理:
            ## 患者基本信息
            ## 主诉
            ## 现病史
            ## 既往史
            ## 检查结果
            ## 诊断
            ## 治疗方案
            ## 注意事项
            
            要求简洁、准确、重点突出。
            """, medicalRecord);
    }

    /**
     * 构建健康咨询提示词
     */
    private String buildHealthPrompt(String question) {
        return String.format("""
            你是健康顾问,请回答健康咨询问题。
            
            问题:%s
            
            回答原则:
            1. 基于医学知识
            2. 语言通俗易懂
            3. 强调重要建议
            4. 必要时建议就医
            5. 不提供药物剂量
            
            用中文回答。
            """, question);
    }
}

1.5 运行测试

启动应用
# 设置API Key环境变量
export DASHSCOPE_API_KEY=sk-your-api-key

# 启动应用
mvn spring-boot:run
测试接口

1. 诊断建议

curl -X POST http://localhost:8080/api/ai/diagnosis \
  -H "Content-Type: application/json" \
  -d '{
    "symptom": "头痛伴发热,体温38.5度,已持续2天"
  }'

响应示例:

{
  "result": "根据您描述的症状...",
  "success": true,
  "message": "诊断成功",
  "timestamp": 1704067200000
}

2. 病历摘要

curl -X POST http://localhost:8080/api/ai/summarize \
  -H "Content-Type: application/json" \
  -d '{
    "symptom": "患者张三,男,45岁。主诉:胸痛3小时..."
  }'

3. 健康咨询

curl -X POST http://localhost:8080/api/ai/consultation \
  -H "Content-Type: application/json" \
  -d '{
    "symptom": "如何预防感冒?"
  }'

4. 健康检查

curl http://localhost:8080/api/ai/health

1.6 提示词模板(可选)

src/main/resources/prompts/his_qa_prompt.yaml

template: |
  你是医院问诊助手,根据症状给出初步诊断建议。
  
  患者症状:{symptom}
  
  请分析:
  1. 可能的疾病
  2. 建议检查项目
  3. 临时缓解措施
  4. 何时需立即就医
  
  注意事项:
  - 这是初步建议,不能替代医生诊断
  - 症状严重请及时就医
  - 回答要专业、清晰、易懂

input-variables:
  - symptom

metadata:
  version: "1.0"
  department: "general"

1.7 关键要点

框架核心

  • Spring AI 提供统一的 AI 模型接入抽象
  • 通义千问通过 OpenAI 兼容层接入
  • ChatClient 封装所有模型交互细节

项目特点

  • 清晰的分层架构:Controller → Service → AI Model
  • 统一的异常处理和响应格式
  • 完整的日志记录便于调试

提示词工程

  • 明确 AI 角色定位(医院助手)
  • 结构化输出要求(分点分析)
  • 责任声明(初步建议,非医生诊断)

1.8 练习任务

  1. 添加多轮对话​:实现会话记忆,支持上下文对话
  2. 专科诊断​:为不同科室设计专门的提示词模板
  3. 监控指标​:统计 API 调用次数、响应时间、成功率

作者:在路上的蟹老板
项目地址:spring-ai-his-demo
版本:v1.0.0

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐