移除rasa

pull/1/head
liu 11 months ago
parent 42b9deb072
commit 15e8f072d0

@ -28,7 +28,6 @@
<module>virtual-patient-common</module> <module>virtual-patient-common</module>
<module>virtual-patient-model</module> <module>virtual-patient-model</module>
<module>virtual-patient-web</module> <module>virtual-patient-web</module>
<module>virtual-patient-rasa</module>
<module>virtual-patient-graph</module> <module>virtual-patient-graph</module>
<module>virtual-patient-manage</module> <module>virtual-patient-manage</module>
</modules> </modules>

@ -1,19 +0,0 @@
# 设置基础镜像
FROM rasa_dev:1.1.0
COPY ./docs/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
# 设置工作目录
WORKDIR /data/vp
# 复制java jar 到容器中
#COPY target/virtual-patient-rasa-1.0-SNAPSHOT.jar /data/vp/virtual-patient-rasa-1.0-SNAPSHOT.jar
# 复制rasa配置文件到 rasa目录下
COPY docs/rasa /rasa
RUN rm -f /rasa/config-local.yml
# 暴漏服务端口
EXPOSE 8890
# 设置启动命令
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]

@ -1,52 +0,0 @@
#### rasa镜像版本说明
| 镜像名称 | 镜像版本 |镜像id| 说明 |
|----------|-------| --- |-------------------------|
| rasa_dev | 1.0.0 | 365fe9f00bac | rasa镜像基础版本只包含必要的rasa服务 |
| rasa_dev | 1.1.0 | | 在1.0.0的基础上添加text2vec服务 |
| rasa_dev | 2.0.0 | 22313f228098 | 添加rasa-java服务 |
# 文本相似度匹配应用程序
> 这个应用程序使用 text2vec 进行文本相似度匹配,允许用户更新数据集并查询最佳匹配项。
## 安装依赖
```bash
创建环境
conda create text2vec_env python=3.9
进入环境
conda activate text2vec_env
```
```bash
pip install torch
pip install flask
pip install text2vec -i https://pypi.tuna.tsinghua.edu.cn/simple
```
启动应用程序
``` bash
python app.py
```
应用程序将在 http://127.0.0.1:5000/ 上运行。
# API文档
```
API 文档:
1. 更新数据集
- 端点: /update_dataset
- 方法: POST
- 输入: JSON [{"id": "101","question": "你好"},{"id": "541","question": "你好吗?"}]
- 输出: JSON {"status": "success", "message": "数据集更新成功"}
2. 获取匹配项
- 端点: /matches
- 方法: POST
- 输入: JSON {"querySentence": "查询句子", "threshold": 0.7}
- 输出: JSON {"status": "success", "results": [{"id": 1, "sentence": "匹配的句子", "similarity": 0.75}]}
3. 获取所有相似度
- 端点: /get_all_similarities
- 方法: POST
- 输入: JSON {"querySentence": "查询句子"}
- 输出: JSON {"status": "success", "results": [{"id": 1, "sentence": "句子1", "similarity": 0.8}]}
```

@ -1,16 +0,0 @@
# 设置基础镜像
FROM rasa_dev:1.0.0
COPY ./bert_chinese /usr/local/text2vec/bert_chinese
COPY ./app.py /usr/local/text2vec/
#COPY ./question.json /usr/local/text2vec/
RUN source /root/anaconda3/etc/profile.d/conda.sh && \
conda create --name text2vec_env python=3.9 -y && \
conda activate text2vec_env && \
pip install torch && \
pip install flask && \
pip install text2vec -i https://pypi.tuna.tsinghua.edu.cn/simple
expose 5000

@ -1,101 +0,0 @@
from flask import Flask, request, jsonify
from text2vec import SentenceModel
import numpy as np
import traceback
import json
import os
app = Flask(__name__)
# 获取当前脚本所在的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
# BERT模型路径
model_path = os.path.join(current_dir, 'bert_chinese')
model = None
questions_data = [] # 用于存储问题数据
sentence_embeddings = []
default_threshold = 0.7
# 数据集文件路径
dataset_file_path = os.path.join(current_dir, 'question.json')
# 初始化函数,用于加载模型和数据集
def initialize_app():
global model, questions_data, sentence_embeddings
model = SentenceModel(model_path)
load_dataset()
# 加载数据集
def load_dataset():
global questions_data, sentence_embeddings, sentences
try:
with open(dataset_file_path, 'r', encoding='utf-8') as file:
questions_data = json.load(file)
sentences = [item["question"] for item in questions_data]
# 重新编码句子
sentence_embeddings = [model.encode(sent) / np.linalg.norm(model.encode(sent)) for sent in sentences]
except Exception as e:
traceback.print_exc()
print(f"Error loading dataset: {str(e)}")
# 错误处理程序
@app.errorhandler(Exception)
def handle_error(e):
traceback.print_exc()
return jsonify({'error': str(e)}), 500
# 初始化应用
initialize_app()
# 替换数据集的接口
@app.route('/update_dataset', methods=['POST'])
def update_dataset():
global questions_data, sentence_embeddings
new_dataset = request.json or []
# 更新数据集
try:
with open(dataset_file_path, 'w', encoding='utf-8') as file:
json.dump(new_dataset, file, ensure_ascii=False, indent=2)
load_dataset()
return jsonify({'status': 'success', 'message': '数据集更新成功'})
except Exception as e:
traceback.print_exc()
return jsonify({'error': f'更新数据集错误: {str(e)}'}), 500
# 获取匹配的接口
@app.route('/matches', methods=['POST'])
def get_matches():
query_sentence = request.json.get('querySentence', '')
query_embedding = model.encode([query_sentence])[0]
# 对向量进行单位化
query_embedding = query_embedding / np.linalg.norm(query_embedding)
# 获取阈值参数,如果请求中没有提供阈值,则使用默认阈值
threshold = request.json.get('threshold', default_threshold)
# 计算相似度
similarities = [embedding.dot(query_embedding) for embedding in sentence_embeddings]
# 获取所有相似度高于阈值的匹配项
matches = [{'id': questions_data[i]["id"], 'sentence': sentences[i], 'similarity': float(similarity)}
for i, similarity in enumerate(similarities) if similarity >= threshold]
return jsonify({'status': 'success', 'results': matches} if matches else {'status': 'success', 'message': '未找到匹配项'})
# 获取所有相似度的接口
@app.route('/get_all_similarities', methods=['POST'])
def get_all_similarities():
query_sentence = request.json.get('querySentence', '')
query_embedding = model.encode([query_sentence])[0]
# 对向量进行单位化
query_embedding = query_embedding / np.linalg.norm(query_embedding)
# 计算所有数据的相似度和对应的文本
results = [{'id': questions_data[i]["id"], 'sentence': sentences[i], 'similarity': float(embedding.dot(query_embedding))}
for i, embedding in enumerate(sentence_embeddings)]
# 返回所有相似度和对应文本
return jsonify({'status': 'success', 'results': results})
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')

@ -1,32 +0,0 @@
{
"_name_or_path": "hfl/chinese-macbert-base",
"architectures": [
"BertModel"
],
"attention_probs_dropout_prob": 0.1,
"classifier_dropout": null,
"directionality": "bidi",
"gradient_checkpointing": false,
"hidden_act": "gelu",
"hidden_dropout_prob": 0.1,
"hidden_size": 768,
"initializer_range": 0.02,
"intermediate_size": 3072,
"layer_norm_eps": 1e-12,
"max_position_embeddings": 512,
"model_type": "bert",
"num_attention_heads": 12,
"num_hidden_layers": 12,
"pad_token_id": 0,
"pooler_fc_size": 768,
"pooler_num_attention_heads": 12,
"pooler_num_fc_layers": 3,
"pooler_size_per_head": 128,
"pooler_type": "first_token_transform",
"position_embedding_type": "absolute",
"torch_dtype": "float32",
"transformers_version": "4.12.3",
"type_vocab_size": 2,
"use_cache": true,
"vocab_size": 21128
}

File diff suppressed because it is too large Load Diff

