webassembly003 TTS BARK.CPP-02-bark_tokenize_input(ctx, text);

2024-01-31 09:52

本文主要是介绍webassembly003 TTS BARK.CPP-02-bark_tokenize_input(ctx, text);,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

bark_tokenize_input函数

  • bark是没有语言控制选项的,但是官方的版本无法运行中文
  • bark_tokenize_input会调用bert_tokenize函数,bark_tokenize_input函数对中文分词失效,也就是导致不支持中文的原因。

在这里插入图片描述

void bark_tokenize_input(struct bark_context * ctx, const char * text) {auto & model = ctx->model.text_model;bark_vocab * vocab = &ctx->model.vocab;int32_t block_size = model.hparams.block_size;int32_t max_ctx_size = std::min(block_size, 256);int32_t n_tokens;bark_sequence tokens(max_ctx_size);bert_tokenize(vocab, text, tokens.data(), &n_tokens, max_ctx_size);for (int i = 0; i < (int) tokens.size(); i++)tokens[i] += TEXT_ENCODING_OFFSET;if (n_tokens < max_ctx_size) {for (int i = n_tokens; i < max_ctx_size; i++)tokens[i] = TEXT_PAD_TOKEN;} else if (n_tokens > max_ctx_size) {fprintf(stderr, "%s: input sequence is too long (%d > 256), truncating sequence", __func__, n_tokens);}tokens.resize(max_ctx_size);// semantic historyfor (int i = 0; i < 256; i++)tokens.push_back(SEMANTIC_PAD_TOKEN);tokens.push_back(SEMANTIC_INFER_TOKEN);assert(tokens.size() == 256 + 256 + 1);ctx->tokens = tokens;printf("%s: prompt: '%s'\n", __func__, text);printf("%s: number of tokens in prompt = %zu, first 8 tokens: ", __func__, ctx->tokens.size());for (int i = 0; i < std::min(8, (int) ctx->tokens.size()); i++) {printf("%d ", ctx->tokens[i]);}printf("\n");
}

单词表对象

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 对象创建自vocab.txt
    在这里插入图片描述
    在这里插入图片描述

上一步完成后还会进行wordpiece处理

// apply wordpiece
for (const auto &word : words) {// 如果单词长度为0,跳过if (word.size() == 0)continue;std::string prefix = "";  // 初始化前缀为空字符串int i = 0;                // 初始化索引 i 为0int n = word.size();      // 获取单词长度loop:while (i < n) {// 如果 tokens 数组中的元素达到了最大允许值,跳出循环if (t >= n_max_tokens - 1)break;int j = n;  // 初始化 j 为单词长度while (j > i) {// 尝试找到前缀加上从 i 到 j 的子串在 token_map 中的映射auto it = token_map->find(prefix + word.substr(i, j - i));if (it != token_map->end()) {// 找到映射,将映射的值添加到 tokens 数组中tokens[t++] = it->second;i = j;  // 更新索引 iprefix = "##";  // 更新前缀为 "##"goto loop;  // 跳转到 loop 标签处}--j;  // 递减 j}// 如果 j 等于 i,说明无法找到合适的子串if (j == i) {fprintf(stderr, "%s: unknown token '%s'\n", __func__, word.substr(i, 1).data());prefix = "##";  // 更新前缀为 "##"++i;  // 更新索引 i}}}
}

bert_tokenize函数

  • bert_tokenize函数会将句子tockenlize到ctx中的tokens对象。

在这里插入图片描述

  • 代码实现如下
void bert_tokenize(const bark_vocab * vocab,const char * text,int32_t * tokens,int32_t * n_tokens,int32_t   n_max_tokens) {std::string str = text;std::vector<std::string> words;int32_t t = 0;auto * token_map = &vocab->token_to_id;// split the text into words{str = strip_accents(text);std::string pat = R"([[:punct:]]|[[:alpha:]]+|[[:digit:]]+)";std::regex re(pat);std::smatch m;while (std::regex_search(str, m, re)) {for (std::string x : m)words.push_back(x);str = m.suffix();}}// apply wordpiecefor (const auto &word : words) {if (word.size() == 0)continue;std::string prefix = "";int i = 0;int n = word.size();loop:while (i < n) {if (t >= n_max_tokens - 1)break;int j = n;while (j > i) {auto it = token_map->find(prefix + word.substr(i, j - i));if (it != token_map->end()) {tokens[t++] = it->second;i = j;prefix = "##";goto loop;}--j;}if (j == i) {fprintf(stderr, "%s: unknown token '%s'\n", __func__, word.substr(i, 1).data());prefix = "##";++i;}}}*n_tokens = t;
}

将文本分割成单词

  • 将文本分割成单词的部分使用了如下的正则表达式,其无法支持中文句子的分割,这也导致了无法正确推理运行。
    在这里插入图片描述
	// split the text into words 将文本分割成单词{// 对文本进行去重音符处理str = strip_accents(text);// 定义正则表达式模式,匹配标点符号、字母和数字std::string pat = R"([[:punct:]]|[[:alpha:]]+|[[:digit:]]+)";// 创建正则表达式对象std::regex re(pat);std::smatch m;// 使用正则表达式匹配文本中的单词while (std::regex_search(str, m, re)) {// 将匹配到的单词添加到单词列表for (std::string x : m)words.push_back(x);// 更新文本,排除已匹配的部分str = m.suffix();}}

在这里插入图片描述
在这里插入图片描述

简单修改与运行

