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

news2024/11/14 1:29:26

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 history
    for (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 为0
    int 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;  // 更新索引 i
                    prefix = "##";  // 更新前缀为 "##"
                    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 wordpiece
    for (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 prompt
    std::string prompt = "你 好"; // "this is an audio";
    //std::string prompt = "this is an audio"; // "this is an audio";

    // paths
    std::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的分词过程。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1421304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

File、IO流(一)

File、IO流 File File是Java.io包下的类&#xff0c;File类的对象&#xff0c;用于代表当前操作系统的文件&#xff08;可以是文件、或者文件夹&#xff09;。 注意&#xff1a;File类只能对文件本身进行操作&#xff0c;不能读写文件里面存储的数据。 IO流 用于读写数据的&…

Unity3d实现简单的战斗

使用u3d实现一个简单的战斗demo&#xff0c;记下学到的知识点&#xff0c;以备后查。 1.判断是否点中指定物体 if (Input.GetMouseButton(0)) {Ray ray Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out RaycastHit hit)){//坐标转换Vector…

数据结构—栈实现后缀表达式的计算

后缀表达式计算 过程分析 中缀表达式 &#xff08;15&#xff09;*3 > 后缀表达式 153* (可参考这篇文章&#xff1a;中缀转后缀) 第一步&#xff1a;我们从左至右扫描 后缀表达式(已经存放在一个字符数组中)&#xff0c;遇到第一个数字字符 ‘1’ 放入栈中第二步&#xf…

springboot本地测试

文章目录 本地测试引入依赖进入StudentMapper右键点击生成 项目结构 本地测试 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope> </d…

[Tcpdump] 网络抓包工具使用教程

往期回顾 海思 tcpdump 移植开发详解海思 tcpdump 移植开发详解 前言 上一节&#xff0c;我们已经讲解了在海思平台如何基于静态库生成 tcpdump 工具&#xff0c;本节将作为上一节的拓展内容。 一、tcpdump 简介 「 tcpdump 」是一款强大的网络抓包工具&#xff0c;它基于…

Redis学习——高级篇⑥

Redis学习——高级篇⑥ Redis7高级之简单实现布隆过滤器BloomFilter &#xff08;七&#xff09; 7 布隆过滤器1. 是什么2.能干嘛3.实现原理和数据结构4.使用三步骤5.尝试手写简单的布隆过滤器&#xff0c;结合bitmap1.整体架构2.步骤设计3 springboot redis mybatis布…

微信扫码登录流程

微信官方文档使用 搜索“微信开放平台”点击导航栏的“资源中心”点击“网站应用”下的“微信登录功能”地址微信扫码登录是基于OAuth2的&#xff0c;所以需要第三方应用&#xff08;就是实现微信扫码登录的应用&#xff09;成为微信的客户端&#xff0c;获取AppId和AppSecret…

PMP备考笔记:模拟考试知识点总结

1. 答题思路&#xff1a;优先看问题&#xff0c;可节省时间。 2. 考试就按照考试的套路来做&#xff0c;不要过多考虑。 开发团队只专注当前冲刺目标&#xff0c;产品负责人对PB排优先级。 收集需求工具-原型法&#xff1a;能够让用户提前体验&#xff0c;减少返工的风险。 …

基于ldap实现登录认证

最近开发的应用需要外协人员实现登录认证&#xff0c;外协人员的密码等信息已经录入到ldap, 需要连接ldap进行登录认证。下面先介绍一下登录的网络旅程图。 一.nginx实现AES加密 nginx请求处理入口&#xff08;前端请求为json格式&#xff09; location /aes {default_type te…

解锁Web3:数字未来的大门

随着科技的不断推进&#xff0c;我们正站在数字时代的新门槛上。Web3&#xff0c;作为互联网的下一个演进阶段&#xff0c;正在逐渐揭开数字未来的面纱。本文将深入探讨Web3的本质、对社会的影响以及在数字时代中所扮演的关键角色。 什么是Web3&#xff1f; Web3是互联网发展的…

数据分析讲课笔记02:科学计算库Numpy

文章目录 零、学习目标一、认识NumPy数组对象&#xff08;一&#xff09;N维数组对象ndarray&#xff08;二&#xff09;ndarray对象重要的属性&#xff08;三&#xff09;ndarray数组案例演示 二、创建NumPy数组&#xff08;一&#xff09;采用array()函数创建数组&#xff08…

父元素flex:1 高度却被子元素撑开的问题

问题 当父元素设置了flex: 1; 的情况下&#xff0c;想在其中子元素超出父元素高度的情况下&#xff0c;产生滚动条&#xff0c;在父元素区域滚动。由于子元素高度不固定&#xff0c;故父元素设置为display: flex; flex-direction: column; 子元素设置flex: 1; overflow: auto;…

select的change方法如何传递多个参数

element-ui中select的change方法传递多个参数 element-ui中的select&#xff0c;checkbox等组件的change方法的回调函数只有当前选择的val&#xff0c;如果想再传入自定义参数怎么办&#xff1f; 不能够传入自定义的参数&#xff0c;在进行某些操作时&#xff0c;会比较困难&…

【Java程序设计】【C00179】基于SSM的电影在线购票管理系统(论文+PPT)

基于SSM的电影在线购票管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的电影在线购票管理系统 本系统分为前台用户和后台管理员2个功能模块。 前台用户&#xff1a;当游客打开系统的网址后&#xff0c;首先看到…

【开源】基于JAVA+Vue+SpringBoot的用户画像活动推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 兴趣标签模块2.3 活动档案模块2.4 活动报名模块2.5 活动留言模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 数据流程设计3.4 E-R图设计 四、系统展示五、核心代码5.1 查询兴趣标签5.2 查询活动推荐…

一张图搞清楚HTTP状态码

HTTP状态码的基本概念 在客户端和服务器连接交互的时候&#xff0c;一般是客户端先给服务器发送请求&#xff0c;然后服务器返回结果。客户端和服务器之间的交互非常频繁&#xff0c;涉及到很多种不同类型的操作&#xff0c;大多数的时候服务器能成功返回结果&#xff0c;有时…

Vue3使用setup-extend简化组件名写法

如果我们在Vue3中要使用setup的语法糖&#xff0c;就需要使用两个script标签&#xff0c;一个用于设置组件的name属性&#xff0c;一个用于编写setup中的代码。如下&#xff1a; 但是我们有觉得光是因为一个name属性就多写一个script标签有点麻烦了。 因此我们可以使用插件来进…

[每日一题] 01.30

文章目录 数列求和质数口袋奇怪数求和 数列求和 n int(input()) print(sum([i for i in range(1,n 1)]))质数口袋 n int(input()) i 2 sum 0 count 0 while n - i > sum:flag Truefor j in range(2,i): # 判断i是否为素数if i % j 0:flag Falsebreakif flag:sum i…

如何解决 DNS 解析错误(DNS_PROBE_FINISHED_NXDOMAIN)问题

如何解决 DNS 解析错误&#xff08;DNS_PROBE_FINISHED_NXDOMAIN&#xff09;问题 导语&#xff1a; 当你在访问网站时遇到 DNS 解析错误&#xff08;DNS_PROBE_FINISHED_NXDOMAIN&#xff09;时&#xff0c;可能是由于本地 DNS 缓存导致的问题。这里介绍一种简单且常见的解决…

MongoDB安装以及卸载

查询id&#xff1a; docker ps [rootlocalhost ~]# docker stop c7a8c4ac9346 c7a8c4ac9346 [rootlocalhost ~]# docker rm c7a8c4ac9346 c7a8c4ac9346 [rootlocalhost ~]# docker rmi mongo sudo docker pull mongo:4.4 sudo docker images 卸载旧的 sudo docker stop mong…