@ -1,218 +0,0 @@
[
{
"id": "101",
"question": "你好"
},
{
"id": "152",
"question": "你好吗?"
},
{
"id": "3",
"question": "你好不好啊?"
},
{
"id": "4",
"question": "你怎么样?"
},
{
"id": "5",
"question": "你好吗,今天?"
},
{
"id": "6",
"question": "你近期好吗?"
},
{
"id": "7",
"question": "你好,对吗?"
},
{
"id": "8",
"question": "你还好吗?"
},
{
"id": "9",
"question": "你一切安好吗?"
},
{
"id": "10",
"question": "你好,还是不好?"
},
{
"id": "11",
"question": "你好吗,朋友?"
},
{
"id": "12",
"question": "你近来可好?"
},
{
"id": "12",
"question": "你还好吗,最近?"
},
{
"id": "14",
"question": "你还好吗,朋友?"
},
{
"id": "15",
"question": "你好吗,最近怎么样?"
},
{
"id": "16",
"question": "你好吗,身体怎么样?"
},
{
"id": "17",
"question": "你好吗,心情如何?"
},
{
"id": "18",
"question": "你好吗,一切顺利吗?"
},
{
"id": "19",
"question": "你好吗,有什么新的计划吗?"
},
{
"id": "20",
"question": "你好,有什么想说的吗?"
},
{
"id": "21",
"question": "你好,有什么问题需要我帮忙的吗?"
},
{
"id": "22",
"question": "您以前有过类似情况吗?"
},
{
"id": "23",
"question": "您之前是否遇到过相似的情况?"
},
{
"id": "24",
"question": "您以前有没有经历过这样的事情?"
},
{
"id": "25",
"question": "这种情况以前对您来说是否熟悉?"
},
{
"id": "26",
"question": "您是否有过与这类似的经历?"
},
{
"id": "27",
"question": "在您的经验中,是否有过这样的先例?"
},
{
"id": "28",
"question": "您是否曾面临过相似的挑战?"
},
{
"id": "29",
"question": "这种情境是否让您回想起过去的某些经历?"
},
{
"id": "30",
"question": "您是否曾经历过与此类似的困境?"
},
{
"id": "31",
"question": "这种情况是否以前也发生过?"
},
{
"id": "32",
"question": "您是否曾有过类似的体验?"
},
{
"id": "33",
"question": "以前是否遇到过相似的问题?"
},
{
"id": "34",
"question": "这种情境是否与您过去的经历相符?"
},
{
"id": "35",
"question": "您是否曾经身处于类似的状况?"
},
{
"id": "36",
"question": "您是否有过和这类似的历史?"
},
{
"id": "37",
"question": "这种情况是否让您想起以前的经历?"
},
{
"id": "38",
"question": "您是否曾遭遇过相同的状况?"
},
{
"id": "39",
"question": "您是否有过类似的先例?"
},
{
"id": "40",
"question": "这种情况是否与您的过往经历相似?"
},
{
"id": "41",
"question": "您是否曾经面对过这样的局面?"
},
{
"id": "42",
"question": "您是否有过和这类似的经验?"
},
{
"id": "43",
"question": "您以前有没有因为这些症状看过其他的医生?"
},
{
"id": "44",
"question": "您之前是否因为这些症状咨询过其他医生?"
},
{
"id": "45",
"question": "您是否曾因这些症状求助于其他医生?"
},
{
"id": "46",
"question": "因为这些症状,您以前看过别的医生吗?"
},
{
"id": "47",
"question": "您是否曾因为这些症状去看过其他医生?"
},
{
"id": "48",
"question": "您是否因这些症状找过其他医生?"
},
{
"id": "49",
"question": "关于这些症状,您以前是否咨询过其他医生?"
},
{
"id": "50",
"question": "您是否曾经因为这些症状找过其他医生?"
},
{
"id": "51",
"question": "您是否曾因为这些症状向其他医生寻求帮助?"
},
{
"id": "52",
"question": "关于这些症状,您是否看过其他医生?"
},
{
"id": "53",
"question": "您以前有没有因为这些症状而咨询过其他医生?"
},
{
"id": "54",
"question": "这些症状以前是否让您去看过其他医生?"
}
]

@ -1,9 +0,0 @@
#!/bin/bash
# 启动text2vec服务
source /root/anaconda3/etc/profile.d/conda.sh && \
conda activate text2vec_env && \
nohup python /usr/local/text2vec/app.py &
# 启动jar包
java -jar -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -Xms256m -Xmx1g /data/vp/virtual-patient-rasa-1.0-SNAPSHOT.jar "$@"

@ -1,29 +0,0 @@
recipe: default.v1
language: zh
pipeline:
- name: JiebaTokenizer
- name: LanguageModelFeaturizer
model_name: "bert"
model_weights: "/rasa/bert-base-chinese"
- name: RegexFeaturizer
- name: DIETClassifier
epochs: 100
learning_rate: 0.001
tensorboard_log_directory: ./log
- name: ResponseSelector
epochs: 100
learning_rate: 0.001
- name: FallbackClassifier
threshold: 0.4
ambiguity_threshold: 0.1
- name: EntitySynonymMapper
policies:
- name: MemoizationPolicy
- name: TEDPolicy
- name: RulePolicy
core_fallback_threshold: 0.4
core_fallback_action_name: "action_default_fallback"
enable_fallback_prediction: True

@ -1,33 +0,0 @@
# This file contains the credentials for the voice & chat platforms
# which your bot is using.
# https://rasa.com/docs/rasa/messaging-and-voice-channels
rest:
# # you don't need to provide anything here - this channel doesn't
# # require any credentials
#facebook:
# verify: "<verify>"
# secret: "<your secret>"
# page-access-token: "<your page access token>"
#slack:
# slack_token: "<your slack token>"
# slack_channel: "<the slack channel>"
# slack_signing_secret: "<your slack signing secret>"
#socketio:
# user_message_evt: <event name for user message>
# bot_message_evt: <event name for bot messages>
# session_persistence: <true/false>
#mattermost:
# url: "https://<mattermost instance>/api/v4"
# token: "<bot token>"
# webhook_url: "<callback URL>"
# This entry is needed if you are using Rasa Enterprise. The entry represents credentials
# for the Rasa Enterprise "channel", i.e. Talk to your bot and Share with guest testers.
rasa:
url: "http://localhost:5002/api"

@ -1,51 +0,0 @@
# This file contains the different endpoints your bot can use.
# Server where the models are pulled from.
# https://rasa.com/docs/rasa/model-storage#fetching-models-from-a-server
#models:
# url: http://my-server.com/models/default_core@latest
# wait_time_between_pulls: 10 # [optional](default: 100)
# Server which runs your custom actions.
# https://rasa.com/docs/rasa/custom-actions
action_endpoint:
url: "http://127.0.0.1:5055/webhook"
# Tracker store which is used to store the conversations.
# By default the conversations are stored in memory.
# https://rasa.com/docs/rasa/tracker-stores
#tracker_store:
# type: redis
# url: <host of the redis instance, e.g. localhost>
# port: <port of your redis instance, usually 6379>
# db: <number of your database within redis, e.g. 0>
# password: <password used for authentication>
# use_ssl: <whether or not the communication is encrypted, default false>
#tracker_store:
# type: mongod
# url: <url to your mongo instance, e.g. mongodb://localhost:27017>
# db: <name of the db within your mongo instance, e.g. rasa>
# username: <username used for authentication>
# password: <password used for authentication>
#tracker_store:
# type: mongod
# url: mongodb://192.168.10.137:27017
# db: dialog_test
# username:
# password:
# Event broker which all conversation events should be streamed to.
# https://rasa.com/docs/rasa/event-brokers
#event_broker:
# url: localhost
# username: username
# password: password
# queue: queue

@ -1,112 +0,0 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.supervision</groupId>
<artifactId>virtual-patient</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>virtual-patient-rasa</artifactId>
<packaging>jar</packaging>
<name>virtual-patient-rasa</name>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>virtual-patient-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.supervision</groupId>
<artifactId>virtual-patient-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!--用来生成yml文件,jakson的模板库满足不了多行文本|管道符的需求-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -1,39 +0,0 @@
package com.supervision.rasa;
import com.supervision.config.WebConfig;
import com.supervision.rasa.service.RasaModelManager;
import com.supervision.rasa.service.Text2vecService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@MapperScan(basePackages = {"com.supervision.**.mapper"})
// 排除JWT权限校验
@ComponentScan(basePackages = {"com.supervision"},excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {WebConfig.class}))
@EnableDiscoveryClient
public class VirtualPatientRasaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(VirtualPatientRasaApplication.class, args);
// 启动rasa服务
RasaModelManager rasaModelManager = context.getBean(RasaModelManager.class);
try {
rasaModelManager.wakeUpInterruptServerScheduled();
} catch (Exception e) {
throw new RuntimeException(e);
}
// 初始化文本匹配数据
Text2vecService text2vecService = context.getBean(Text2vecService.class);
text2vecService.initText2vecDataset();
}
}

@ -1,30 +0,0 @@
package com.supervision.rasa.config;
import java.util.ArrayList;
import java.util.concurrent.*;
public class ThreadPoolExecutorConfig {
private volatile static ThreadPoolExecutor instance = null;
private ThreadPoolExecutorConfig(){}
public static ThreadPoolExecutor getInstance() {
new ArrayList<>();
if (instance == null) {
synchronized (ThreadPoolExecutorConfig.class) { // 加锁
if (instance == null) {
int corePoolSize = 5;
int maximumPoolSize = 10;
long keepAliveTime = 100;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(20);
RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();
instance = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, rejectedExecutionHandler);
}
}
}
return instance;
}
}

