一、实验目的
1、掌握百度AI Studio平台的基本使用方法。
2、学习ERNIE-UIE模型在信息抽取任务中的应用。
3、掌握Python模型封装和Java接口调用的技术。
4、实现中医症状信息抽取的功能开发。
二、实验学时
2学时
三、实验类型
综合性
四、实验需求
1、硬件
每⼈配备计算机1台,建议优先使⽤个⼈计算机开展实验。
2、软件
安装IntelliJ IDEA Community,安装Python 3.7+环境,安装Node.js环境。
3、⽹络
本地主机能够访问互联⽹和实验中⼼⽹络。
4、⼯具
⽆。
五、实验任务
1、注册百度AI Studio账号并创建项目。
2、在AI Studio平台上使用ERNIE-UIE模型
3、将uie-medical-base模型封装为Python接口
4、Java调用Python接口实现业务逻辑
5、前端调用Java接口实现主诉症状标准化
6、结合系统实现智能增强
六、实验内容及步骤
1、注册百度AI Studio账号并创建项目
步骤1:访问AI Studio官网注册个人账号。
打开浏览器,访问网址 aistudio.baidu.com/,点击页面右上角的“登录/注册”按钮,选择使用百度账号进行登录,若尚未拥有账号则可注册新账号,具体操作可参考图1。
步骤2:查找ERNIE-UIE模型
登录后进入AI Studio控制台,点击左侧导航栏的“模型库”,接着在搜索框中输入“ERNIE-UIE”,如图2所示,找到对应的模型并点击进入其详情页,如图3所示。
步骤3:学习模型范例
点击“模型范例”中的“快递单信息抽取”,仔细阅读示例代码和说明文档,了解UIE模型的基本使用流程,如图4所示。
步骤4:创建项目并启动环境
点击"运行一下"按钮,系统会自动创建项目,如图5所示,点击启动环境,等待环境初始化完成(约1-2分钟)即可进入操作,如图6所示。
💡 在选择运行环境时,建议优先选用包含GPU的环境,以便在进行模型微调时使用。
2、 在AI Studio平台上使用ERNIE-UIE模型
💡 参照参考项目中的文档说明,按要求依次执行操作。若执行失败,可尝试重试几次;特别是在环境准备阶段,依赖下载失败可能是由网络问题所致。
步骤1:点击代码前边的执行按钮,完成paddlenlp的环境准备,如图7、8所示。
步骤2:使用默认配置进行快递信息抽取
PaddleNLP已经封装了NLP的模型,可直接使用,具体示例如图9所示。
步骤3:模型微调
使用默认配置抽取快递信息时,电话、详细地址类的数据没有抽取出来,因此可对模型进行微调,具体微调步骤如下。
- 安装doccano(请勿在AI Studio内部运行,需下载至本地执行)
- 初始化数据库和账户
- 启动doccano服务
- 运行doccano标注实体和关系
具体请参考项目的《5.1 数据标注》节。
本实验可使用已经标注好的数据执行模型微调,如图11、12所示。
步骤4:使用之前的数据和微调后的模型测试微调效果,如图13所示。
3、将uie-medical-base模型封装为Python接口
步骤1:配置Paddle运行环境,创建requirements.txt,记录所需要的依赖,并执行命令安装依赖。
# requirements.txt
flask==2.3.3
paddlenlp==2.6.0
requests==2.31.0
werkzeug==2.3.7
pip install -r requirements.txt
步骤2:创建model_loader.py文件配置模型专用方法。
# model_loader.py
from paddlenlp import Taskflow
import logging
class MedicalModel:
def __init__(self):
self.model = None
self.schema = ['症状', '部位', '性质', '程度', '诱发因素', '缓解因素']
def load_model(self):
"""加载医疗专用模型"""
try:
self.model = Taskflow('information_extraction',
schema=self.schema,
model='uie-medical-base')
logging.info("医疗模型加载成功")
return True
except Exception as e:
logging.error(f"模型加载失败: {e}")
return False
def predict(self, text):
"""症状信息抽取预测"""
if not self.model:
raise Exception("模型未加载")
return self.model(text)
步骤3:创建app.py,使用Flask框架开发Web接口实现模型调用
# app.py
from flask import Flask, request, jsonify
from model_loader import MedicalModel
import logging
app = Flask(__name__)
medical_model = MedicalModel()
# 在应用启动时初始化模型
with app.app_context():
medical_model.load_model()
@app.route('/api/health', methods=['GET'])
def health_check():
"""健康检查接口"""
return jsonify({"status": "healthy", "model_loaded": medical_model.model is not None})
@app.route('/api/extract-symptoms', methods=['POST'])
def extract_symptoms():
"""症状信息抽取接口"""
try:
data = request.get_json()
if not data or 'text' not in data:
return jsonify({"error": "缺少text参数"}), 400
text = data['text']
if len(text.strip()) == 0:
return jsonify({"error": "文本内容为空"}), 400
# 调用模型进行预测
result = medical_model.predict(text)
return jsonify({
"success": True,
"data": result,
"text": text
})
except Exception as e:
logging.error(f"症状抽取失败: {str(e)}")
return jsonify({"error": str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)
步骤4:启动项目,PaddleNLP将自动下载指定的模型并加载,具体运行记录如图13所示。
python app.py
步骤5:接口测试与验证
打开APIPost输入主诉数据,进行模型测试,如图14所示。
4、Java调用Python接口实现业务逻辑
步骤1:创建Spring Boot项目结构,示例代码如下。
<!-- pom.xml 依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
步骤2:实现Python接口调用服务,示例代码如下。
// SymptomExtractionService.java
@Service
public class SymptomExtractionService {
private static final Logger logger = LoggerFactory.getLogger(SymptomExtractionService.class);
@Value("${python.api.url:http://localhost:5000}")
private String pythonApiUrl;
private final RestTemplate restTemplate;
public SymptomExtractionService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder
.setConnectTimeout(Duration.ofSeconds(30))
.setReadTimeout(Duration.ofSeconds(60))
.build();
}
public SymptomExtractionResult extractSymptoms(String text) {
try {
// 构建请求
String url = pythonApiUrl + "/api/extract-symptoms";
Map<String, String> request = new HashMap<>();
request.put("text", text);
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Map<String, String>> entity = new HttpEntity<>(request, headers);
// 发送请求
ResponseEntity<SymptomExtractionResult> response = restTemplate.exchange(
url, HttpMethod.POST, entity, SymptomExtractionResult.class);
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return response.getBody();
} else {
throw new SymptomExtractionException("Python服务调用失败");
}
} catch (Exception e) {
logger.error("症状抽取服务调用异常", e);
throw new SymptomExtractionException("症状抽取服务暂时不可用", e);
}
}
}
步骤3:定义数据模型,示例代码如下。
// SymptomExtractionResult.java
@Data
public class SymptomExtractionResult {
private Boolean success;
private String text;
private List<SymptomEntity> data;
private String error;
@Data
public static class SymptomEntity {
private String type;
private List<EntityInfo> entities;
}
@Data
public static class EntityInfo {
private String text;
private Double probability;
private Integer start;
private Integer end;
}
}
步骤3:创建RESTful API控制器,示例代码如下。
// SymptomController.java
@RestController
@RequestMapping("/api/symptoms")
@Validated
public class SymptomController {
private final SymptomExtractionService extractionService;
public SymptomController(SymptomExtractionService extractionService) {
this.extractionService = extractionService;
}
@PostMapping("/extract")
public ResponseEntity<?> extractSymptoms(@Valid @RequestBody SymptomRequest request) {
try {
SymptomExtractionResult result = extractionService.extractSymptoms(request.getText());
return ResponseEntity.ok(result);
} catch (SymptomExtractionException e) {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(Map.of("error", e.getMessage()));
}
}
@Data
public static class SymptomRequest {
@NotBlank(message = "文本内容不能为空")
@Size(max = 1000, message = "文本长度不能超过1000字符")
private String text;
}
}
5、前端调用Java接口实现主诉症状标准化
步骤1:实现症状标准化组件,示例代码如下。
推荐结合实验10通过语音识别录入主诉,后通过UIE抽取关键字。
<!-- SymptomStandardization.vue -->
<template>
<div class="symptom-standardization">
<h2>中医主诉症状标准化系统</h2>
<!-- 症状输入区域 -->
<div class="input-section">
<textarea
v-model="symptomText"
placeholder="请输入患者主诉症状描述..."
:disabled="loading"
@keyup.enter="extractSymptoms"
></textarea>
<div class="button-group">
<button
@click="extractSymptoms"
:disabled="!symptomText || loading"
class="primary-btn"
>
{{ loading ? '处理中...' : '症状标准化' }}
</button>
<button @click="clearInput" class="secondary-btn">
清空
</button>
</div>
</div>
<!-- 标准化结果显示 -->
<div v-if="results" class="results-section">
<h3>标准化结果</h3>
<div v-for="(result, index) in results" :key="index" class="result-category">
<h4>{{ getCategoryName(result.type) }}</h4>
<div v-for="entity in result.entities" :key="entity.text" class="entity-item">
<span class="entity-text">{{ entity.text }}</span>
<span class="confidence">(置信度: {{ (entity.probability * 100).toFixed(1) }}%)</span>
</div>
</div>
</div>
<!-- 错误提示 -->
<div v-if="error" class="error-message">
{{ error }}
</div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-spinner">
正在分析症状信息...
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
const symptomText = ref('')
const results = ref(null)
const loading = ref(false)
const error = ref('')
// API基础URL
const API_BASE = 'http://localhost:8080/api'
// 症状类型映射
const categoryMap = {
'症状': '主要症状',
'部位': '发病部位',
'性质': '症状性质',
'程度': '严重程度',
'诱发因素': '诱发因素',
'缓解因素': '缓解因素'
}
const getCategoryName = (type) => {
return categoryMap[type] || type
}
// 提取症状信息
const extractSymptoms = async () => {
if (!symptomText.value.trim()) {
error.value = '请输入症状描述'
return
}
loading.value = true
error.value = ''
results.value = null
try {
const response = await axios.post(`${API_BASE}/symptoms/extract`, {
text: symptomText.value
})
if (response.data.success) {
results.value = response.data.data
} else {
error.value = '症状提取失败'
}
} catch (err) {
error.value = err.response?.data?.error || '网络请求失败'
console.error('症状提取错误:', err)
} finally {
loading.value = false
}
}
// 清空输入
const clearInput = () => {
symptomText.value = ''
results.value = null
error.value = ''
}
</script>
<style scoped>
.symptom-standardization {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.input-section textarea {
width: 100%;
height: 120px;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
resize: vertical;
}
.button-group {
margin-top: 10px;
display: flex;
gap: 10px;
}
.primary-btn, .secondary-btn {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.primary-btn {
background: #1890ff;
color: white;
}
.primary-btn:disabled {
background: #ccc;
cursor: not-allowed;
}
.secondary-btn {
background: #f5f5f5;
color: #333;
}
.results-section {
margin-top: 20px;
padding: 15px;
border: 1px solid #e8e8e8;
border-radius: 4px;
}
.result-category {
margin-bottom: 15px;
}
.entity-item {
padding: 5px 0;
border-bottom: 1px solid #f0f0f0;
}
.entity-text {
font-weight: bold;
color: #1890ff;
}
.confidence {
color: #666;
font-size: 12px;
}
.error-message {
color: #ff4d4f;
padding: 10px;
background: #fff2f0;
border-radius: 4px;
margin-top: 10px;
}
.loading-spinner {
text-align: center;
padding: 20px;
color: #1890ff;
}
</style>
步骤2:测试并验证功能
按照以下顺序依次启动系统:
- 启动Python服务:python app.py
- 启动Java服务:运行Spring Boot应用
- 启动前端服务:npm run dev
测试症状信息正确抽取和分类,置信度显示合理,错误处理机制正常,界面交互流畅。
6、结合系统实现智能增强
步骤1:功能设计
结合系统功能实现基于智能算法的智能增强,例如症状、疾病信息的标准化或自行引入其他模型(如使用OCR模型实现处方内容识别)。
步骤2:编码实现
(1)使用百度AI Studio选择模型进行训练或者微调,形成专属的模型。
(2)实现模型的调用封装,需要正确处理各种输入格式,设置合适的超时机制和重试策略,保证服务的稳定性。
(3)开发业务处理逻辑,需要设计合理的数据结构来存储和传递分析结果,确保信息的完整性和准确性。
(4)实现友好的命令行交互界面,提供清晰的进度反馈和状态提示。优化结果展示格式,同时需要完善错误处理和异常提示机制。
步骤3:测试优化
验证每个功能模块的正确性,重点实现模型处理、API调用等,确保系统在各种情况下都能正常工作,特别是边界情况和异常场景。
七、实验考核
1、本课程实验考核方案
本课程实验考核采用【实验智能评】【实验随堂查】方式开展,根据不同的实验内容选择不同的考核方式。
【实验智能评】:实验完成后提交GitLab,通过自动化代码评审工具进行评分。
【实验随堂查】:在实验课上通过现场演示的方式向实验指导教师进行汇报,并完成现场问答交流。
2、本实验考核要求
本实验考核方式:实验智能评
实验10-12作为本课程第3次实验考核。
考核要求:
(1)学生通过GitLab提交实验成果:{此部分说明需要提交的内容}。
(2)由GitLab根据成果和交流情况综合评分。