upgrade milvus to v2.0

This commit is contained in:
Calvin 2022-02-13 17:07:49 +08:00
parent 71410281b9
commit 4dd8f3fdc4
21 changed files with 836 additions and 875 deletions

View File

@ -91,54 +91,30 @@ java -jar video-search-0.1.0.jar
```
## 3. 后端向量引擎部署(docker
## 3. 后端向量引擎部署(Milvus 2.0
#### 3.1 环境要求:
- 需要安装docker运行环境Mac环境可以使用Docker Desktop
#### 3.2 拉取Milvus向量引擎镜像用于计算特征值向量相似度
[安装文档](https://github.com/milvus-io/docs/blob/master/v0.10.0/site/zh-CN/quick_start/install_milvus/cpu_milvus_docker.md)
##### 最新版本请参考官网
- Milvus向量引擎参考链接
[Milvus向量引擎官网](https://milvus.io/cn/docs/overview.md)
[Milvus向量引擎Github](https://github.com/milvus-io)
下载 milvus-standalone-docker-compose.yml 配置文件并保存为 docker-compose.yml
[单机版安装文档](https://milvus.io/docs/v2.0.0/install_standalone-docker.md)
```bash
sudo docker pull milvusdb/milvus:0.10.0-cpu-d061620-5f3c00
wget https://github.com/milvus-io/milvus/releases/download/v2.0.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
```
#### 3.3 下载配置文件
[vector_engine.zip](https://aias-home.oss-cn-beijing.aliyuncs.com/AIAS/image_search/vector_engine.zip)
#### 3.4 启动 Docker 容器
/Users/calvin/vector_engine为主机路径根据需要修改。conf下为引擎所需的配置文件。
#### 3.3 启动 Docker 容器
```bash
docker run -d --name milvus_cpu_0.10.0 \
-p 19530:19530 \
-p 19121:19121 \
-p 9091:9091 \
-v /Users/calvin/vector_engine/db:/var/lib/milvus/db \
-v /Users/calvin/vector_engine/conf:/var/lib/milvus/conf \
-v /Users/calvin/vector_engine/logs:/var/lib/milvus/logs \
-v /Users/calvin/vector_engine/wal:/var/lib/milvus/wal \
milvusdb/milvus:0.10.0-cpu-d061620-5f3c00
sudo docker-compose up -d
```
#### 3.5 编辑向量引擎连接配置信息
- application.yml
- 根据需要编辑向量引擎连接ip地址127.0.0.1为容器所在的主机ip
```bash
##################### 向量引擎 ###############################
################## 向量引擎 ################
search:
host: 127.0.0.1
port: 19530
indexFileSize: 1024 # maximum size (in MB) of each index file
nprobe: 256
nlist: 16384
faceDimension: 512 #dimension of each vector
faceCollectionName: faces #collection name
commDimension: 512 #dimension of each vector
commCollectionName: comm #collection name
```
## 4. 打开浏览器

View File

@ -77,8 +77,8 @@ file:
path: /home/aias/file/
rootPath: /home/aias/file/audio_root/ #压缩包解压缩文件夹
windows:
path: file:///D:/aias/file/
rootPath: file:///D:/aias/file/audio_root/ #压缩包解压缩文件夹
path: file:/D:/aias/file/
rootPath: file:/D:/aias/file/audio_root/ #压缩包解压缩文件夹
...
```
@ -97,54 +97,30 @@ java -jar voiceprint-search-0.1.0.jar
```
## 3. 后端向量引擎部署(docker
## 3. 后端向量引擎部署(Milvus 2.0
#### 3.1 环境要求:
- 需要安装docker运行环境Mac环境可以使用Docker Desktop
#### 3.2 拉取Milvus向量引擎镜像用于计算特征值向量相似度
[安装文档](https://github.com/milvus-io/docs/blob/master/v0.10.0/site/zh-CN/quick_start/install_milvus/cpu_milvus_docker.md)
##### 最新版本请参考官网
- Milvus向量引擎参考链接
[Milvus向量引擎官网](https://milvus.io/cn/docs/overview.md)
[Milvus向量引擎Github](https://github.com/milvus-io)
下载 milvus-standalone-docker-compose.yml 配置文件并保存为 docker-compose.yml
[单机版安装文档](https://milvus.io/docs/v2.0.0/install_standalone-docker.md)
```bash
sudo docker pull milvusdb/milvus:0.10.0-cpu-d061620-5f3c00
wget https://github.com/milvus-io/milvus/releases/download/v2.0.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
```
#### 3.3 下载配置文件
[vector_engine.zip](https://aias-home.oss-cn-beijing.aliyuncs.com/AIAS/image_search/vector_engine.zip)
#### 3.4 启动 Docker 容器
/Users/calvin/vector_engine为主机路径根据需要修改。conf下为引擎所需的配置文件。
#### 3.3 启动 Docker 容器
```bash
docker run -d --name milvus_cpu_0.10.0 \
-p 19530:19530 \
-p 19121:19121 \
-p 9091:9091 \
-v /Users/calvin/vector_engine/db:/var/lib/milvus/db \
-v /Users/calvin/vector_engine/conf:/var/lib/milvus/conf \
-v /Users/calvin/vector_engine/logs:/var/lib/milvus/logs \
-v /Users/calvin/vector_engine/wal:/var/lib/milvus/wal \
milvusdb/milvus:0.10.0-cpu-d061620-5f3c00
sudo docker-compose up -d
```
#### 3.5 编辑向量引擎连接配置信息
- application.yml
- 根据需要编辑向量引擎连接ip地址127.0.0.1为容器所在的主机ip
```bash
##################### 向量引擎 ###############################
################## 向量引擎 ################
search:
host: 127.0.0.1
port: 19530
indexFileSize: 1024 # maximum size (in MB) of each index file
nprobe: 256
nlist: 16384
faceDimension: 512 #dimension of each vector
faceCollectionName: faces #collection name
commDimension: 512 #dimension of each vector
commCollectionName: comm #collection name
```
## 4. 打开浏览器
@ -158,9 +134,8 @@ search:
![Screenshot](https://aias-home.oss-cn-beijing.aliyuncs.com/AIAS/audio_search/storage.png)
- 视频搜索
上传图片,点击查询,可以看到返回的图片清单,根据相似度排序。
- 音频搜索
上传wav格式音频文件点击查询可以看到返回的清单根据相似度排序。
![Screenshot](https://aias-home.oss-cn-beijing.aliyuncs.com/AIAS/audio_search/search.png)
## 5. 帮助信息
@ -170,29 +145,10 @@ http://localhost:8089/swagger-ui.html
- 初始化向量引擎(清空数据):
me.aias.tools.MilvusInit.java
```bash
String host = "127.0.0.1";
int port = 19530;
final String collectionName = "voiceprint"; // collection name
MilvusClient client = new MilvusGrpcClient();
// Connect to Milvus server
ConnectParam connectParam = new ConnectParam.Builder().withHost(host).withPort(port).build();
try {
Response connectResponse = client.connect(connectParam);
} catch (ConnectFailedException e) {
e.printStackTrace();
}
// 检查 collection 是否存在
HasCollectionResponse hasCollection = hasCollection(client, collectionName);
if (hasCollection.hasCollection()) {
dropIndex(client, collectionName);
dropCollection(client, collectionName);
}
...
```
- Milvus向量引擎参考链接
[Milvus向量引擎官网](https://milvus.io/cn/docs/overview.md)
[Milvus向量引擎Github](https://github.com/milvus-io)
### 官网:
[官网链接](http://www.aias.top/)

View File

@ -15,7 +15,7 @@
"dependencies": {
"crypto-js": "^3.1.9-1",
"axios": "0.18.1",
"core-js": "3.6.5",
"core-js": "3.21.0",
"easy-circular-progress": "1.0.4",
"echarts": "^4.2.1",
"element-ui": "2.13.2",
@ -23,7 +23,6 @@
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"vertx3-eventbus-client": "^3.9.4",
"vue": "2.6.10",
"vue-count-to": "^1.0.13",
"vue-json-viewer": "^2.2.18",

View File

@ -38,7 +38,7 @@ service.interceptors.response.use(
response => {
const res = response.data
// if the custom code is not 20000, it is judged as an error.
// if the custom code is not 0, it is judged as an error.
if (res.code !== 0) {
Message({
message: res.message || 'Error',

View File

@ -1,12 +1,11 @@
<template>
<div class="image-table">
<div class="wave-table">
<div class="head">
<div class="bts">
TopK<el-input v-model="topK" type="primary" style="margin:0 5px;width: 100px;" placeholder="输入TopK" />
<el-upload
ref="avatarUploader"
ref="waveUploader"
name="audio"
style="height: 28px;"
:on-change="handleFileChange"
:before-upload="handleUploadBefore"
:on-success="handleSuccess"
@ -15,10 +14,10 @@
:auto-upload="false"
:action="upload()"
:limit="0"
:show-file-list="true"
:show-file-list="false"
>
<el-input
style="margin-right: 5px;"
style="margin-right: 15px;"
placeholder="请上传wav格式音频文件"
>
<i slot="prefix" class="el-icon-search el-input__icon" />
@ -26,6 +25,7 @@
</el-upload>
<el-button
ref="queryButton"
style="margin-left: 10px;"
icon="el-icon-search"
class="filter-item"
size="medium"
@ -115,7 +115,7 @@ export default {
doFaceQuery() {
this.page.pageNum = 1
this.type = 1
this.$refs.avatarUploader.submit()
this.$refs.waveUploader.submit()
},
handleSuccess(response, file, fileList) {
if (response.success && response.data) {
@ -137,14 +137,16 @@ export default {
this.tableData = []
this.page.total = 0
}
fileList[fileList.length - 1].status = 'ready'
},
handleFileChange(file, fileList) {
if (fileList[0] && fileList[0].size > 2097152) {
this.$message.warning('请上传小于2M大小的图片')
this.$refs.avatarUploader.clearFiles()
this.$refs.waveUploader.clearFiles()
return false
}
this.imgFile = file
fileList[fileList.length - 1].status = 'ready'
},
handleUploadBefore(file) {
if (file.size > 2097152) {
@ -153,13 +155,13 @@ export default {
}
},
removeField() {
this.$refs.avatarUploader.clearFiles()
this.$refs.waveUploader.clearFiles()
}
}
}
</script>
<style lang='scss' scoped>
<style lang='scss'>
@import "~@/assets/styles/base";
.left {
@ -176,26 +178,45 @@ export default {
overflow-y: auto;
flex-wrap: wrap;
}
.image-table {
.wave-table {
position: relative;
top: 15px;
box-sizing: border-box;
height: calc(100vh - 200px);
height: calc(100vh - 100px);
}
:global(.el-radio-button__inner) {
.el-upload-dragger {
border: none;
border-radius: 0;
box-sizing: border-box;
width: 200px;
height: 40px;
left: 2px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.el-radio-button__inner{
color: rgba(14, 37, 60, 1);
font-weight: 400;
.iconfont {
color: rgba(14, 37, 60, 1);
font-weight: 400;
}
}
:global(.el-upload) {
.el-upload{
border: none;
display: inherit;
}
.img-upload {
@include all-height(36px);
@include flex-row-between-center;
width: 36px;
margin: 0 0 0 8px;
img {
width: 36px;
height: 36px;
}
}
.head {

View File

@ -145,7 +145,7 @@ export default {
extract(id).then(response => {
this.$message({
type: 'success',
message: '已开始,刷新页面查看进度!'
message: '提取成功!'
})
})
}

View File

@ -109,7 +109,7 @@
<dependency>
<groupId>io.milvus</groupId>
<artifactId>milvus-sdk-java</artifactId>
<version>0.8.2</version>
<version>2.0.0</version>
</dependency>
<!-- java cv -->
<dependency>

View File

@ -0,0 +1,235 @@
package me.aias.common.milvus;
import io.milvus.client.MilvusClient;
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import java.util.Enumeration;
import java.util.Vector;
public class ConnectionPool {
private String host = ""; // Milvus 主机
private int port; // Milvus 端口号
private static volatile ConnectionPool uniqueInstance;
private int initialConnections = 10; // 连接池的初始大小
private int incrementalConnections = 5; // 连接池自动增加的大小
private int maxConnections = 50; // 连接池最大的大小
private Vector connections = null; // 存放连接池中连接的向量, 存放的对象为 PooledConnection
private ConnectionPool(String host, int port) {
this.host = host;
this.port = port;
}
public static ConnectionPool getInstance(String host, String port, boolean refresh) {
if (uniqueInstance == null || refresh) {
synchronized (ConnectionPool.class) {
if (uniqueInstance == null || refresh) {
uniqueInstance = new ConnectionPool(host, Integer.parseInt(port));
try {
uniqueInstance.createPool();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
return uniqueInstance;
}
private void createPool() { // synchronized
if (connections != null) {
return; // 假如己经创建则返回
}
// 创建保存连接的向量 , 初始时有 0 个元素
connections = new Vector();
// 根据 initialConnections 中设置的值创建连接
createConnections(this.initialConnections);
System.out.println(" Milvus连接池创建成功");
}
private void createConnections(int numConnections) {
// 循环创建指定数目的数据库连接
for (int x = 0; x < numConnections; x++) {
// 是否连接池中的Milvus连接数量己经达到最大最大值由类成员 maxConnections
if (this.maxConnections > 0 && this.connections.size() >= this.maxConnections) {
break;
}
// 增加一个连接到连接池中Vector connections
connections.addElement(new PooledConnection(newConnection()));
System.out.println(" Milvus连接己创建 ......");
}
}
private MilvusClient newConnection() {
// 创建一个 Milvus 客户端
ConnectParam connectParam = ConnectParam.newBuilder()
.withHost(host)
.withPort(port)
.build();
MilvusServiceClient milvusClient = new MilvusServiceClient(connectParam);
// 返回创建的新的Milvus连接
return milvusClient;
}
public synchronized MilvusClient getConnection() {
// 确保连接池己被创建
if (connections == null) {
return null; // 连接池还没创建则返回 null
}
MilvusClient client = getFreeConnection(); // 获得一个可用的数据库连接
// 假如目前没有可以使用的连接即所有的连接都在使用中
while (client == null) {
// 等一会再试 250 ms
wait(250);
client = getFreeConnection(); // 重新再试直到获得可用的连接假如
// getFreeConnection() 返回的为 null
// 则表明创建一批连接后也不可获得可用连接
}
return client; // 返回获得的可用的连接
}
private MilvusClient getFreeConnection() {
// 从连接池中获得一个可用的Milvus连接
MilvusClient client = findFreeConnection();
if (client == null) {
// 假如目前连接池中没有可用的连接
// 创建一些连接
createConnections(incrementalConnections);
// 重新从池中查找是否有可用连接
client = findFreeConnection();
if (client == null) {
// 假如创建连接后仍获得不到可用的连接则返回 null
return null;
}
}
return client;
}
private MilvusClient findFreeConnection() {
MilvusClient client = null;
PooledConnection pConn = null;
// 获得连接池中所有的对象
Enumeration enumerate = connections.elements();
// 遍历所有的对象看是否有可用的连接
while (enumerate.hasMoreElements()) {
pConn = (PooledConnection) enumerate.nextElement();
if (!pConn.isBusy()) {
// 假如此对象不忙则获得它的数据库连接并把它设为忙
client = pConn.getConnection();
pConn.setBusy(true);
break; // 己经找到一个可用的连接退出
}
}
return client; // 返回找到到的可用连接
}
public void returnConnection(MilvusClient client) {
// 确保连接池存在假如连接没有创建不存在直接返回
if (connections == null) {
System.out.println(" 连接池不存在,无法返回此连接到连接池中 !");
return;
}
PooledConnection pConn = null;
Enumeration enumerate = connections.elements();
// 遍历连接池中的所有连接找到这个要返回的连接对象
while (enumerate.hasMoreElements()) {
pConn = (PooledConnection) enumerate.nextElement();
// 先找到连接池中的要返回的连接对象
if (client == pConn.getConnection()) {
// 找到了 , 设置此连接为空闲状态
pConn.setBusy(false);
break;
}
}
}
public synchronized void refreshConnections() {
// 确保连接池己创新存在
if (connections == null) {
System.out.println(" 连接池不存在,无法刷新 !");
return;
}
PooledConnection pConn = null;
Enumeration enumerate = connections.elements();
while (enumerate.hasMoreElements()) {
// 获得一个连接对象
pConn = (PooledConnection) enumerate.nextElement();
// 假如对象忙则等 5 ,5 秒后直接刷新
if (pConn.isBusy()) {
wait(5000); // 5
}
// 关闭此连接用一个新的连接代替它
closeConnection(pConn.getConnection());
pConn.setConnection(newConnection());
pConn.setBusy(false);
}
}
public synchronized void closeConnectionPool() {
// 确保连接池存在假如不存在返回
if (connections == null) {
System.out.println(" 连接池不存在,无法关闭 !");
return;
}
PooledConnection pConn = null;
Enumeration enumerate = connections.elements();
while (enumerate.hasMoreElements()) {
pConn = (PooledConnection) enumerate.nextElement();
// 假如忙 5
if (pConn.isBusy()) {
wait(5000); // 5
}
// 5 秒后直接关闭它
closeConnection(pConn.getConnection());
// 从连接池向量中删除它
connections.removeElement(pConn);
}
// 置连接池为空
connections = null;
}
private void closeConnection(MilvusClient client) {
client.close();
}
private void wait(int mSeconds) {
try {
Thread.sleep(mSeconds);
} catch (InterruptedException e) {
}
}
class PooledConnection {
MilvusClient client = null; // Milvus连接
boolean busy = false; // 此连接是否正在使用的标志默认没有正在使用
// 构造函数根据一个 Connection 构告一个 PooledConnection 对象
public PooledConnection(MilvusClient client) {
this.client = client;
}
// 返回此对象中的连接
public MilvusClient getConnection() {
return client;
}
// 设置此对象的连接
public void setConnection(MilvusClient client) {
this.client = client;
}
// 获得对象连接是否忙
public boolean isBusy() {
return busy;
}
// 设置对象的连接正在忙
public void setBusy(boolean busy) {
this.busy = busy;
}
}
}

View File

@ -1,35 +0,0 @@
package me.aias.common.milvus;
import io.milvus.client.*;
import lombok.extern.slf4j.Slf4j;
/**
* @author Calvin
* @date Oct 20, 2021
*/
@Slf4j
public final class MilvusConnector {
// 创建一个 Milvus 客户端
private MilvusClient client = null;
public void init(String host, int port) {
client = new MilvusGrpcClient();
// Connect to Milvus server
ConnectParam connectParam = new ConnectParam.Builder().withHost(host).withPort(port).build();
try {
Response connectResponse = client.connect(connectParam);
} catch (ConnectFailedException e) {
log.error("Failed to connect to Milvus server: " + e.toString());
}
}
public void close() throws InterruptedException {
this.client.disconnect();
}
public MilvusClient getClient() {
return client;
}
}

View File

@ -1,4 +1,4 @@
package me.aias.voice;
package me.aias.common.voice;
import ai.djl.MalformedModelException;
import ai.djl.inference.Predictor;
@ -18,22 +18,18 @@ import java.io.IOException;
* @date 2021-12-12
**/
public final class VoiceprintModel {
private ZooModel<float[][], float[]> model;
private Predictor<float[][], float[]> predictor;
public void init(String modelUri) throws MalformedModelException, ModelNotFoundException, IOException {
this.model = ModelZoo.loadModel(detectCriteria(modelUri));
this.predictor = model.newPredictor();
}
public ZooModel<float[][], float[]> getModel() {
return model;
}
public void close() {
this.model.close();
this.predictor.close();
}
public float[] predict(float[][] mag) throws TranslateException {
return predictor.predict(mag);
}
private Criteria<float[][], float[]> detectCriteria(String modelUri) {

View File

@ -1,4 +1,4 @@
package me.aias.voice;
package me.aias.common.voice;
import ai.djl.ndarray.NDArray;
import ai.djl.ndarray.NDList;

View File

@ -1,26 +0,0 @@
package me.aias.config;
import me.aias.common.milvus.MilvusConnector;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 图片操作常量类
* @author Calvin
* @date 2021-12-12
**/
@Configuration
public class MilvusConfiguration {
@Value("${search.host}")
private String host;
@Value("${search.port}")
private int port;
@Bean
public MilvusConnector milvusConnector() {
MilvusConnector milvus = new MilvusConnector();
milvus.init(host, port);
return milvus;
}
}

View File

@ -2,7 +2,7 @@ package me.aias.config;
import ai.djl.MalformedModelException;
import ai.djl.repository.zoo.ModelNotFoundException;
import me.aias.voice.VoiceprintModel;
import me.aias.common.voice.VoiceprintModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@ -6,8 +6,7 @@ import ai.djl.ndarray.NDManager;
import ai.djl.translate.TranslateException;
import com.jlibrosa.audio.exception.FileFormatNotSupportedException;
import com.jlibrosa.audio.wavFile.WavFileException;
import io.milvus.client.ConnectFailedException;
import io.milvus.client.HasCollectionResponse;
import io.milvus.param.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
@ -18,10 +17,7 @@ import me.aias.common.utils.UUIDUtil;
import me.aias.common.utils.UserAgentUtil;
import me.aias.common.utils.ZipUtil;
import me.aias.config.FileProperties;
import me.aias.domain.AudioInfo;
import me.aias.domain.LocalStorage;
import me.aias.domain.ResEnum;
import me.aias.domain.ResultRes;
import me.aias.domain.*;
import me.aias.service.AudioService;
import me.aias.service.FeatureService;
import me.aias.service.LocalStorageService;
@ -68,12 +64,6 @@ public class AudioController {
@Autowired
private LocalStorageService localStorageService;
@Value("${search.dimension}")
String dimension;
@Value("${search.collectionName}")
String collectionName;
@ApiOperation(value = "视频解析图片帧并提取特征值")
@GetMapping("/extractFeatures")
public ResponseEntity<Object> extractFeatures(@RequestParam(value = "id") String id, HttpServletRequest request) throws IOException {
@ -126,13 +116,12 @@ public class AudioController {
// 将向量插入Milvus向量引擎
try {
HasCollectionResponse response = searchService.hasCollection(this.collectionName);
if (!response.hasCollection()) {
searchService.createCollection(this.collectionName, Long.parseLong(this.dimension));
searchService.createIndex(this.collectionName);
R<Boolean> response = searchService.hasCollection();
if (!response.getData()) {
searchService.initSearchEngine();
}
searchService.insertVectors(this.collectionName, vectorIds, vectors);
} catch (ConnectFailedException e) {
searchService.insert(vectorIds, vectors);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
return new ResponseEntity<>(ResultRes.error(ResEnum.MILVUS_CONNECTION_ERROR.KEY, ResEnum.MILVUS_CONNECTION_ERROR.VALUE), HttpStatus.OK);
@ -149,6 +138,6 @@ public class AudioController {
e.printStackTrace();
}
return new ResponseEntity<>(ResultRes.success(), HttpStatus.OK);
return new ResponseEntity<>(ResultBean.success(), HttpStatus.OK);
}
}

View File

@ -2,9 +2,9 @@ package me.aias.controller;
import ai.djl.Device;
import ai.djl.ndarray.NDManager;
import com.google.common.collect.Lists;
import io.milvus.client.ConnectFailedException;
import io.milvus.client.SearchResponse;
import io.milvus.Response.SearchResultsWrapper;
import io.milvus.grpc.SearchResults;
import io.milvus.param.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
@ -64,7 +64,7 @@ public class SearchController {
@ApiOperation(value = "音频搜索", nickname = "searchAudio")
public ResponseEntity<Object> searchImage(@RequestParam("audio") MultipartFile audioFile, @RequestParam(value = "topK") String topk) {
// 生成向量
Long topK = Long.parseLong(topk);
Integer topK = Integer.parseInt(topk);
float[][] mag;
try {
@ -95,43 +95,26 @@ public class SearchController {
try {
// 根据音频文件向量搜索
SearchResponse searchResponse = searchService.search(this.collectionName, topK, vectorsToSearch);
List<List<Long>> resultIds = searchResponse.getResultIdsList();
List<String> idList = Lists.transform(resultIds.get(0), (entity) -> {
return entity.toString();
});
R<SearchResults> searchResponse = searchService.search(topK, vectorsToSearch);
SearchResultsWrapper wrapper = new SearchResultsWrapper(searchResponse.getData().getResults());
List<SearchResultsWrapper.IDScore> scores = wrapper.getIDScore(0);
// 根据ID获取图片信息
ConcurrentHashMap<String, String> map = audioService.getMap();
List<AudioInfoRes> audioInfoResList = new ArrayList<>();
for (String id : idList) {
for (SearchResultsWrapper.IDScore score : scores) {
AudioInfoRes imageInfoRes = new AudioInfoRes();
Float score = maxScore(searchResponse, Long.parseLong(id));
imageInfoRes.setScore(score);
imageInfoRes.setId(Long.parseLong(id));
imageInfoRes.setUrl(baseUrl + map.get(id));
imageInfoRes.setScore(score.getScore());
imageInfoRes.setId(score.getLongID());
imageInfoRes.setUrl(baseUrl + map.get("" + score.getLongID()));
audioInfoResList.add(imageInfoRes);
}
return new ResponseEntity<>(ResultRes.success(audioInfoResList, audioInfoResList.size()), HttpStatus.OK);
} catch (ConnectFailedException e) {
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
return new ResponseEntity<>(ResultRes.error(ResEnum.MILVUS_CONNECTION_ERROR.KEY, ResEnum.MILVUS_CONNECTION_ERROR.VALUE), HttpStatus.OK);
}
}
private Float maxScore(SearchResponse searchResponse, Long imageId) {
float maxScore = -1;
List<SearchResponse.QueryResult> list = searchResponse.getQueryResultsList().get(0);
for (SearchResponse.QueryResult result : list) {
if (result.getVectorId() == imageId.longValue()) {
if (result.getDistance() > maxScore) {
maxScore = result.getDistance();
}
}
}
return maxScore;
}
}

View File

@ -1,78 +1,71 @@
package me.aias.service;
import io.milvus.client.*;
import io.milvus.client.MilvusClient;
import io.milvus.grpc.MutationResult;
import io.milvus.grpc.QueryResults;
import io.milvus.grpc.SearchResults;
import io.milvus.param.R;
import io.milvus.param.RpcStatus;
import me.aias.common.milvus.ConnectionPool;
import java.util.List;
/**
* 搜索服务接口
*
* @author Calvin
* @date 2021-12-12
**/
public interface SearchService {
// 引擎初始化
void initSearchEngine() throws ConnectFailedException;
// 重置向量引擎
void clearSearchEngine();
// 初始化向量引擎
void initSearchEngine();
// 获取连接池
ConnectionPool getConnectionPool(boolean refresh);
// 获取Milvus Client
MilvusClient getClient(ConnectionPool connPool);
// 检查是否存在 collection
HasCollectionResponse hasCollection(MilvusClient client, String collectionName);
void returnConnection(ConnectionPool connPool, MilvusClient client);
HasCollectionResponse hasCollection(String collectionName) throws ConnectFailedException;
// 检查是否存在 collection
R<Boolean> hasCollection(MilvusClient milvusClient);
R<Boolean> hasCollection();
// 创建 collection
Response createCollection(
MilvusClient client, String collectionName, long dimension, long indexFileSize);
R<RpcStatus> createCollection(MilvusClient milvusClient, long timeoutMiliseconds);
Response createCollection(String collectionName, long dimension) throws ConnectFailedException;
// 加载 collection
R<RpcStatus> loadCollection(MilvusClient milvusClient);
// 释放 collection
R<RpcStatus> releaseCollection(MilvusClient milvusClient);
// 删除 collection
Response dropCollection(MilvusClient client, String collectionName);
R<RpcStatus> dropCollection(MilvusClient milvusClient);
// 查看 collection 信息
Response getCollectionStats(MilvusClient client, String collectionName);
// 创建 分区
R<RpcStatus> createPartition(MilvusClient milvusClient, String partitionName);
// 插入向量
void insertVectors(String collectionName, Long id, List<Float> feature) throws ConnectFailedException;
// 删除 分区
R<RpcStatus> dropPartition(MilvusClient milvusClient, String partitionName);
void insertVectors(String collectionName, List<Long> vectorIds, List<List<Float>> vectors) throws ConnectFailedException;
InsertResponse insertVectors(
MilvusClient client, String collectionName, List<Long> vectorIds, List<List<Float>> vectors);
// 查询向量数量
long count(MilvusClient client, String collectionName);
// 根据ID获取向量
GetEntityByIDResponse getEntityByID(
MilvusClient client, String collectionName, List<Long> vectorIds);
// 搜索向量
SearchResponse search(String collectionName, long topK, List<List<Float>> vectorsToSearch) throws ConnectFailedException;
SearchResponse search(
MilvusClient client,
String collectionName,
int nprobe,
long topK,
List<List<Float>> vectorsToSearch);
// 删除向量
Response deleteVectorsByIds(MilvusClient client, String collectionName, List<Long> vectorIds);
// 是否存在分区
R<Boolean> hasPartition(MilvusClient milvusClient, String partitionName);
// 创建 index
Response createIndex(MilvusClient client, String collectionName);
Response createIndex(String collectionName) throws ConnectFailedException;
// 查看索引信息
GetIndexInfoResponse getIndexInfo(MilvusClient client, String collectionName);
R<RpcStatus> createIndex(MilvusClient client);
// 删除 index
Response dropIndex(MilvusClient client, String collectionName);
R<RpcStatus> dropIndex(MilvusClient client);
// 压缩 collection
Response compactCollection(MilvusClient client, String collectionName);
// 插入向量
R<MutationResult> insert(List<Long> vectorIds, List<List<Float>> vectors);
// 检查 collection 中是否有 partition "tag"
HasPartitionResponse hasPartition(MilvusClient client, String collectionName, String tag);
// 查询向量
R<QueryResults> query(String expr);
// 搜索向量
R<SearchResults> search(Integer topK, List<List<Float>> vectorsToSearch);
// 删除向量
R<MutationResult> delete(String expr);
}

View File

@ -1,9 +1,12 @@
package me.aias.service.impl;
import ai.djl.inference.Predictor;
import ai.djl.modality.cv.Image;
import ai.djl.repository.zoo.ZooModel;
import ai.djl.translate.TranslateException;
import lombok.extern.slf4j.Slf4j;
import me.aias.service.FeatureService;
import me.aias.voice.VoiceprintModel;
import me.aias.common.voice.VoiceprintModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -23,8 +26,9 @@ public class FeatureServiceImpl implements FeatureService {
private VoiceprintModel featureModel;
public List<Float> feature(float[][] mag) throws TranslateException {
float[] embeddings = null;
embeddings = featureModel.predict(mag);
ZooModel<float[][], float[]> model = featureModel.getModel();
try (Predictor<float[][], float[]> predictor = model.newPredictor()) {
float[] embeddings = predictor.predict(mag);
List<Float> feature = new ArrayList<>();
if (embeddings != null) {
@ -37,3 +41,4 @@ public class FeatureServiceImpl implements FeatureService {
return feature;
}
}
}

View File

@ -1,23 +1,37 @@
package me.aias.service.impl;
import com.google.gson.JsonObject;
import io.milvus.client.*;
import io.milvus.Response.QueryResultsWrapper;
import io.milvus.Response.SearchResultsWrapper;
import io.milvus.client.MilvusClient;
import io.milvus.grpc.DataType;
import io.milvus.grpc.MutationResult;
import io.milvus.grpc.QueryResults;
import io.milvus.grpc.SearchResults;
import io.milvus.param.IndexType;
import io.milvus.param.MetricType;
import io.milvus.param.R;
import io.milvus.param.RpcStatus;
import io.milvus.param.collection.*;
import io.milvus.param.dml.DeleteParam;
import io.milvus.param.dml.InsertParam;
import io.milvus.param.dml.QueryParam;
import io.milvus.param.dml.SearchParam;
import io.milvus.param.index.CreateIndexParam;
import io.milvus.param.index.DropIndexParam;
import io.milvus.param.partition.CreatePartitionParam;
import io.milvus.param.partition.DropPartitionParam;
import io.milvus.param.partition.HasPartitionParam;
import lombok.extern.slf4j.Slf4j;
import me.aias.common.milvus.MilvusConnector;
import me.aias.common.milvus.ConnectionPool;
import me.aias.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 搜素服务
*
* @author Calvin
* @date 2021-12-12
**/
@Slf4j
@Service
public class SearchServiceImpl implements SearchService {
@ -27,11 +41,20 @@ public class SearchServiceImpl implements SearchService {
@Value("${search.port}")
String port;
@Value("${search.indexType}")
String indexType;
@Value("${search.metricType}")
String metricType;
@Value("${search.dimension}")
String dimension;
@Value("${search.collectionName}")
String collectionName;
@Value("${search.indexFileSize}")
String indexFileSize;
@Value("${search.partitionName}")
String partitionName;
@Value("${search.nprobe}")
String nprobe;
@ -39,234 +62,344 @@ public class SearchServiceImpl implements SearchService {
@Value("${search.nlist}")
String nlist;
@Autowired
private MilvusConnector milvusConnector;
private static final String ID_FIELD = "featureId";
private static final String VECTOR_FIELD = "feature";
// 重置向量引擎
public void clearSearchEngine() {
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient client = connPool.getConnection();
try {
this.releaseCollection(client);
this.dropPartition(client, partitionName);
this.dropIndex(client);
this.dropCollection(client);
} finally {
returnConnection(connPool, client);
}
}
// 初始化向量引擎
public void initSearchEngine() {
MilvusClient client = milvusConnector.getClient();
// 检查 collection 是否存在
HasCollectionResponse hasCollection = this.hasCollection(client, collectionName);
if (hasCollection.hasCollection()) {
this.dropCollection(client, collectionName);
this.dropIndex(client, collectionName);
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient client = connPool.getConnection();
try {
this.createCollection(client, 2000);
this.loadCollection(client);
this.createPartition(client, partitionName);
this.createIndex(client);
} finally {
returnConnection(connPool, client);
}
}
// 检查是否存在 collection
public HasCollectionResponse hasCollection(MilvusClient client, String collectionName) {
HasCollectionResponse response = client.hasCollection(collectionName);
return response;
public ConnectionPool getConnectionPool(boolean refresh) {
ConnectionPool connPool = ConnectionPool.getInstance(host, port, refresh);
return connPool;
}
public MilvusClient getClient(ConnectionPool connPool) {
MilvusClient client = connPool.getConnection();
return client;
}
public void returnConnection(ConnectionPool connPool, MilvusClient client) {
// 释放 Milvus client 回连接池
connPool.returnConnection(client);
// 关闭 Milvus 连接池
// connPool.closeConnectionPool();
}
// 检查是否存在 collection
public HasCollectionResponse hasCollection(String collectionName) {
MilvusClient client = milvusConnector.getClient();
HasCollectionResponse response = client.hasCollection(collectionName);
public R<Boolean> hasCollection(MilvusClient client) {
R<Boolean> response = client.hasCollection(HasCollectionParam.newBuilder()
.withCollectionName(collectionName)
.build());
return response;
}
public R<Boolean> hasCollection() {
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient client = connPool.getConnection();
try {
R<Boolean> response = hasCollection(client);
return response;
} finally {
returnConnection(connPool, client);
}
}
// 创建 collection
public Response createCollection(
MilvusClient client, String collectionName, long dimension, long indexFileSize) {
// 选择内积 IP (Inner Product) 作为距离计算方式 MetricType.IP
final MetricType metricType = MetricType.L2;
CollectionMapping collectionMapping =
new CollectionMapping.Builder(collectionName, dimension)
.withIndexFileSize(indexFileSize)
.withMetricType(metricType)
public R<RpcStatus> createCollection(MilvusClient milvusClient, long timeoutMiliseconds) {
System.out.println("========== createCollection() ==========");
FieldType fieldType1 = FieldType.newBuilder()
.withName(ID_FIELD)
.withDescription("image id")
.withDataType(DataType.Int64)
.withPrimaryKey(true)
.withAutoID(false) // 使用数据库生成的id
.build();
Response createCollectionResponse = client.createCollection(collectionMapping);
return createCollectionResponse;
FieldType fieldType2 = FieldType.newBuilder()
.withName(VECTOR_FIELD)
.withDescription("image embedding")
.withDataType(DataType.FloatVector)
.withDimension(Integer.parseInt(dimension))
.build();
CreateCollectionParam createCollectionReq = CreateCollectionParam.newBuilder()
.withCollectionName(collectionName)
.withDescription("image info")
.withShardsNum(2)
.addFieldType(fieldType1)
.addFieldType(fieldType2)
.build();
R<RpcStatus> response = milvusClient.withTimeout(timeoutMiliseconds, TimeUnit.MILLISECONDS)
.createCollection(createCollectionReq);
return response;
}
public Response createCollection(String collectionName, long dimension) {
// 选择内积 IP (Inner Product) 作为距离计算方式 MetricType.IP
final MetricType metricType = MetricType.L2;
CollectionMapping collectionMapping =
new CollectionMapping.Builder(collectionName, dimension)
.withIndexFileSize(Long.parseLong(indexFileSize))
.withMetricType(metricType)
.build();
MilvusClient client = milvusConnector.getClient();
Response createCollectionResponse = client.createCollection(collectionMapping);
return createCollectionResponse;
// 加载 collection
public R<RpcStatus> loadCollection(MilvusClient milvusClient) {
System.out.println("========== loadCollection() ==========");
R<RpcStatus> response = milvusClient.loadCollection(LoadCollectionParam.newBuilder()
.withCollectionName(collectionName)
.build());
return response;
}
// 释放 collection
public R<RpcStatus> releaseCollection(MilvusClient milvusClient) {
System.out.println("========== releaseCollection() ==========");
R<RpcStatus> response = milvusClient.releaseCollection(ReleaseCollectionParam.newBuilder()
.withCollectionName(collectionName)
.build());
return response;
}
// 删除 collection
public Response dropCollection(MilvusClient client, String collectionName) {
// Drop collection
Response dropCollectionResponse = client.dropCollection(collectionName);
return dropCollectionResponse;
public R<RpcStatus> dropCollection(MilvusClient milvusClient) {
System.out.println("========== dropCollection() ==========");
R<RpcStatus> response = milvusClient.dropCollection(DropCollectionParam.newBuilder()
.withCollectionName(collectionName)
.build());
return response;
}
// 查看 collection 信息
public Response getCollectionStats(MilvusClient client, String collectionName) {
Response getCollectionStatsResponse = client.getCollectionStats(collectionName);
// if (getCollectionStatsResponse.ok()) {
// // JSON 格式 collection 信息
// String jsonString = getCollectionStatsResponse.getMessage();
// System.out.format("Collection 信息: %s\n", jsonString);
// }
return getCollectionStatsResponse;
// 创建 分区
public R<RpcStatus> createPartition(MilvusClient milvusClient, String partitionName) {
System.out.println("========== createPartition() ==========");
R<RpcStatus> response = milvusClient.createPartition(CreatePartitionParam.newBuilder()
.withCollectionName(collectionName)
.withPartitionName(partitionName)
.build());
return response;
}
// 插入向量
public void insertVectors(String collectionName, Long id, List<Float> feature) {
MilvusClient client = milvusConnector.getClient();
List<Long> vectorIds = new ArrayList<>();
List<List<Float>> vectors = new ArrayList<>();
vectorIds.add(id);
vectors.add(feature);
this.insertVectors(client, collectionName, vectorIds, vectors);
// 删除 分区
public R<RpcStatus> dropPartition(MilvusClient milvusClient, String partitionName) {
System.out.println("========== dropPartition() ==========");
R<RpcStatus> response = milvusClient.dropPartition(DropPartitionParam.newBuilder()
.withCollectionName(collectionName)
.withPartitionName(partitionName)
.build());
return response;
}
// 插入向量
public void insertVectors(String collectionName, List<Long> vectorIds, List<List<Float>> vectors) {
MilvusClient client = milvusConnector.getClient();
this.insertVectors(client, collectionName, vectorIds, vectors);
}
public InsertResponse insertVectors(
MilvusClient client, String collectionName, List<Long> vectorIds, List<List<Float>> vectors) {
// 需要主动指定ID图片的ID用来关联图片资源页面显示使用等
InsertParam insertParam =
new InsertParam.Builder(collectionName)
.withVectorIds(vectorIds)
.withFloatVectors(vectors)
.build();
InsertResponse insertResponse = client.insert(insertParam);
// 返回向量ID列表向量ID如果不主动赋值系统自动生成并返回
// List<Long> vectorIds = insertResponse.getVectorIds();
return insertResponse;
}
// 刷新数据
public Response flushData(MilvusClient client, String collectionName) {
// Flush data in collection
Response flushResponse = client.flush(collectionName);
return flushResponse;
}
// 查询向量数量
public long count(MilvusClient client, String collectionName) {
// 获取数据条数
CountEntitiesResponse ountEntitiesResponse = client.countEntities(collectionName);
long rows = ountEntitiesResponse.getCollectionEntityCount();
return rows;
}
// 根据ID获取向量
public GetEntityByIDResponse getEntityByID(
MilvusClient client, String collectionName, List<Long> vectorIds) {
GetEntityByIDResponse getEntityByIDResponse =
client.getEntityByID(collectionName, vectorIds.subList(0, 5));
return getEntityByIDResponse;
}
// 搜索向量
public SearchResponse search(String collectionName, long topK, List<List<Float>> vectorsToSearch) {
// 索引类型不同参数也可能不同查询文档选择最优参数
JsonObject searchParamsJson = new JsonObject();
searchParamsJson.addProperty("nprobe", Integer.parseInt(nprobe));
SearchParam searchParam =
new SearchParam.Builder(collectionName)
.withFloatVectors(vectorsToSearch)
.withTopK(topK)
.withParamsInJson(searchParamsJson.toString())
.build();
MilvusClient client = milvusConnector.getClient();
SearchResponse searchResponse = client.search(searchParam);
return searchResponse;
}
public SearchResponse search(
MilvusClient client,
String collectionName,
int nprobe,
long topK,
List<List<Float>> vectorsToSearch) {
// 索引类型不同参数也可能不同查询文档选择最优参数
JsonObject searchParamsJson = new JsonObject();
searchParamsJson.addProperty("nprobe", nprobe);
SearchParam searchParam =
new SearchParam.Builder(collectionName)
.withFloatVectors(vectorsToSearch)
.withTopK(topK)
.withParamsInJson(searchParamsJson.toString())
.build();
SearchResponse searchResponse = client.search(searchParam);
return searchResponse;
}
// 删除向量
public Response deleteVectorsByIds(
MilvusClient client, String collectionName, List<Long> vectorIds) {
Response deleteByIdsResponse = client.deleteEntityByID(collectionName, vectorIds);
// Flush, 使删除数据生效
Response flushResponse = client.flush(collectionName);
return deleteByIdsResponse;
// 是否存在分区
public R<Boolean> hasPartition(MilvusClient milvusClient, String partitionName) {
System.out.println("========== hasPartition() ==========");
R<Boolean> response = milvusClient.hasPartition(HasPartitionParam.newBuilder()
.withCollectionName(collectionName)
.withPartitionName(partitionName)
.build());
return response;
}
// 创建 index
public Response createIndex(MilvusClient client, String collectionName) {
// 索引类型在配置页面设置 IndexType.IVF_SQ8
final IndexType indexType = IndexType.IVFLAT;
// 每种索引有自己的可选参数 - 在配置页面设置
JsonObject indexParamsJson = new JsonObject();
indexParamsJson.addProperty("nlist", Integer.parseInt(nlist));
Index index =
new Index.Builder(collectionName, indexType)
.withParamsInJson(indexParamsJson.toString())
.build();
public R<RpcStatus> createIndex(MilvusClient milvusClient) {
System.out.println("========== createIndex() ==========");
String INDEX_PARAM = "{\"nlist\":" + nlist + "}";
Response createIndexResponse = client.createIndex(index);
return createIndexResponse;
IndexType INDEX_TYPE;
switch (indexType.toUpperCase()) {
case "IVF_FLAT":
INDEX_TYPE = IndexType.IVF_FLAT;
break;
case "IVF_SQ8":
INDEX_TYPE = IndexType.IVF_SQ8;
break;
case "IVF_PQ":
INDEX_TYPE = IndexType.IVF_PQ;
break;
case "HNSW":
INDEX_TYPE = IndexType.HNSW;
break;
case "ANNOY":
INDEX_TYPE = IndexType.ANNOY;
break;
case "RHNSW_FLAT":
INDEX_TYPE = IndexType.RHNSW_FLAT;
break;
case "RHNSW_PQ":
INDEX_TYPE = IndexType.RHNSW_PQ;
break;
case "RHNSW_SQ":
INDEX_TYPE = IndexType.RHNSW_SQ;
break;
case "BIN_IVF_FLAT":
INDEX_TYPE = IndexType.BIN_IVF_FLAT;
break;
default:
INDEX_TYPE = IndexType.IVF_FLAT;
break;
}
public Response createIndex(String collectionName) {
// 索引类型在配置页面设置 IndexType.IVF_SQ8
final IndexType indexType = IndexType.IVFLAT;
// 每种索引有自己的可选参数 - 在配置页面设置
JsonObject indexParamsJson = new JsonObject();
indexParamsJson.addProperty("nlist", Integer.parseInt(nlist));
Index index =
new Index.Builder(collectionName, indexType)
.withParamsInJson(indexParamsJson.toString())
.build();
MilvusClient client = milvusConnector.getClient();
Response createIndexResponse = client.createIndex(index);
return createIndexResponse;
MetricType METRIC_TYPE;
MetricType metricTypeEnum = MetricType.valueOf(metricType.toUpperCase());
switch (metricTypeEnum) {
case L2:
METRIC_TYPE = MetricType.L2;
break;
case IP:
METRIC_TYPE = MetricType.IP;
break;
case HAMMING:
METRIC_TYPE = MetricType.HAMMING;
break;
case JACCARD:
METRIC_TYPE = MetricType.JACCARD;
break;
case TANIMOTO:
METRIC_TYPE = MetricType.TANIMOTO;
break;
case SUBSTRUCTURE:
METRIC_TYPE = MetricType.SUBSTRUCTURE;
break;
case SUPERSTRUCTURE:
METRIC_TYPE = MetricType.SUPERSTRUCTURE;
break;
default:
METRIC_TYPE = MetricType.L2;
break;
}
// 查看索引信息
public GetIndexInfoResponse getIndexInfo(MilvusClient client, String collectionName) {
GetIndexInfoResponse getIndexInfoResponse = client.getIndexInfo(collectionName);
// System.out.format("索引信息: %s\n",search.service.SearchServiceImpl.getIndexInfo(client,
// collectionName).getIndex().toString());
return getIndexInfoResponse;
R<RpcStatus> response = milvusClient.createIndex(CreateIndexParam.newBuilder()
.withCollectionName(collectionName)
.withFieldName(VECTOR_FIELD)
.withIndexType(INDEX_TYPE)
.withMetricType(METRIC_TYPE)
.withExtraParam(INDEX_PARAM)
.withSyncMode(Boolean.TRUE)
.build());
return response;
}
// 删除 index
public Response dropIndex(MilvusClient client, String collectionName) {
Response dropIndexResponse = client.dropIndex(collectionName);
return dropIndexResponse;
public R<RpcStatus> dropIndex(MilvusClient milvusClient) {
System.out.println("========== dropIndex() ==========");
R<RpcStatus> response = milvusClient.dropIndex(DropIndexParam.newBuilder()
.withCollectionName(collectionName)
.withFieldName(VECTOR_FIELD)
.build());
return response;
}
// 压缩 collection
public Response compactCollection(MilvusClient client, String collectionName) {
// 压缩 collection, 从磁盘抹除删除的数据并在后台重建索引如果压缩后的数据比indexFileSize还要大
// 在主动压缩前数据只是软删除
Response compactResponse = client.compact(collectionName);
return compactResponse;
// 插入向量
public R<MutationResult> insert(List<Long> vectorIds, List<List<Float>> vectors) {
System.out.println("========== insert() ==========");
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient milvusClient = connPool.getConnection();
try {
List<InsertParam.Field> fields = new ArrayList<>();
fields.add(new InsertParam.Field(ID_FIELD, DataType.Int64, vectorIds));
fields.add(new InsertParam.Field(VECTOR_FIELD, DataType.FloatVector, vectors));
InsertParam insertParam = InsertParam.newBuilder()
.withCollectionName(collectionName)
.withPartitionName(partitionName)
.withFields(fields)
.build();
R<MutationResult> response = milvusClient.insert(insertParam);
return response;
} finally {
returnConnection(connPool, milvusClient);
}
}
// 检查 collection 中是否有 partition "tag"
public HasPartitionResponse hasPartition(MilvusClient client, String collectionName, String tag) {
HasPartitionResponse hasPartitionResponse = client.hasPartition(collectionName, tag);
return hasPartitionResponse;
// 查询向量
// queryExpr = ID_FIELD + " == 60";
public R<QueryResults> query(String expr) {
System.out.println("========== query() ==========");
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient milvusClient = connPool.getConnection();
try {
List<String> fields = Arrays.asList(ID_FIELD);
QueryParam test = QueryParam.newBuilder()
.withCollectionName(collectionName)
.withExpr(expr)
.withOutFields(fields)
.build();
R<QueryResults> response = milvusClient.query(test);
QueryResultsWrapper wrapper = new QueryResultsWrapper(response.getData());
System.out.println(ID_FIELD + ":" + wrapper.getFieldWrapper(ID_FIELD).getFieldData().toString());
System.out.println("Query row count: " + wrapper.getFieldWrapper(ID_FIELD).getRowCount());
return response;
} finally {
returnConnection(connPool, milvusClient);
}
}
// 搜索向量
public R<SearchResults> search(Integer topK, List<List<Float>> vectorsToSearch) {
System.out.println("========== searchImage() ==========");
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient milvusClient = connPool.getConnection();
try {
String SEARCH_PARAM = "{\"nprobe\":" + nprobe + "}";
List<String> outFields = Arrays.asList(ID_FIELD);
SearchParam searchParam = SearchParam.newBuilder()
.withCollectionName(collectionName)
.withMetricType(MetricType.L2)
.withOutFields(outFields)
.withTopK(topK)
.withVectors(vectorsToSearch)
.withVectorFieldName(VECTOR_FIELD)
// .withExpr(expr)
.withParams(SEARCH_PARAM)
.build();
R<SearchResults> response = milvusClient.search(searchParam);
SearchResultsWrapper wrapper = new SearchResultsWrapper(response.getData().getResults());
for (int i = 0; i < vectorsToSearch.size(); ++i) {
System.out.println("Search result of No." + i);
List<SearchResultsWrapper.IDScore> scores = wrapper.getIDScore(i);
System.out.println(scores);
System.out.println("Output field data for No." + i);
}
return response;
} finally {
returnConnection(connPool, milvusClient);
}
}
// 删除向量
// String deleteExpr = ID_FIELD + " in " + deleteIds.toString();
public R<MutationResult> delete(String expr) {
System.out.println("========== delete() ==========");
ConnectionPool connPool = this.getConnectionPool(false);
MilvusClient milvusClient = connPool.getConnection();
try {
DeleteParam build = DeleteParam.newBuilder()
.withCollectionName(collectionName)
.withPartitionName(partitionName)
.withExpr(expr)
.build();
R<MutationResult> response = milvusClient.delete(build);
return response;
} finally {
returnConnection(connPool, milvusClient);
}
}
}

View File

@ -1,6 +1,14 @@
package me.aias.tools;
import io.milvus.client.*;
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.R;
import io.milvus.param.RpcStatus;
import io.milvus.param.collection.DropCollectionParam;
import io.milvus.param.collection.HasCollectionParam;
import io.milvus.param.collection.ReleaseCollectionParam;
import io.milvus.param.index.DropIndexParam;
import io.milvus.param.partition.DropPartitionParam;
/**
* 搜索引擎初始化工具
@ -9,49 +17,92 @@ import io.milvus.client.*;
* @date 2021-12-12
**/
public class MilvusInit {
private static final MilvusServiceClient milvusClient;
public static void main(String[] args) throws InterruptedException {
static {
ConnectParam connectParam = ConnectParam.newBuilder()
.withHost("127.0.0.1")
.withPort(19530)
.build();
milvusClient = new MilvusServiceClient(connectParam);
}
String host = "127.0.0.1";
int port = 19530;
final String collectionName = "voiceprint"; // collection name
private static final String COLLECTION_NAME = "voiceprint";// collection name
private static final String VECTOR_FIELD = "feature";
MilvusClient client = new MilvusGrpcClient();
// Connect to Milvus server
ConnectParam connectParam = new ConnectParam.Builder().withHost(host).withPort(port).build();
public static void main(String[] args) {
try {
Response connectResponse = client.connect(connectParam);
} catch (ConnectFailedException e) {
// 检查 collection 是否存在不存在会抛异常
hasCollection();
releaseCollection();
// dropPartition("p1");
dropIndex();
dropCollection();
} catch (Exception e) {
e.printStackTrace();
}
// 检查 collection 是否存在
HasCollectionResponse hasCollection = hasCollection(client, collectionName);
if (hasCollection.hasCollection()) {
dropIndex(client, collectionName);
dropCollection(client, collectionName);
}
// 关闭 Milvus 连接
client.disconnect();
milvusClient.close();
}
// 检查是否存在 collection
public static HasCollectionResponse hasCollection(MilvusClient client, String collectionName) {
HasCollectionResponse response = client.hasCollection(collectionName);
private static R<Boolean> hasCollection() {
System.out.println("========== hasCollection() ==========");
R<Boolean> response = milvusClient.hasCollection(HasCollectionParam.newBuilder()
.withCollectionName(COLLECTION_NAME)
.build());
handleResponseStatus(response);
System.out.println(response);
return response;
}
// 删除 collection
public static Response dropCollection(MilvusClient client, String collectionName) {
// Drop collection
Response dropCollectionResponse = client.dropCollection(collectionName);
return dropCollectionResponse;
private static R<RpcStatus> dropCollection() {
System.out.println("========== dropCollection() ==========");
R<RpcStatus> response = milvusClient.dropCollection(DropCollectionParam.newBuilder()
.withCollectionName(COLLECTION_NAME)
.build());
System.out.println(response);
return response;
}
private static R<RpcStatus> releaseCollection() {
System.out.println("========== releaseCollection() ==========");
R<RpcStatus> response = milvusClient.releaseCollection(ReleaseCollectionParam.newBuilder()
.withCollectionName(COLLECTION_NAME)
.build());
handleResponseStatus(response);
System.out.println(response);
return response;
}
// 删除 index
public static Response dropIndex(MilvusClient client, String collectionName) {
Response dropIndexResponse = client.dropIndex(collectionName);
return dropIndexResponse;
private static R<RpcStatus> dropIndex() {
System.out.println("========== dropIndex() ==========");
R<RpcStatus> response = milvusClient.dropIndex(DropIndexParam.newBuilder()
.withCollectionName(COLLECTION_NAME)
.withFieldName(VECTOR_FIELD)
.build());
handleResponseStatus(response);
System.out.println(response);
return response;
}
private static R<RpcStatus> dropPartition(String partitionName) {
System.out.println("========== dropPartition() ==========");
R<RpcStatus> response = milvusClient.dropPartition(DropPartitionParam.newBuilder()
.withCollectionName(COLLECTION_NAME)
.withPartitionName(partitionName)
.build());
handleResponseStatus(response);
System.out.println(response);
return response;
}
private static void handleResponseStatus(R<?> r) {
if (r.getStatus() != R.Status.Success.getCode()) {
throw new RuntimeException(r.getMessage());
}
}
}

View File

@ -21,8 +21,8 @@ file:
path: /home/aias/file/
rootPath: /home/aias/file/audio_root/ #压缩包解压缩文件夹
windows:
path: file:///D:/aias/file/
rootPath: file:///D:/aias/file/audio_root/ #压缩包解压缩文件夹
path: file:/D:/aias/file/
rootPath: file:/D:/aias/file/audio_root/ #压缩包解压缩文件夹
# 文件大小 /M
maxSize: 3000
@ -33,12 +33,29 @@ audio:
# path: /Users/calvin/Documents/audio_root/ #文件存放文件夹
baseUrl: http://127.0.0.1:8089/files/
# 向量引擎 Milvus
# Vector Engine - Milvus
search:
host: 127.0.0.1
port: 19530
indexFileSize: 1024 # maximum size (in MB) of each index file
# https://milvus.io/cn/docs/v2.0.0/build_index.md
# https://milvus.io/cn/docs/v2.0.0/metric.md#floating
# For floating point vectors:
# IVF_FLAT
# IVF_SQ8
# IVF_PQ
# HNSW
# ANNOY
# RHNSW_FLAT
# RHNSW_PQ
# RHNSW_SQ
# For binary vectors:
# BIN_IVF_FLAT
indexType: IVF_FLAT
metricType: L2
nprobe: 256
nlist: 16384
dimension: 512 # dimension of each vector
collectionName: voiceprint #collection name
partitionName: p1

View File

@ -1,332 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/java" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.11.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.28" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.1.10.RELEASE" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.23" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.9.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.9" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.9.9" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.26" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.26" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.26" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.17.Final" level="project" />
<orderEntry type="library" name="Maven: javax.validation:validation-api:2.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.3.Final" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.1.9.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.1.9.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.1.9.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.1.9.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.12" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.11.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:2.23.4" level="project" />
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.9.16" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.9.16" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.6" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.1.10.RELEASE" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.6.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.1.2.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.1.10.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.28" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.15.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.11.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.logging.log4j:log4j-core:2.11.2" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.5" level="project" />
<orderEntry type="library" name="Maven: ai.djl:api:0.14.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.21" level="project" />
<orderEntry type="library" name="Maven: ai.djl:basicdataset:0.14.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-csv:1.8" level="project" />
<orderEntry type="library" name="Maven: ai.djl:model-zoo:0.14.0" level="project" />
<orderEntry type="library" name="Maven: ai.djl.pytorch:pytorch-engine:0.14.0" level="project" />
<orderEntry type="library" name="Maven: ai.djl.pytorch:pytorch-native-auto:1.9.1" level="project" />
<orderEntry type="library" name="Maven: ai.djl.paddlepaddle:paddlepaddle-model-zoo:0.14.0" level="project" />
<orderEntry type="library" name="Maven: ai.djl.paddlepaddle:paddlepaddle-engine:0.14.0" level="project" />
<orderEntry type="library" name="Maven: ai.djl.paddlepaddle:paddlepaddle-native-auto:2.0.2" level="project" />
<orderEntry type="library" name="Maven: io.milvus:milvus-sdk-java:0.8.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.plugins:maven-gpg-plugin:1.6" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-plugin-api:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-project:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-settings:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-profile:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-artifact-manager:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.wagon:wagon-provider-api:1.0-beta-6" level="project" />
<orderEntry type="library" name="Maven: backport-util-concurrent:backport-util-concurrent:3.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-plugin-registry:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.plexus:plexus-interpolation:1.11" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.plexus:plexus-container-default:1.0-alpha-9-stable-1" level="project" />
<orderEntry type="library" name="Maven: classworlds:classworlds:1.1-alpha-2" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-artifact:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-repository-metadata:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven:maven-model:2.2.1" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.plexus:plexus-utils:3.0.20" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.plexus:plexus-sec-dispatcher:1.4" level="project" />
<orderEntry type="library" name="Maven: org.sonatype.plexus:plexus-cipher:1.4" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: io.grpc:grpc-netty-shaded:1.27.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: io.grpc:grpc-core:1.27.2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: com.google.android:annotations:4.1.1.4" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: io.perfmark:perfmark-api:0.19.0" level="project" />
<orderEntry type="library" name="Maven: io.grpc:grpc-protobuf:1.27.2" level="project" />
<orderEntry type="library" name="Maven: io.grpc:grpc-api:1.27.2" level="project" />
<orderEntry type="library" name="Maven: io.grpc:grpc-context:1.27.2" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.18" level="project" />
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:3.11.0" level="project" />
<orderEntry type="library" name="Maven: com.google.api.grpc:proto-google-common-protos:1.17.0" level="project" />
<orderEntry type="library" name="Maven: io.grpc:grpc-protobuf-lite:1.27.2" level="project" />
<orderEntry type="library" name="Maven: io.grpc:grpc-stub:1.27.2" level="project" />
<orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java-util:3.11.0" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-text:1.6" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.4" level="project" />
<orderEntry type="library" name="Maven: org.json:json:20190722" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacv-platform:1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacv:1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:javacpp:1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:0.2.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:0.200-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas-platform:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-arm:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-arm64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-x86:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:android-x86_64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:ios-arm64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:ios-x86_64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-x86:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-x86_64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-armhf:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-arm64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:linux-ppc64le:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:macosx-x86_64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:windows-x86:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:openblas:windows-x86_64:0.3.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv-platform:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-arm:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-arm64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-x86:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:android-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:ios-arm64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:ios-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-x86:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-armhf:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-arm64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:linux-ppc64le:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:macosx-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:windows-x86:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:opencv:windows-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg-platform:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-arm:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-arm64:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-x86:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:android-x86_64:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-x86:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-x86_64:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-armhf:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-arm64:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:linux-ppc64le:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:macosx-x86_64:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:windows-x86:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:ffmpeg:windows-x86_64:4.1.3-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture-platform:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-x86:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-x86_64:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-armhf:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:linux-arm64:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:windows-x86:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flycapture:windows-x86_64:2.13.3.31-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394-platform:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-x86:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-x86_64:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-armhf:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-arm64:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:linux-ppc64le:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:macosx-x86_64:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:windows-x86:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libdc1394:windows-x86_64:2.2.6-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect-platform:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-x86:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-x86_64:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-armhf:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-arm64:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:linux-ppc64le:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:macosx-x86_64:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:windows-x86:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect:windows-x86_64:0.5.7-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2-platform:0.2.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:linux-x86:0.2.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:linux-x86_64:0.2.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:macosx-x86_64:0.2.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:libfreenect2:windows-x86_64:0.2.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense-platform:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-x86:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:linux-x86_64:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:macosx-x86_64:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:windows-x86:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:librealsense:windows-x86_64:1.12.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput-platform:0.200-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:windows-x86:0.200-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:videoinput:windows-x86_64:0.200-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus-platform:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-arm:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-arm64:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-x86:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:android-x86_64:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-x86:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-x86_64:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-armhf:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-arm64:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:linux-ppc64le:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:macosx-x86_64:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:windows-x86:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:artoolkitplus:windows-x86_64:2.3.1-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark-platform:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-arm:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-arm64:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-x86:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:android-x86_64:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-x86:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-x86_64:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-armhf:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-arm64:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:linux-ppc64le:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:macosx-x86_64:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:windows-x86:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:flandmark:windows-x86_64:1.07-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica-platform:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-arm:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-arm64:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-x86:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:android-x86_64:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-x86:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-x86_64:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-armhf:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-arm64:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:linux-ppc64le:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:macosx-x86_64:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:windows-x86:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:leptonica:windows-x86_64:1.78.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract-platform:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-arm:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-arm64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-x86:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:android-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-x86:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-armhf:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-arm64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:linux-ppc64le:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:macosx-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:windows-x86:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.bytedeco:tesseract:windows-x86_64:4.1.0-1.5.1" level="project" />
<orderEntry type="library" name="Maven: net.java.dev.jna:jna:5.6.0" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.10" level="project" />
<orderEntry type="library" name="Maven: com.google.http-client:google-http-client:1.19.0" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.10" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.12" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.4" level="project" />
<orderEntry type="module-library">
<library name="Maven: jlibrosa:jlibrosa:1.1.8-SNAPSHOT">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/jlibrosa-1.1.8-SNAPSHOT.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:tritonus-share:0.3.7.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:tritonus-all:0.3.7.2" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:jlayer:1.0.1.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:mp3spi:1.9.5.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:jorbis:0.0.17.4" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:vorbisspi:1.0.3.3" level="project" />
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:basicplayer:3.0.0.0" level="project" />
<orderEntry type="library" name="Maven: fr.delthas:javamp3:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.orctom:vad4j:1.0" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.70" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger2:2.9.2" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spi:2.9.2" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-core:2.9.2" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-schema:2.9.2" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger-common:2.9.2" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-web:2.9.2" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:20.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-core:1.2.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-metadata:1.2.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mapstruct:mapstruct:1.2.0.Final" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger-ui:2.9.2" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-annotations:1.5.21" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-models:1.5.21" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.3.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.ant:ant:1.9.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.ant:ant-launcher:1.9.4" level="project" />
<orderEntry type="library" name="Maven: eu.bitwalker:UserAgentUtils:1.21" level="project" />
</component>
</module>