@ -1,13 +0,0 @@
package com.supervision.rasa.constant;
public class RasaConstant {
public static final String TRAN_SUCCESS_MESSAGE = "Your Rasa model is trained and saved at";
public static final String RUN_SUCCESS_MESSAGE = "Rasa server is up and running";
public static final String RUN_SHELL = "run.sh";
public static final String TRAIN_SHELL = "train.sh";
public static final String KILL_SHELL = "kill.sh";
}

@ -1,56 +0,0 @@
package com.supervision.rasa.controller;
import cn.hutool.core.util.StrUtil;
import com.supervision.exception.BusinessException;
import com.supervision.rasa.constant.RasaConstant;
import com.supervision.rasa.pojo.vo.RasaCmdArgumentVo;
import com.supervision.rasa.service.RasaCmdService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@Tag(name = "rasa管理")
@RestController
@RequestMapping("rasaCmd")
@RequiredArgsConstructor
public class RasaCmdController {
private final RasaCmdService rasaCmdService;
@Operation(summary = "执行训练shell命令")
@PostMapping("/trainExec")
public String trainExec(@RequestBody RasaCmdArgumentVo argument) throws IOException, ExecutionException, InterruptedException, TimeoutException {
return rasaCmdService.trainExec(argument);
}
@Operation(summary = "执行启动shell命令")
@PostMapping("/runExec")
public String runExec(@RequestBody RasaCmdArgumentVo argument) throws ExecutionException, InterruptedException, TimeoutException {
String outString = rasaCmdService.runExec(argument);
if (StrUtil.isEmptyIfStr(outString) || !outString.contains(RasaConstant.RUN_SUCCESS_MESSAGE)){
throw new BusinessException("任务执行异常。详细日志:"+outString);
}
return outString;
}
@Operation(summary = "部署rasa")
@PostMapping("/deploy")
public boolean deployRasa() throws Exception {
return rasaCmdService.deployRasa();
}
}

@ -1,36 +0,0 @@
package com.supervision.rasa.controller;
import com.supervision.exception.BusinessException;
import com.supervision.rasa.service.RasaFileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@Tag(name = "rasa文件保存")
@RestController
@RequestMapping("rasaFile")
@RequiredArgsConstructor
public class RasaFileController {
private final RasaFileService rasaFileService;
@Operation(summary = "接受并保存rasa文件")
@PostMapping("/saveRasaFile")
public String saveRasaFile(@RequestParam("file") MultipartFile file) throws IOException {
if (file == null || file.isEmpty()) {
throw new BusinessException("file is empty");
}
rasaFileService.saveRasaFile(file,"1");
return "success";
}
}

@ -1,30 +0,0 @@
package com.supervision.rasa.controller;
import com.supervision.rasa.service.RasaTalkService;
import com.supervision.vo.rasa.RasaTalkVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "ras对话服务")
@RestController
@RequestMapping("rasa")
@RequiredArgsConstructor
public class RasaTalkController {
private final RasaTalkService rasaTalkService;
@Operation(summary = "rasa对话")
@PostMapping("talkRasa")
public List<String> talkRasa(@RequestBody RasaTalkVo rasaTalkVo){
return rasaTalkService.talkRasa(rasaTalkVo);
}
}

@ -1,38 +0,0 @@
package com.supervision.rasa.controller;
import com.supervision.rasa.pojo.dto.Text2vecDataVo;
import com.supervision.rasa.pojo.dto.Text2vecMatchesReq;
import com.supervision.rasa.pojo.dto.Text2vecMatchesRes;
import com.supervision.rasa.service.Text2vecService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name = "text2vec服务")
@RestController
@RequestMapping("/text2vec")
@RequiredArgsConstructor
public class Text2vecController {
private final Text2vecService text2vecService;
@Operation(summary = "更新数据库")
@PostMapping("updateDataset")
public boolean talkRasa(@RequestBody List<Text2vecDataVo> text2vecDataVoList){
return text2vecService.updateDataset(text2vecDataVoList);
}
@Operation(summary = "获取匹配项")
@PostMapping("matches")
public List<Text2vecMatchesRes> matches(@RequestBody Text2vecMatchesReq text2vecMatchesReq){
return text2vecService.matches(text2vecMatchesReq);
}
}

@ -1,28 +0,0 @@
package com.supervision.rasa.pojo.dto;
import lombok.Data;
import java.util.LinkedHashMap;
import java.util.List;
@Data
public class DomainYmlTemplate {
private List<String> intents;
private LinkedHashMap<String,List<String>> responses;
private List<String> actions;
private SessionConfig session_config = new SessionConfig();
@Data
public static class SessionConfig{
private final int session_expiration_time = 60;
private final Boolean carry_over_slots_to_new_session = true;
}
}

@ -1,28 +0,0 @@
package com.supervision.rasa.pojo.dto;
import lombok.Data;
import java.util.List;
@Data
public class NluYmlTemplate {
private List<Nlu> nlu;
@Data
public static class Nlu{
private String intent;
private List<String> examples;
public Nlu(String intent, List<String> examples) {
this.intent = intent;
this.examples = examples;
}
public Nlu() {
}
}
}

@ -1,20 +0,0 @@
package com.supervision.rasa.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QuestionAnswerDTO {
private List<String> questionList;
private List<String> answerList;
private String desc;
}

@ -1,13 +0,0 @@
package com.supervision.rasa.pojo.dto;
import lombok.Data;
@Data
public class RasaReqDTO {
private String sender;
private String message;
}

@ -1,11 +0,0 @@
package com.supervision.rasa.pojo.dto;
import lombok.Data;
@Data
public class RasaResDTO {
private String recipient_id;
private String text;
}

@ -1,72 +0,0 @@
package com.supervision.rasa.pojo.dto;
import cn.hutool.core.collection.CollUtil;
import lombok.Data;
import java.util.List;
/**
* rasa
*/
@Data
public class RasaRunParam {
/**
* bash
*/
private String bashPath;
/**
* rasa
*/
private String shellPath;
/**
* rasa
*/
private String rasaModelPath;
/**
* rasa
*/
private String endpointsPath;
/**
* rasa
*/
private String port;
/**
* listRasaRunParam
* @param args bashPath = args[0], shellPath = args[1], rasaModelPath = args[2], endpointsPath = args[3], port = args[4]
* @return
*/
public static RasaRunParam build(List<String> args) {
RasaRunParam rasaRunParam = new RasaRunParam();
if (CollUtil.isEmpty(args)){
return rasaRunParam;
}
rasaRunParam.setBashPath(args.get(0));
if (args.size()>1){
rasaRunParam.setShellPath(args.get(1));
}
if (args.size()>2){
rasaRunParam.setRasaModelPath(args.get(2));
}
if (args.size()>3){
rasaRunParam.setEndpointsPath(args.get(3));
}
if (args.size()>4){
rasaRunParam.setPort(args.get(4));
}
return rasaRunParam;
}
public List<String> toList(){
return CollUtil.newArrayList(bashPath,shellPath,rasaModelPath,endpointsPath,port);
}
}

@ -1,86 +0,0 @@
package com.supervision.rasa.pojo.dto;
import cn.hutool.core.collection.CollUtil;
import lombok.Data;
import java.util.List;
/**
* rasa
*/
@Data
public class RasaTrainParam {
/**
* bash
*/
private String bashPath;
/**
* rasa
*/
private String shellPath;
/**
* rasa
*/
private String configPath;
/**
* rasa (rules.yml nlu.yml)
*/
private String localDataPath;
/**
* rasa domain.yml
*/
private String domainPath;
/**
* rasa
*/
private String localModelsPath;
/**
*
*/
private String fixedModelName;
/**
* listRasaTrainParam
* @param args bashPath = args[0] shellPath = args[1] configPath = args[2]
* localDataPath = args[3] domainPath = args[4] localModelsPath = args[5] fixedModelName = args[6]
* @return
*/
public static RasaTrainParam build(List<String> args) {
RasaTrainParam rasaTrainParam = new RasaTrainParam();
if (CollUtil.isEmpty(args)){
return rasaTrainParam;
}
rasaTrainParam.bashPath = args.get(0);
if (args.size() > 1){
rasaTrainParam.shellPath = args.get(1);
}
if (args.size() > 2){
rasaTrainParam.configPath = args.get(2);
}
if (args.size() > 3){
rasaTrainParam.localDataPath = args.get(3);
}
if (args.size() > 4){
rasaTrainParam.domainPath = args.get(4);
}
if (args.size() > 5){
rasaTrainParam.localModelsPath = args.get(5);
}
if (args.size() > 6){
rasaTrainParam.fixedModelName = args.get(6);
}
return rasaTrainParam;
}
public List<String> toList() {
return CollUtil.newArrayList(bashPath, shellPath, configPath, localDataPath, domainPath, localModelsPath, fixedModelName);
}
}