// examples/main.cpp
struct bark_params {int32_t n_threads = std::min(4, (int32_t) std::thread::hardware_concurrency());// user promptstd::string prompt = "你 好"; // "this is an audio";//std::string prompt = "this is an audio"; // "this is an audio";// pathsstd::string model_path = "./bark.cpp/ggml_weights";std::string dest_wav_path = "output.wav";int32_t seed = 0;
};
// bark.cpp// split the text into words{str = strip_accents(text);//        std::string pat = R"([[:punct:]]|[[:alpha:]]+|[[:digit:]]+)";
//
//        std::regex re(pat);
//        std::smatch m;
//
//        while (std::regex_search(str, m, re)) {
//            for (std::string x : m)
//                words.push_back(x);
//            str = m.suffix();
//        }// 用空格分割字符串std::istringstream iss(str);std::vector<std::string> words;// 从输入流中读取每个分词并添加到 vector 中do {std::string word;iss >> word;words.push_back(word);} while (iss);// 输出分词结果std::cout << "分词结果:" << std::endl;for (const auto& word : words) {std::cout << word << std::endl;}}
  • ps:这样就能成功运行了,但是,不知道为什么中文推理用的内存比英文多,还有这个分不能通过手动空格实现(即使空格也无法运行,因为许多词没在词表中,还需要参考一下bert的分词过程。)

这篇关于webassembly003 TTS BARK.CPP-02-bark_tokenize_input(ctx, text);的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/663367

相关文章

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

Git 的特点—— Git 学习笔记 02

文章目录 Git 简史Git 的特点直接记录快照,而非差异比较近乎所有操作都是本地执行保证完整性一般只添加数据 参考资料 Git 简史 众所周知,Linux 内核开源项目有着为数众多的参与者。这么多人在世界各地为 Linux 编写代码,那Linux 的代码是如何管理的呢?事实是在 2002 年以前,世界各地的开发者把源代码通过 diff 的方式发给 Linus,然后由 Linus

【Python报错已解决】AttributeError: ‘list‘ object has no attribute ‘text‘

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一:检查属性名2.2 步骤二:访问列表元素的属性 三、其他解决方法四、总结 前言 在Python编程中,属性错误(At

MySQL record 02 part

查看已建数据库的基本信息: show CREATE DATABASE mydb; 注意,是DATABASE 不是 DATABASEs, 命令成功执行后,回显的信息有: CREATE DATABASE mydb /*!40100 DEFAULT CHARACTER SET utf8mb3 / /!80016 DEFAULT ENCRYPTION=‘N’ / CREATE DATABASE myd

GPU 计算 CMPS224 2021 学习笔记 02

并行类型 (1)任务并行 (2)数据并行 CPU & GPU CPU和GPU拥有相互独立的内存空间,需要在两者之间相互传输数据。 (1)分配GPU内存 (2)将CPU上的数据复制到GPU上 (3)在GPU上对数据进行计算操作 (4)将计算结果从GPU复制到CPU上 (5)释放GPU内存 CUDA内存管理API (1)分配内存 cudaErro

类模板中.h和.cpp的实现方法

一般类的声明和实现放在两个文件中,然后在使用该类的主程序代码中,包含相应的头文件".h"就可以了,但是,模板类必须包含该其实现的.cpp文件才行。也就是说,在你的主程序中,将 #include"DouCirLList.h" 替换成 #include"DouCirLList.cpp" 应该就可以了。 在使用类模板技术时,可在.h中实现,也可在.h和.cpp中分开实现,若用.h实

CPP中的hash [more cpp-7]

写在前面 hash 在英文中是弄乱的含义。在编程中,hash是一种数据技术,它把任意类型的数据通过算法,生成一串数字(hash code),实现hash的函数称为哈希函数,又称散列函数,杂凑函数。在CPP中hashcode是一个size_t类型的数字。 你可能会问?把数据弄乱有什么用?为什么我们要把数据映射到一串数字上?这又什么意义吗?我们先看看hash的性质 一般hash性质 唯一性(唯

滚雪球学MyBatis(02):环境搭建

环境搭建 前言 欢迎回到我们的MyBatis系列教程。在上一期中,我们详细介绍了MyBatis的基本概念、特点以及它与其他ORM框架的对比。通过这些内容,大家应该对MyBatis有了初步的了解。今天,我们将从理论走向实践,开始搭建MyBatis的开发环境。了解并掌握环境搭建是使用MyBatis的第一步,也是至关重要的一步。 环境搭建步骤 在开始之前,我们需要准备一些必要的工具和软件,包括J

SAP学习笔记 - 开发02 - BTP实操流程(账号注册,BTP控制台,BTP集成开发环境搭建)

上一章讲了 BAPI的概念,以及如何调用SAP里面的既存BAPI。 SAP学习笔记 - 开发01 - BAPI是什么?通过界面和ABAP代码来调用BAPI-CSDN博客 本章继续讲开发相关的内容,主要就是BTP的实际操作流程,比如账号注册,登录,BTP集成开发环境的搭建这方面。 目录 1,账号注册 2,BTP登录URL 3,如何在BTP上进行开发? 以下是详细内容。 1,账

浙大数据结构:02-线性结构4 Pop Sequence

这道题我们采用数组来模拟堆栈和队列。 简单说一下大致思路,我们用栈来存1234.....,队列来存输入的一组数据,栈与队列进行匹配,相同就pop 机翻 1、条件准备 stk是栈,que是队列。 tt指向的是栈中下标,front指向队头,rear指向队尾。 初始化栈顶为0,队头为0,队尾为-1 #include<iostream>using namespace std;#defi