坐在上海的公交车上,我有时会遇到这样的懊恼:稍一分神,没能听见普通话报站,支棱起耳朵,却听不懂沪语报站。为了解决这个问题,我决定——学习沪语?No, 作为一名数据工程师,我索性搭建了一个方言翻译器,帮忙大家轻松听懂中央方言,再也不会错过公交车站。

在本次的我的项目中,我会手把手教你应用 Milvus 搭建方言翻译器。通过这个我的项目,你能播种:

  • 相熟开源数据集,在日常的模型训练中利用这些数据集
  • 亲自动手搭建 Demo,真正解决理论生存场景中问题
  • 学会应用 Milvus 后,还有更多的能够联合 Milvus 的利用场景等着你去发现
  • 如果你是首次理解 Milvus 和 MagicHub 的小伙伴,咱们为你筹备了一个简短的介绍:

Milvus
Milvus 是基于 FAISS、Annoy、HNSW 等向量搜寻库构建,外围是解决浓密向量类似度检索的问题。最近, Milvus 2.0 版本曾经公布了,在向量检索库的根底上,Milvus 反对了数据分区分片、长久化、增量数据摄取、标量向量混合查问、Time Travel 等性能,同时大幅优化了向量检索的性能。举荐用户应用 Kubernetes 部署 Milvus ,以获得最佳的可用性和弹性。

MagicHub
MagicHub.com 是爱数智慧公布的一个开源社区。爱数智慧为从事语音辨认、语音合成、自然语言了解等人工智能畛域研发与利用钻研的企业、科研机构提供数据服务。MagicHub 开源数据笼罩多个场景、行业、语种。自 2021 年 4 月 15 日正式公布以来,曾经笼罩 3000+ 寰球开发者,累计下载超过 15 万小时数据集。目前开源 50 多种用于人工智能训练/测试的数据集,包含方言和小语种。数据集品种蕴含 NLP、ASR、TTS 数据集和 LEX 发音词典等。MagicHub 帮忙 AI 开发者疾速找到适宜本人模型的数据集,用开源数据减速翻新。

1. 数据筹备

本我的项目中,咱们抉择了 MagicHub 社区中提供的上海话数据集(起源详见文末链接[1]),你也能够依据本人的须要应用其余方言的数据集。

上海话朗诵音频数据集-日常用语(此数据集蕴含了 4.23 个小时的上海话朗诵音频和转写文本,有 4,819 条由 10 名谈话人提供的日常用语语料。)
录音环境 : 室内
录音语料 : 日常书面语句子
文件格式 : WAV, TXT
语音参数 : 16 kHz/16 bits
录音设施 : 手机
实用畛域 : 语音辨认
版权所有者 : 爱数智慧

下载数据集,解压实现后能够看到这几个文件:WAV - 音频文件夹,README.txt - 数据集版权介绍文件,SPKINFO.txt - 每个音频的录音设施,性别,年龄,区域,录音频道的介绍文件,UTTRANSINFO.txt - 音频的文本内容,蕴含普通话和上海话。这里咱们次要用到的是音频文本内容普通话局部。这里将 UTTRANSINFO.txt 文件转成了 CSV 的模式,有利于咱们后续数据处理。

def loadDataSet(test_dir):    f = open(test_dir,'r',encoding='utf-8')    fname ='ts.csv'    with open(fname,'w') as fine:        for line in f.readlines():            line1 =line.split()            PROMPT=line1[3]            linew = PROMPT+"\n"            fine.write(linew)

2. 音频检索

音频搜寻我的项目中,首先,将音频文件用 Panns-Inference 模型转成特征向量存储到 Milvus 2.0,并返回对应的 ID;接着,在 MySQL 数据库中存储 ID 、音频文件的门路 ,以及文本内容对应关系;随后,在 Milvus 2.0 中检索得出与其类似的音频文件,并返回最类似的前 N 个后果;最初,依据返回的 ID 后果,在数据库中搜寻到对应的音频文件和文本内容。

应用 Milvus 2.0 最新音频检索我的项目,只须要批改大量代码,就能够对上海话音频进行检索,返回上海话的音频和音频内容。

上面是音频检索我的项目中须要批改的代码,在 load.py 中读取 CSV 的数据

def do_load(table_name, audio_dir,text_dir, model, milvus_client, mysql_cli):    if not table_name:        table_name = DEFAULT_TABLE    vectors, names = extract_features(audio_dir, model)    ids = milvus_client.insert(table_name, vectors)    loadDataSet(text_dir)    data = pd.read_csv("ts.csv")    text = data['PROMPT'].tolist()    milvus_client.create_index(table_name)    mysql_cli.create_mysql_table(table_name)    mysql_cli.load_data_to_mysql(table_name, format_data(ids, names,text))    return len(ids)

在 search.py 中须要批改以下的代码局部:

def do_search(host,table_name, audio_path, model, milvus_client, mysql_cli):    try:        if not table_name:            table_name = DEFAULT_TABLE        feat = get_audio_embedding(audio_path)        vectors = milvus_client.search_vectors(table_name, [feat], TOP_K)        vids = [str(x.id) for x in vectors[0]]        paths,text = mysql_cli.search_by_milvus_ids(vids, table_name)        distances = [x.distance for x in vectors[0]]        for i in range(len(paths)):             tmp = "http://" + str(host) + "/data?audio_path=" + str(paths[i])             paths[i] = tmp        return vids, paths, distances,text    except Exception as e:        LOGGER.error(" Error with search : {}".format(e))        sys.exit(1)

在 mysql_helpers.py 文件中批改以下代码:

def create_mysql_table(self, table_name):        sql = "create table if not exists " + table_name + "(milvus_id TEXT, audio_path TEXT,text TEXT) ENGINE=InnoDB DEFAULT CHARSET=utf8;"        try:            self.cursor.execute(sql)            LOGGER.debug("MYSQL create table: {} with sql: {}".format(table_name, sql))        except Exception as e:            LOGGER.error("MYSQL ERROR: {} with sql: {}".format(e, sql))            sys.exit(1)def load_data_to_mysql(self, table_name, data):        sql = "insert into " + table_name + " (milvus_id,audio_path,text) values (%s,%s,%s);"        try:            self.cursor.executemany(sql, data)            self.conn.commit()            LOGGER.debug("MYSQL loads data to table: {} successfully".format(table_name))        except Exception as e:            LOGGER.error("MYSQL ERROR: {} with sql: {}".format(e, sql))            sys.exit(1)def search_by_milvus_ids(self, ids, table_name):        str_ids = str(ids).replace('[', '').replace(']', '')        sql = "select * from " + table_name + " where milvus_id in (" + str_ids + ") order by field (milvus_id," + str_ids + ");"        try:            self.cursor.execute(sql)            results = self.cursor.fetchall()            results_path=[res[1] for res in results]            results_text=[res[2] for res in results]            LOGGER.debug("MYSQL search by milvus id.")            return results_path,results_text        except Exception as e:            LOGGER.error("MYSQL ERROR: {} with sql: {}".format(e, sql))            sys.exit(1)

以及批改相干的接口,在 main.py 中批改以下代码:

class Item(BaseModel):    Table: Optional[str] = None    File:str    Text:str@app.post('/audio/load')async def load_audios(item: Item):    # Insert all the audio files under the file path to Milvus/MySQL    try:        total_num = do_load(item.Table, item.File,item.Text,MODEL, MILVUS_CLI, MYSQL_CLI)        LOGGER.info("Successfully loaded data, total count: {}".format(total_num))        return {'status': True, 'msg': "Successfully loaded data!"}    except Exception as e:        LOGGER.error(e)        return {'status': False, 'msg': e}, 400@app.post('/audio/search')async def search_audio(request: Request,Table: str = None, audio: UploadFile = File(...)):    # Search the uploaded audio in Milvus/MySQL    try:        # Save the upload data to server.        content = await audio.read()        audio_path = os.path.join(UPLOAD_PATH, audio.filename)        with open(audio_path, "wb+") as f:            f.write(content)        host = request.headers['host']        ids, paths,text, distances= do_search(host,Table, audio_path, MODEL, MILVUS_CLI, MYSQL_CLI)        names=[]        names = text        res = dict(zip(paths, zip(names, distances)))        #res = sorted(res.items(), key=lambda item: item[1][1])        LOGGER.info("Successfully searched similar audio!")        return res    except Exception as e:        LOGGER.error(e)        return {'status': False, 'msg': e}, 400

3. 测试运行

当初,批改完上述代码当前,参考 Github 中 Audio_similar_search 的 Readme 文档(起源详见文末链接[2])启动 FastAPI ,从 FastAPI 中验证代码是否胜利运行,在浏览器中输出 localhost:8002/docs 能够看到如图所示 FastAPI 的页面, 在 Load API 中别离输出 Table 的名称,音频文件的门路,音频对应的文本的门路,而后点击 Excute 的按钮,图中显示数据插入胜利。

而后,在 Search API 中输出对应的 Table 名称和须要检索的音频门路,点击 Excute 按钮进行检索。如下图所示,就能够看到相应的音频和其对应的文本内容了。

最初,感激爱数智慧 MagicHub 提供的开源数据集,让咱们更好地联合模型与 Milvus 进行多个畛域的向量检索。

在这个音频检索我的项目中,咱们也能够应用其余的方言数据集,将数据集通过 AI 模型转成特征向量,联合 Milvus 进行类似检索,就能够把任何你听不懂的方言翻译成普通话啦!

入手玩一把?

源码链接就在下方!


[1] 爱数智慧 MagicHub 开源社区:

https://magichub.com/cn/categ...

[2] 音频检索:

https://github.com/milvus-io/...


作者 | 贾晶晶

Zilliz 数据工程师,毕业于西安交通大学计算机系。退出Zilliz后,次要工作内容为数据预处理、AI模型部署、Milvus 相干技术钻研,以及帮忙社区用户实现利用场景落地。资深动漫粉,对社区沟通超级有急躁,平时比拟关注自然语言解决畛域的钻研。