@ -1,44 +0,0 @@
package com.supervision.rasa.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
public class RuleYmlTemplate {
private List<Rule> rules;
@Data
public static class Rule {
private String rule;
private List<Step> steps;
public Rule() {
}
public Rule(String rule, String intent, String action) {
this.rule = rule;
steps = new ArrayList<>();
Step step = new Step(intent, action);
steps.add(step);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Step {
private String intent;
private String action;
}
}

@ -1,23 +0,0 @@
package com.supervision.rasa.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class Text2vecDataVo {
@Schema(description = "数据id")
private String id;
@Schema(description = "问题")
private String question;
public Text2vecDataVo(String id, String question) {
this.id = id;
this.question = question;
}
public Text2vecDataVo() {
}
}

@ -1,27 +0,0 @@
package com.supervision.rasa.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class Text2vecMatchesReq {
@Schema(description = "需要被匹配的语句")
private String querySentence;
@Schema(description = "相似度阈值")
private Double threshold;
public Text2vecMatchesReq() {
}
public Text2vecMatchesReq(String querySentence) {
this.querySentence = querySentence;
}
public Text2vecMatchesReq(String querySentence, Double threshold) {
this.querySentence = querySentence;
this.threshold = threshold;
}
}

@ -1,18 +0,0 @@
package com.supervision.rasa.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class Text2vecMatchesRes {
@Schema(description = "id")
private String id;
@Schema(description = "句子")
private String sentence;
@Schema(description = "相似度")
private String similarity;
}

@ -1,21 +0,0 @@
package com.supervision.rasa.pojo.vo;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import java.util.Date;
@Data
public class RasaCmdArgumentVo {
private String fixedModelName;//fixed-model-name
private String modelId;
public void setFixedModelNameIfAbsent(){
if (StrUtil.isEmpty(fixedModelName)){
fixedModelName = String.valueOf(new Date().getTime()/1000);
}
}
}

@ -1,30 +0,0 @@
package com.supervision.rasa.service;
import com.supervision.rasa.pojo.dto.QuestionAnswerDTO;
import com.supervision.rasa.pojo.vo.RasaCmdArgumentVo;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;
public interface RasaCmdService {
String trainExec(RasaCmdArgumentVo argument) throws IOException, ExecutionException, InterruptedException, TimeoutException;
String runExec( RasaCmdArgumentVo argument) throws ExecutionException, InterruptedException, TimeoutException;
List<String> execCmd(List<String> cmds, Predicate<String> endPredicate, long timeOut) throws InterruptedException, ExecutionException, TimeoutException;
String getShellPath(String shell);
boolean deployRasa() throws Exception;
Map<String, QuestionAnswerDTO> generateRasaYml(String path);
Map<String, QuestionAnswerDTO> getIntentCodeAndIdMap();
}

@ -1,10 +0,0 @@
package com.supervision.rasa.service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public interface RasaFileService {
void saveRasaFile(MultipartFile file,String modelId) throws IOException;
}

@ -1,149 +0,0 @@
package com.supervision.rasa.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.supervision.model.RasaModelInfo;
import com.supervision.rasa.constant.RasaConstant;
import com.supervision.rasa.pojo.dto.RasaRunParam;
import com.supervision.rasa.util.PortUtil;
import com.supervision.service.RasaModeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class RasaModelManager {
@Value("${rasa.models-path}")
private String modelsPath;
private final RasaModeService rasaModeService;
private final RasaCmdService rasaCmdService;
private boolean wakeUpInterruptServerRunning = false;
public void wakeUpInterruptServer(){
// 1. 查找出记录表中存活的服务
List<RasaModelInfo> rasaModelInfos = rasaModeService.listActive();
List<RasaModelInfo> activeRasaList = rasaModelInfos.stream().filter(info -> CollectionUtil.isNotEmpty(info.getRunCmd()) && null != info.getPort()).collect(Collectors.toList());
if (CollectionUtil.isEmpty(activeRasaList)){
log.info("wakeUpInterruptService: no rasa service need wake up ...");
return;
}
// 2. 重新启动中断的服务
for (RasaModelInfo rasaModelInfo : activeRasaList) {
if (PortUtil.portIsActive(rasaModelInfo.getPort())) {
log.info("wakeUpInterruptServer: port:{} is run..", rasaModelInfo.getPort());
continue;
}
try {
RasaRunParam rasaRunParam = RasaRunParam.build(rasaModelInfo.getRunCmd());
rasaRunParam.setPort(String.valueOf(rasaModelInfo.getPort()));
rasaRunParam.setShellPath(rasaCmdService.getShellPath(RasaConstant.RUN_SHELL));
String rasaModelPath = rasaRunParam.getRasaModelPath();
if (StrUtil.isEmpty(rasaModelPath) || !FileUtil.exist(rasaModelPath)) {
log.info("wakeUpInterruptServer: rasa model path {} not exist,attempt find last ...", rasaModelPath);
String modeParentPath = replaceDuplicateSeparator(String.join(File.separator, modelsPath));
String fixedModePath = listLastFilePath(modeParentPath, f -> f.getName().matches("-?\\d+(\\.\\d+)?.tar.gz"));
Assert.notEmpty(fixedModePath, "wakeUpInterruptService: no rasa model in path {} ", modeParentPath);
rasaRunParam.setRasaModelPath(fixedModePath);
}
log.info("wakeUpInterruptServer : use fixedModePath :{}", rasaRunParam.getRasaModelPath());
List<String> outMessageList = rasaCmdService.execCmd(rasaRunParam.toList(),
s -> StrUtil.isNotBlank(s) && s.contains(RasaConstant.RUN_SUCCESS_MESSAGE), 300);
rasaModelInfo.setRunLog(String.join("\r\n", outMessageList));
rasaModelInfo.setRunCmd(rasaRunParam.toList());
rasaModeService.updateById(rasaModelInfo);
if (!runIsSuccess(outMessageList)) {
log.info("wakeUpInterruptServer: restart server port for {} failed,details info : {}", rasaModelInfo.getPort(), String.join("\r\n", outMessageList));
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
log.info("wakeUpInterruptServer: restart server port for {} failed", rasaModelInfo.getPort());
throw new RuntimeException(e);
}
log.info("wakeUpInterruptServer: restart server port for {} success ", rasaModelInfo.getPort());
}
}
//默认每十分钟执行一次
@Scheduled(cron = "${rasa.wakeup.cron:0 */10 * * * ?}")
public void wakeUpInterruptServerScheduled() {
log.info("wakeUpInterruptServerScheduled: Scheduled is run .... wakeUpInterruptServerRunning is :{}", wakeUpInterruptServerRunning);
if (wakeUpInterruptServerRunning) {
return;
}
try {
wakeUpInterruptServerRunning = true;
wakeUpInterruptServer();
} finally {
wakeUpInterruptServerRunning = false;
}
}
private boolean runIsSuccess(List<String> messageList){
return containKey(messageList,RasaConstant.RUN_SUCCESS_MESSAGE);
}
private boolean containKey(List<String> messageList,String keyWord){
if (CollectionUtil.isEmpty(messageList)){
return false;
}
if (StrUtil.isEmpty(keyWord)){
return false;
}
return messageList.stream().anyMatch(s->StrUtil.isNotEmpty(s) && s.contains(keyWord));
}
private String replaceDuplicateSeparator(String path){
if (StrUtil.isEmpty(path)){
return path;
}
return path.replace(File.separator + File.separator, File.separator);
}
private String listLastFilePath(String path, FileFilter filter){
File file = listLastFile(path, filter);
if (null == file){
return null;
}
return file.getPath();
}
private File listLastFile(String path,FileFilter filter){
File file = new File(path);
File[] files = file.listFiles(filter);
if (null == files){
return null;
}
return Arrays.stream(files).max(Comparator.comparing(File::getName)).orElse(null);
}
}

@ -1,11 +0,0 @@
package com.supervision.rasa.service;
import com.supervision.vo.rasa.RasaTalkVo;
import java.util.List;
public interface RasaTalkService {
List<String> talkRasa(RasaTalkVo rasaTalkVo) ;
}

@ -1,34 +0,0 @@
package com.supervision.rasa.service;
import com.supervision.rasa.pojo.dto.QuestionAnswerDTO;
import com.supervision.rasa.pojo.dto.Text2vecDataVo;
import com.supervision.rasa.pojo.dto.Text2vecMatchesReq;
import com.supervision.rasa.pojo.dto.Text2vecMatchesRes;
import java.util.List;
import java.util.Map;
public interface Text2vecService {
/**
*
* @param text2vecDataVoList
* @return
*/
boolean updateDataset(List<Text2vecDataVo> text2vecDataVoList);
boolean updateDataset(Map<String, QuestionAnswerDTO> questionAnswerDTOMap);
/**
*
* @param text2vecMatchesReq
* @return
*/
List<Text2vecMatchesRes> matches(Text2vecMatchesReq text2vecMatchesReq);
/**
*
*/
void initText2vecDataset();
}

@ -1,112 +0,0 @@
package com.supervision.rasa.service;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.supervision.rasa.pojo.dto.QuestionAnswerDTO;
import com.supervision.rasa.pojo.dto.Text2vecDataVo;
import com.supervision.rasa.pojo.dto.Text2vecMatchesReq;
import com.supervision.rasa.pojo.dto.Text2vecMatchesRes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@Service
public class Text2vecServiceImpl implements Text2vecService {
@Value("${text2vec.service.domain}")
private String TEXT2VEC_SERVICE_DOMAIN;
private final String UPDATE_DATASET_PATH = "update_dataset";
private final String MATCHES_PATH = "matches";
private final String GET_ALL_SIMILARITIES_PATH = "get_all_similarities";
private final RasaCmdService rasaCmdService;
public Text2vecServiceImpl(@Autowired @Lazy RasaCmdService rasaCmdService) {
this.rasaCmdService = rasaCmdService;
}
@Override
public boolean updateDataset(List<Text2vecDataVo> text2vecDataVoList) {
Assert.notEmpty(text2vecDataVoList, "数据不能为空");
text2vecDataVoList.forEach(vo->{
Assert.notEmpty(vo.getId(), "id不能为空");
Assert.notEmpty(vo.getQuestion(), "question不能为空");
});
String url = TEXT2VEC_SERVICE_DOMAIN + UPDATE_DATASET_PATH;
log.info("updateDataset: url is : {}",url);
TimeInterval timer = DateUtil.timer();
String body = HttpUtil.post(url, JSONUtil.toJsonStr(text2vecDataVoList));
log.info("updateDataset: res is :{},耗时:{}s",body,timer.intervalSecond());
return "success".equals(JSONUtil.parseObj(body).get("status"));
}
@Override
public boolean updateDataset(Map<String, QuestionAnswerDTO> questionAnswerDTOMap) {
if (CollUtil.isEmpty(questionAnswerDTOMap)){
log.info("updateDataset: questionAnswerDTOMap is empty");
return false;
}
// 更新text2vec数据信息
List<Text2vecDataVo> text2vecDataVoList = questionAnswerDTOMap.entrySet().stream()
.filter(entry -> Objects.nonNull(entry.getValue())
&& CollUtil.isNotEmpty(entry.getValue().getQuestionList())
&& CollUtil.isNotEmpty(entry.getValue().getAnswerList()))
.flatMap(entry -> entry.getValue().getQuestionList().stream()
.map(question -> new Text2vecDataVo(entry.getValue().getAnswerList().get(0), question))).collect(Collectors.toList());
if (CollUtil.isEmpty(text2vecDataVoList)){
log.info("updateDataset: text2vecDataVoList is empty");
return false;
}
return updateDataset(text2vecDataVoList);
}
@Override
public List<Text2vecMatchesRes> matches(Text2vecMatchesReq text2vecMatchesReq) {
Assert.notEmpty(text2vecMatchesReq.getQuerySentence(), "querySentence不能为空");
String path = Objects.nonNull(text2vecMatchesReq.getThreshold()) ? MATCHES_PATH : GET_ALL_SIMILARITIES_PATH;
String url = TEXT2VEC_SERVICE_DOMAIN + path;
log.info("matches: url is : {},req:{}",url,JSONUtil.toJsonStr(text2vecMatchesReq));
String body = HttpUtil.post(url, JSONUtil.toJsonStr(text2vecMatchesReq));
log.info("matches: res is :{}",body);
JSONObject jsonBody = JSONUtil.parseObj(body);
Assert.isTrue("success".equals(jsonBody.get("status")),"查询失败");
return JSONUtil.toList(JSONUtil.parseArray(jsonBody.get("results")), Text2vecMatchesRes.class);
}
public void initText2vecDataset(){
log.info("initText2vecDataset ...");
if (FileUtil.exist("/usr/local/text2vec/question.json")){
log.info("question.json文件已经存在不进行text2vec数据初始化操作....");
return;
}
// 更新text2vec数据信息
Map<String, QuestionAnswerDTO> intentCodeAndIdMap = rasaCmdService.getIntentCodeAndIdMap();
this.updateDataset(intentCodeAndIdMap);
}
}

@ -1,486 +0,0 @@
package com.supervision.rasa.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.exception.BusinessException;
import com.supervision.model.AskTemplateQuestionLibrary;
import com.supervision.model.ConfigAncillaryItem;
import com.supervision.model.ConfigPhysicalTool;
import com.supervision.model.RasaModelInfo;
import com.supervision.rasa.config.ThreadPoolExecutorConfig;
import com.supervision.rasa.constant.RasaConstant;
import com.supervision.rasa.pojo.dto.*;
import com.supervision.rasa.pojo.vo.RasaCmdArgumentVo;
import com.supervision.rasa.service.RasaCmdService;
import com.supervision.rasa.service.Text2vecService;
import com.supervision.rasa.util.PortUtil;
import com.supervision.service.AskTemplateQuestionLibraryService;
import com.supervision.service.ConfigAncillaryItemService;
import com.supervision.service.ConfigPhysicalToolService;
import com.supervision.service.RasaModeService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class RasaCmdServiceImpl implements RasaCmdService {
@Value("${rasa.models-path}")
private String modelsPath;
@Value("${rasa.endpoints}")
private String endpoints;
@Value("${rasa.config}")
private String config;
@Value("${rasa.data-path}")
private String dataPath;
@Value("${rasa.shell-env:/bin/bash}")
private String shellEnv;
@Value("${rasa.data-path:/home/rasa/model_resource/}")
private String rasaFilePath;
private final RasaModeService rasaModeService;
private final ConfigPhysicalToolService configPhysicalToolService;
private final ConfigAncillaryItemService configAncillaryItemService;
private final AskTemplateQuestionLibraryService askTemplateQuestionLibraryService;
private final Text2vecService text2vecService;
private final ConcurrentHashMap<String,String> shellPathCache = new ConcurrentHashMap<>();
@Override
@Transactional
public String trainExec(RasaCmdArgumentVo argument) throws ExecutionException, InterruptedException, TimeoutException {
log.info("trainExec:start train rasa model ....argument:{}", JSONUtil.toJsonStr(argument));
argument.setFixedModelNameIfAbsent();
// /rasa/v3_jiazhuangxian/domain.yml domain的路径应该是从zip文件中加压出来的文件的路径后面拼上/domain.yml
String domain = replaceDuplicateSeparator(String.join(File.separator,dataPath,"domain.yml"));
// /rasa/v3_jiazhuangxian/ yml文件的路径应该是从zip文件中加压出来的文件的路径,在配置文件中配置
String localDataPath = replaceDuplicateSeparator(String.join(File.separator,dataPath));
// /rasa/models 生成出来的模型的存放路径,也写在配置文件里面
String localModelsPath = replaceDuplicateSeparator(String.join(File.separator,modelsPath));
List<String> cmds = ListUtil.toList(shellEnv, getShellPath(RasaConstant.TRAIN_SHELL),config,localDataPath,domain,localModelsPath);
cmds.add(argument.getFixedModelName());
log.info("trainExec cmd : {}",StrUtil.join(" ",cmds));
List<String> outMessage = execCmd(cmds, s -> StrUtil.isNotBlank(s) && s.contains(RasaConstant.TRAN_SUCCESS_MESSAGE), 300);
String outMessageString = String.join("\r\n", outMessage);
//保存 模型信息
RasaModelInfo rasaModelInfo = new RasaModelInfo();
rasaModelInfo.setModelId(argument.getModelId());
rasaModelInfo.setTranStatus(trainIsSuccess(outMessage)?1:0);
rasaModelInfo.setServerStatus(-1);
cmds.set(1,null);
rasaModelInfo.setTrainCmd(cmds);
rasaModelInfo.setTrainLog(outMessageString);
rasaModelInfo.setModelId("1");
rasaModeService.saveOrUpdateByModelId(rasaModelInfo);
log.info("trainExec:end train rasa model ....");
return outMessageString;
}
@Override
public String runExec(RasaCmdArgumentVo argument) throws ExecutionException, InterruptedException, TimeoutException {
log.info("runExec:start runExec rasa model ....args:{}",JSONUtil.toJsonStr(argument));
// 1. 查找可用端口
int port = PortUtil.findUnusedPort(5050, 100000,rasaModeService.listActivePort());
log.info("runExec findUnusedPort is : {}",port);
// 2. 运行模型
// 2.1 -m 参数对应的值 /rasa/models/aaa1111.tar.gz 指run的模型的路径/rasa/models应该来自于配置文件和训练时的--out是同一配置项
// aaa1111.tar.gz这个前面的文件名应该是--fixed-model-name指定的.tar.gz是文件后缀代码拼接
String fixedModePath;
String modeParentPath = replaceDuplicateSeparator(String.join(File.separator, modelsPath));
if (StrUtil.isEmpty(argument.getFixedModelName())){
fixedModePath = listLastFilePath(modeParentPath, f -> f.getName().matches("-?\\d+(\\.\\d+)?.tar.gz"));
}else {
String fixedModelName = argument.getFixedModelName()+".tar.gz";
fixedModePath = String.join(modeParentPath,fixedModelName);
}
List<String> cmds = ListUtil.toList(shellEnv, getShellPath(RasaConstant.RUN_SHELL),fixedModePath,endpoints,String.valueOf(port));
log.info("runExec cmd : {}",StrUtil.join(" ",cmds));
List<String> outMessageList = execCmd(cmds, s -> StrUtil.isNotBlank(s) && s.contains(RasaConstant.RUN_SUCCESS_MESSAGE), 300);
String outMessageString = String.join("\r\n", outMessageList);
// 3. 尝试停止原先的程序
boolean runIsSuccess = runIsSuccess(outMessageList);
RasaModelInfo dbRasaModelInfo = rasaModeService.queryByModelId(argument.getModelId());
if (null != dbRasaModelInfo.getPort() && !dbRasaModelInfo.getPort().equals(port) && runIsSuccess){
log.info("runExec server is up and dbRasaModelInfo is: {}, start kill old server ....",dbRasaModelInfo.getPort());
// 3.1 如果原本的程序已经运行且本次成功启动,杀掉原本的进程
execCmd(ListUtil.toList(shellEnv, getShellPath(RasaConstant.KILL_SHELL), String.valueOf(dbRasaModelInfo.getPort())), s -> false, 20);
}
if (null != dbRasaModelInfo.getPort() && !runIsSuccess){
// 3.2 如果原本的程序已经运行,但本次程序未正常启动,不对端口号进行变动
log.info("runExec server start fail and dbRasaModelInfo is: {}, user old server ....",dbRasaModelInfo.getPort());
port = dbRasaModelInfo.getPort();
}
// 4. 更新模型信息
RasaModelInfo rasaModelInfo = new RasaModelInfo();
rasaModelInfo.setModelId(argument.getModelId());
rasaModelInfo.setPort(port);
rasaModelInfo.setServerStatus( runIsSuccess ? 1 : 0 );
rasaModelInfo.setRunCmd(ListUtil.toList(shellEnv, null,fixedModePath,endpoints));
rasaModelInfo.setRunLog(outMessageString);
rasaModeService.saveOrUpdateByModelId(rasaModelInfo);
log.info("runExec:runExec end ....");
return outMessageString;
}
public List<String> execCmd(List<String> cmds, Predicate<String> endPredicate, long timeOut) throws InterruptedException, ExecutionException, TimeoutException {
ProcessBuilder processBuilder = new ProcessBuilder(cmds);
processBuilder.redirectErrorStream(true);
ThreadPoolExecutor instance = ThreadPoolExecutorConfig.getInstance();
Future<List<String>> future = instance.submit(() -> {
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
Reader reader = new InputStreamReader(inputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(reader);
List<String> outString = new ArrayList<>();
String resultLines = bufferedReader.readLine();
while( resultLines != null) {
resultLines = bufferedReader.readLine();
log.info("resultLines:{}",resultLines);
outString.add(resultLines);
if (endPredicate.test(resultLines)){
break;
}
}
bufferedReader.close();
return outString;
});
return future.get(timeOut, TimeUnit.SECONDS);
}
@Override
public boolean deployRasa() throws Exception {
// 1.生成rasa模型语料文件
Map<String, QuestionAnswerDTO> questionAnswerDTOMap = generateRasaYml(String.join(File.separator, rasaFilePath));
// 2.训练模型
//删除目录下的旧的训练文件,防止有缓存
List<File> modelsFiles = FileUtil.loopFiles(replaceDuplicateSeparator(String.join(File.separator, modelsPath)));
for (File modelsFile : modelsFiles) {
log.info("deployRasa: delete filename:{}",modelsFile.getName());
FileUtil.del(modelsFile);
}
trainExec(new RasaCmdArgumentVo());
//3.运行模型
RasaCmdArgumentVo rasaCmdArgumentVo = new RasaCmdArgumentVo();
rasaCmdArgumentVo.setModelId("1");
runExec(rasaCmdArgumentVo);
// 更新text2vec数据信息
text2vecService.updateDataset(questionAnswerDTOMap);
return true;
}
@Override
public Map<String, QuestionAnswerDTO> generateRasaYml(String path) {
log.info("generateRasaYml:start generateRasaYml ....");
// 默认问答MAP
List<RuleYmlTemplate.Rule> ruleList = new ArrayList<>();
Map<String, File> ymalFileMap = new HashMap<>();
Map<String, QuestionAnswerDTO> intentCodeAndIdMap = getIntentCodeAndIdMap();
// 开始生成各种yaml文件
Pair<String, File> nulFilePair = generateNlu(intentCodeAndIdMap);
ymalFileMap.put(nulFilePair.getKey(),nulFilePair.getValue());
Pair<String, File> domainFilePair = generateDomain(intentCodeAndIdMap, ruleList);
ymalFileMap.put(domainFilePair.getKey(),domainFilePair.getValue());
Pair<String, File> ruleFilePair = generateRule(ruleList);
ymalFileMap.put(ruleFilePair.getKey(),ruleFilePair.getValue());
// 把文件复制到指定位置
for (Map.Entry<String, File> fileEntry : ymalFileMap.entrySet()) {
try {
FileUtil.copy(fileEntry.getValue(), new File(StrUtil.join(File.separator, path,fileEntry.getKey())), true);
}finally {
FileUtil.del(fileEntry.getValue());
}
}
log.info("generateRasaYml:end generateRasaYml ....");
return intentCodeAndIdMap;
}
public String getShellPath(String shell){
if (StrUtil.isEmpty(shell)){
throw new BusinessException("shell 不能为空...");
}
// 1. 先从缓存中获取shell脚本路径
String shellPath = "shellScript/" + shell;
String cachePath = shellPathCache.get(shell);
if (StrUtil.isNotEmpty(cachePath)){
if (new File(cachePath).exists()){
return cachePath;
}else {
shellPathCache.remove(shell);
}
}
// 2. 如果缓存中不存在shell脚本路径从resources目录下加载
ClassPathResource shellScript = new ClassPathResource(shellPath);
try {
// 2.1 加载文件,写入临时目录中
InputStream inputStream = shellScript.getInputStream();
File tempFile = File.createTempFile(shell, ".sh");
tempFile.deleteOnExit();
FileUtil.writeFromStream(inputStream, tempFile);
// 2.2 给文件赋可执行权限
ProcessBuilder chmod = new ProcessBuilder("chmod", "+x", shellPath);
Process chmodProcess = chmod.start();
chmodProcess.waitFor();
// 2.3 把文件路径放到缓存信息中
shellPathCache.put(shell,tempFile.getAbsolutePath());
return tempFile.getAbsolutePath();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
private Pair<String, File> generateNlu(Map<String, QuestionAnswerDTO> intentCodeAndIdMap) {
// 首先生成根据意图查找到nlu文件
List<NluYmlTemplate.Nlu> nluList = intentCodeAndIdMap.entrySet()
.stream().map(entry ->
new NluYmlTemplate.Nlu(entry.getKey(), entry.getValue().getQuestionList()))
.collect(Collectors.toList());
NluYmlTemplate nluYmlTemplate = new NluYmlTemplate();
nluYmlTemplate.setNlu(nluList);
// 生成后生成yml文件
return createYmlFile(NluYmlTemplate.class, "nlu.ftl", nluYmlTemplate, "nlu.yml");
}
public Map<String, QuestionAnswerDTO> getIntentCodeAndIdMap() {
Map<String, QuestionAnswerDTO> intentCodeAndIdMap = new HashMap<>();
// 默认意图
List<AskTemplateQuestionLibrary> askTemplateQuestionLibraryList = askTemplateQuestionLibraryService.lambdaQuery().list();
// 生成默认意图的nlu
for (AskTemplateQuestionLibrary questionLibrary : askTemplateQuestionLibraryList) {
if (CollUtil.isEmpty(questionLibrary.getQuestion())){
log.warn("getIntentCodeAndIdMap: questionId:{},description:{},questionLibrary.getQuestion() is empty", questionLibrary.getId(), questionLibrary.getDescription());
continue;
}
// 开始生成
// 拼接格式:code_id(防止重复)
String intentCode = questionLibrary.getCode() + "_" + questionLibrary.getId();
intentCodeAndIdMap.put(intentCode, new QuestionAnswerDTO(questionLibrary.getQuestion(), CollUtil.newArrayList( questionLibrary.getId()), questionLibrary.getDescription()));
}
// 这里处理呼出的问题(code和问题不能为空)
List<ConfigPhysicalTool> physicalToolList = configPhysicalToolService.lambdaQuery()
.isNotNull(ConfigPhysicalTool::getCode)
.isNotNull(ConfigPhysicalTool::getCallOutQuestion).list();
for (ConfigPhysicalTool tool : physicalToolList) {
if (CollUtil.isEmpty(tool.getCallOutQuestion())){
log.warn("getIntentCodeAndIdMap: toolId:{},toolName:{},tool.getCallOutQuestion() is empty", tool.getId(), tool.getToolName());
continue;
}
// 把呼出的问题全部加进去
String toolIntent = "tool_" + tool.getCode();
// answer格式为:---tool---工具ID
intentCodeAndIdMap.put(toolIntent,
new QuestionAnswerDTO(tool.getCallOutQuestion(),
CollUtil.newArrayList("tool_" + tool.getId()), "tool-" + tool.getToolName()));
}
// 生成呼出的辅助检查
List<ConfigAncillaryItem> ancillaryItemList = configAncillaryItemService.lambdaQuery()
.isNotNull(ConfigAncillaryItem::getCode)
.isNotNull(ConfigAncillaryItem::getCallOutQuestion).list();
for (ConfigAncillaryItem ancillary : ancillaryItemList) {
if (CollUtil.isEmpty(ancillary.getCallOutQuestion())){
log.warn("getIntentCodeAndIdMap: ancillaryId:{},itemName:{},ancillary.getCallOutQuestion() is empty", ancillary.getId(), ancillary.getItemName());
continue;
}
// 把辅助问诊的问题全部加进去
String itemIntent = "ancillary_" + ancillary.getCode();
// answer格式为:---ancillary---工具ID
intentCodeAndIdMap.put(itemIntent,
new QuestionAnswerDTO(ancillary.getCallOutQuestion(),
CollUtil.newArrayList("ancillary_" + ancillary.getId()), "呼出-ancillary-" + ancillary.getItemName()));
}
return intentCodeAndIdMap;
}
public Pair<String, File> generateDomain(Map<String, QuestionAnswerDTO> questionCodeAndIdMap, List<RuleYmlTemplate.Rule> ruleList) {
LinkedHashMap<String, List<String>> responses = new LinkedHashMap<>();
for (Map.Entry<String, QuestionAnswerDTO> entry : questionCodeAndIdMap.entrySet()) {
String intentCode = entry.getKey();
QuestionAnswerDTO value = entry.getValue();
String utter = "utter_" + intentCode;
responses.put(utter, CollUtil.newArrayList(value.getAnswerList()));
ruleList.add(new RuleYmlTemplate.Rule(value.getDesc(), intentCode, utter));
}
DomainYmlTemplate domainYmlTemplate = new DomainYmlTemplate();
// 意图
List<String> intentList = new ArrayList<>(questionCodeAndIdMap.keySet());
domainYmlTemplate.setIntents(intentList);
// 回复
domainYmlTemplate.setResponses(responses);
// action
List<String> actionList = new ArrayList<>(responses.keySet());
domainYmlTemplate.setActions(actionList);
// 生成yml文件
return createYmlFile(DomainYmlTemplate.class, "domain.ftl", domainYmlTemplate, "domain.yml");
}
/**
* rule
*/
public Pair<String, File> generateRule(List<RuleYmlTemplate.Rule> ruleList) {
RuleYmlTemplate ruleYmlTemplate = new RuleYmlTemplate();
ruleYmlTemplate.setRules(ruleList);
// 生成yml文件
return createYmlFile(RuleYmlTemplate.class, "rules.ftl", ruleYmlTemplate, "rules.yml");
}
private Pair<String,File> createYmlFile(Class<?> clazz, String ftlName, Object data, String ymlName) {
try {
// 这个版本和maven依赖的版本一致
Configuration configuration = new Configuration(Configuration.VERSION_2_3_31);
configuration.setClassForTemplateLoading(clazz, "/templates"); // 模板文件的所在目录
// 获取模板
Template template = configuration.getTemplate(ftlName);
File tempFile = FileUtil.createTempFile(".yml", true);
// 创建输出文件
try (PrintWriter out = new PrintWriter(tempFile);) {
// 填充并生成输出
template.process(data, out);
} catch (Exception e) {
log.error("文件生成失败");
}
return Pair.of(ymlName,tempFile);
} catch (Exception e) {
log.error("导出模板失败", e);
throw new RuntimeException("文件生成失败", e);
}
}
private boolean trainIsSuccess(List<String> messageList){
return containKey(messageList,RasaConstant.TRAN_SUCCESS_MESSAGE);
}
private boolean runIsSuccess(List<String> messageList){
return containKey(messageList,RasaConstant.RUN_SUCCESS_MESSAGE);
}
private boolean containKey(List<String> messageList,String keyWord){
if (CollectionUtil.isEmpty(messageList)){
return false;
}
if (StrUtil.isEmpty(keyWord)){
return false;
}
return messageList.stream().anyMatch(s->StrUtil.isNotEmpty(s) && s.contains(keyWord));
}
private String replaceDuplicateSeparator(String path){
if (StrUtil.isEmpty(path)){
return path;
}
return path.replace(File.separator + File.separator, File.separator);
}
private String listLastFilePath(String path, FileFilter filter){
File file = listLastFile(path, filter);
if (null == file){
return null;
}
return file.getPath();
}
private File listLastFile(String path,FileFilter filter){
File file = new File(path);
File[] files = file.listFiles(filter);
if (null == files){
return null;
}
return Arrays.stream(files).max(Comparator.comparing(File::getName)).orElse(null);
}
}

@ -1,69 +0,0 @@
package com.supervision.rasa.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.supervision.rasa.service.RasaFileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
@Service
@Slf4j
@RequiredArgsConstructor
public class RasaFileServiceImpl implements RasaFileService {
@Value("${rasa.data-path:/home/rasa/model_resource/}")
private String rasaFilePath;
@Value("${rasa.file-name:rasa.zip}")
private String rasaFileName;
@Override
public void saveRasaFile(MultipartFile file,String modelId) throws IOException {
String suffix = "_back";
String rasaFullPath = String.join(File.separator, rasaFilePath,modelId, rasaFileName);
String rasaBackFullPath = rasaFullPath + suffix;
//初始化目录
File dir = new File(String.join(File.separator, rasaFilePath,modelId));
if (!dir.exists()){
FileUtil.mkdir(dir);
}
//1.检查路径下是否存在文件
File oldFile = new File(rasaFullPath);
if (oldFile.exists()){
//1.1 如果存在文件,先备份文件
FileUtil.rename(oldFile,rasaBackFullPath,true);
}
try {
//2.把流文件保存到本地
file.transferTo(new File(rasaFullPath));
//3.解压文件
ZipUtil.unzip(rasaFullPath,String.join(File.separator, rasaFilePath,modelId));
//4.删除备份文件
FileUtil.del(rasaBackFullPath);
} catch (IOException e) {
// 恢复文件
File backFile = new File(rasaBackFullPath);
if (backFile.exists()){ //恢复文件
FileUtil.rename(backFile,rasaFileName,true);
}
throw new IOException(e);
}
}
}

@ -1,65 +0,0 @@
package com.supervision.rasa.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.supervision.model.RasaModelInfo;
import com.supervision.rasa.pojo.dto.RasaReqDTO;
import com.supervision.rasa.pojo.dto.RasaResDTO;
import com.supervision.rasa.pojo.dto.Text2vecMatchesReq;
import com.supervision.rasa.pojo.dto.Text2vecMatchesRes;
import com.supervision.rasa.service.Text2vecService;
import com.supervision.vo.rasa.RasaTalkVo;
import com.supervision.rasa.service.RasaTalkService;
import com.supervision.service.RasaModeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class RasaTalkServiceImpl implements RasaTalkService {
@Value("${rasa.url}")
private String rasaUrl;
private final RasaModeService rasaModeService;
private final Text2vecService text2vecService;
@Override
public List<String> talkRasa(RasaTalkVo rasaTalkVo) {
RasaModelInfo rasaModelInfo = rasaModeService.queryByModelId("1");
RasaReqDTO rasaReqDTO = new RasaReqDTO();
rasaReqDTO.setSender(rasaTalkVo.getSessionId());
rasaReqDTO.setMessage(rasaTalkVo.getQuestion());
String rasaUrl = getRasaUrl(rasaModelInfo.getPort());
log.info("talkRasa: url is: {}",rasaUrl);
rasaReqDTO.setSender(UUID.randomUUID().toString());
String post = HttpUtil.post(rasaUrl, JSONUtil.toJsonStr(rasaReqDTO));
List<RasaResDTO> list = JSONUtil.toList(post, RasaResDTO.class);
log.info("talkRasa: rasa talk result is: {}",JSONUtil.toJsonStr(list));
if (CollUtil.isNotEmpty(list)){
return list.stream().map(RasaResDTO::getText).collect(Collectors.toList());
}
log.info("talkRasa: rasa talk result is empty , redirect for text2vecService ...");
return text2vecService.matches(new Text2vecMatchesReq(rasaTalkVo.getQuestion()))
.stream().map(Text2vecMatchesRes::getId).collect(Collectors.toList());
}
private String getRasaUrl(int port){
return StrUtil.format(rasaUrl, port);
}
}

@ -1,42 +0,0 @@
package com.supervision.rasa.util;
import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.Socket;
import java.util.List;
@Slf4j
public class PortUtil {
public static boolean portIsActive(int port){
try {
Socket socket = new Socket("localhost", port);
socket.close();
return true;
} catch (IOException e) {
log.info("portIsActive: port:{} connect error",port);
}
return false;
}
public static int findUnusedPort(int minPort, int maxPort, List<Integer> excludePorts){
if (maxPort < minPort){
return -1;
}
for (int port = minPort; port < maxPort; port++) {
if (CollectionUtil.isNotEmpty(excludePorts)&& excludePorts.contains(port)){
continue;
}
if (!portIsActive(port)){
return port;
}
}
return -1;
}
}

@ -1,66 +0,0 @@
server:
port: 8890
servlet:
context-path: /virtual-patient-rasa
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
rasa:
data-path: /data/vp/rasa/model_resource/ # 文件解压后存放位置
models-path: /data/vp/rasa/models/
endpoints: /rasa/endpoints.yml # 启动的配置项,应该是写在配置文件里面
config: /rasa/config.yml # 启动rasa需要的配置文件在配置文件中配置
url: 127.0.0.1:{}/webhooks/rest/webhook
wakeup:
cron: 0 */10 * * * ? #每十分钟执行一次
text2vec:
service:
domain: http://127.0.0.1:5000/
spring:
application:
name: virtual-patient
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
##数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://virtual-patient-mysql:3306/virtual_patient?useUnicode=true&characterEncoding=utf-8&useSSL=true&nullCatalogMeansCurrent=true&serverTimezone=GMT%2B8
username: root
password: '123456'
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: false # 是否开启 StatViewServlet
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

@ -1,46 +0,0 @@
server:
port: 8890
servlet:
context-path: /virtual-patient-rasa
undertow:
# HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
max-http-post-size: -1
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
##数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件stat-监控统计log4j-日志wall-防火墙防止SQL注入去掉后监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效默认true开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效默认false开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效默认false建议开启不影响性能
stat-view-servlet:
enabled: false # 是否开启 StatViewServlet
filter:
stat:
enabled: true # 是否开启 FilterStat默认true
log-slow-sql: true # 是否开启 慢SQL 记录默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000单位毫秒
merge-sql: false # 合并多个连接池的监控数据默认false
mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

@ -1,10 +0,0 @@
spring:
cloud:
nacos:
config:
server-addr: 192.168.10.137:8848
file-extension: yml
namespace: b9eea377-79ec-4ba5-9cc2-354f7bd5181e
discovery:
server-addr: 192.168.10.137:8848
namespace: b9eea377-79ec-4ba5-9cc2-354f7bd5181e

@ -1,10 +0,0 @@
spring:
cloud:
nacos:
config:
server-addr: 192.168.10.137:8848
file-extension: yml
namespace: 88e1f674-1fbc-4021-9ff1-60b94ee13ef0
discovery:
server-addr: 192.168.10.137:8848
namespace: 88e1f674-1fbc-4021-9ff1-60b94ee13ef0

@ -1,5 +0,0 @@
spring:
profiles:
active: test
application:
name: virtual-patient-rasa

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<logger name="org.springframework.web" level="INFO"/>
<!-- 开发环境 -->
<springProfile name="local">
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="INFO"/>
<logger name="com.supervision" level="DEBUG"/>
<logger name="org.springframework.scheduling" level="INFO"/>
</springProfile>
<!-- 测试环境,生产环境 -->
<springProfile name="dev,test,prod">
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springboot.sample" level="INFO"/>
<logger name="com.supervision" level="INFO"/>
<logger name="org.springframework.scheduling" level="INFO"/>
<root level="INFO">
<appender name="DAILY_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 服务器中当天的日志 -->
<file>/data/vp/log/virtual-patient-rasa.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 服务器归档日志 -->
<fileNamePattern>/data/vp/log/history/virtual-patient-rasa-%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
</root>
</springProfile>
</configuration>

@ -1,14 +0,0 @@
!/usr/bin/env bash
PORT=$1
KPID=$(lsof -t -i:$PORT)
if [ -n "$KPID" ]; then
echo "PORT ===>> $PORT map PID is not empty. pid is $KPID "
echo "cmd is kill -9 $KPID "
kill -9 $KPID
else
echo "PORT ===>> $PORT map PID is empty."
fi

@ -1,16 +0,0 @@
#!/usr/bin/env bash
source /root/anaconda3/etc/profile.d/conda.sh
conda activate rasa3
MODELS_PATH=$1
ENDPOINTS=$2
PORT=$3
echo "shell cmd is rasa run -m $MODELS_PATH --enable-api --cors "*" --debug --endpoints $ENDPOINTS --port $PORT "
rasa run -m $MODELS_PATH --enable-api --cors "*" --debug --endpoints $ENDPOINTS --port $PORT
echo 'start success ...'

@ -1,21 +0,0 @@
#!/usr/bin/env bash
source /root/anaconda3/etc/profile.d/conda.sh
conda activate rasa3
CONFIG=$1
DATA=$2
DOMAIN=$3
OUT=$4
FIXED_MODEL_NAME=$5
echo "tran shell is run..."
echo "cmd is rasa train --config $CONFIG --data $DATA --domain $DOMAIN --out $OUT --fixed-model-name $FIXED_MODEL_NAME"
rasa train --config $CONFIG --data $DATA --domain $DOMAIN --out $OUT --fixed-model-name $FIXED_MODEL_NAME
echo 'train done'

@ -1,28 +0,0 @@
recipe: default.v1
language: zh
pipeline:
- name: JiebaTokenizer
- name: LanguageModelFeaturizer
model_name: bert
model_weights: bert-base-chinese
- name: RegexFeaturizer
- name: DIETClassifier
epochs: 100
learning_rate: 0.001
tensorboard_log_directory: ./log
- name: ResponseSelector
epochs: 100
learning_rate: 0.001
- name: FallbackClassifier
threshold: 0.4
ambiguity_threshold: 0.1
- name: EntitySynonymMapper
policies:
- name: MemoizationPolicy
- name: TEDPolicy
- name: RulePolicy
core_fallback_threshold: 0.4
core_fallback_action_name: "action_default_fallback"
enable_fallback_prediction: True

@ -1,23 +0,0 @@
version: "3.1"
intents:
<#list intents as intent>
- ${intent}
</#list>
responses:
<#list responses?keys as response>
${response}:
<#list responses[response] as item>
- text: "${item}"
</#list>
</#list>
actions:
<#list actions as action>
- ${action}
</#list>
session_config:
session_expiration_time: 60
carry_over_slots_to_new_session: true

@ -1,10 +0,0 @@
version: "3.1"
nlu:
<#list nlu as item>
- intent: ${item.intent}
examples: |
<#list item.examples as example>
- ${example}
</#list>
</#list>

@ -1,12 +0,0 @@
version: "3.1"
rules:
<#list rules as item>
- rule: ${item.rule}
steps:
<#list item.steps as ss>
- intent: ${ss.intent}
- action: ${ss.action}
</#list>
</#list>

@ -1,47 +0,0 @@
package com.supervision.rasa;
import com.supervision.rasa.pojo.dto.QuestionAnswerDTO;
import com.supervision.rasa.pojo.dto.Text2vecDataVo;
import com.supervision.rasa.service.RasaCmdService;
import com.supervision.rasa.service.Text2vecService;
import com.supervision.util.RedisSequenceUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@SpringBootTest
class VirtualPatientRasaApplicationTests {
@Autowired
private RasaCmdService rasaCmdService;
@Autowired
private Text2vecService text2vecService;
@Test
void contextLoads() {
/*Map<String, QuestionAnswerDTO> questionAnswerDTOMap = rasaCmdService.generateRasaYml("F:\\tmp\\rasa");
System.out.println(questionAnswerDTOMap);*/
/* Map<String, QuestionAnswerDTO> questionAnswerDTOMap = rasaCmdService.generateRasaYml(String.join(File.separator, "F:\\tmp\\rasa"));
List<Text2vecDataVo> text2vecDataVoList = questionAnswerDTOMap.entrySet().stream()
.flatMap(entry -> entry.getValue().getQuestionList().stream()
.map(question -> new Text2vecDataVo(entry.getKey(), question))).collect(Collectors.toList());
text2vecService.updateDataset(text2vecDataVoList);*/
String complexDiseaseNo = RedisSequenceUtil.getComplexDiseaseNo();
String processNo = RedisSequenceUtil.getProcessNo();
String questionLibraryCode = RedisSequenceUtil.getQuestionLibraryCode(()->0L);
String questionLibraryCode1 = RedisSequenceUtil.getQuestionLibraryDefaultAnswerCode(() -> 0L);
System.out.println("complexDiseaseNo"+complexDiseaseNo+" processNo"+processNo+" questionLibraryCode"+questionLibraryCode+" questionLibraryCode1"+questionLibraryCode1);
}
}
Loading…
Cancel
Save