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 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的分词过程。)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis Plus轻松实现数据库变更全局审计日志

Mybatis Plus轻松实现数据库变更全局审计日志 Mybatis Plus轻松实现数据库变更全局审计日志引言实现审计日志1.创建审计日志表2.创建AuditLogAspect用于记录请求日志4. 保存审计日志 总结 Mybatis Plus轻松实现数据库变更全局审计日志 引言 在日常的业务开发中&#xff0c;监…

MySQL十部曲之一:MySQL概述及手册说明

文章目录 数据库、数据库管理系统以及SQL之间的关系关系型数据库与非关系型数据库MySQL程序系统变量系统状态变量SQL模式MySQL数据目录手册语法约定 数据库、数据库管理系统以及SQL之间的关系 名称说明数据库&#xff08;Database&#xff09;即存储数据的仓库&#xff0c;其本…

07. STP的基本配置

文章目录 一. 初识STP1.1. STP概述1.2. STP的出现1.3. STP的作用1.4. STP的专业术语1.5. BPDU的报文格式1.6. STP的选择原则&#xff08;1&#xff09;选择根桥网桥原则&#xff08;2&#xff09;选择根端口原则 1.7. 端口状态1.8. STP报文类型1.9. STP的收敛时间 二. 实验专题…

数据结构——并查集

1.并查集的定义 并查集其实也是一种树形结构&#xff0c;在使用中通常用森林的方式来表示 并查集的逻辑结构其实就是集合 并查集一般可以通过双亲写法&#xff08;顺序结构&#xff09;来完成&#xff0c;即通过一个数组存储父亲结点的下标 int s[10005]; int main() {for(…

原来服务器这么有用-使用轻量应用服务器搭建专属自己PDF处理工具

原来服务器这么有用-使用轻量应用服务器搭建专属自己PDF处理工具 1、前言 PDF文件是日常办公中经常使用的一种文档格式。最近&#xff0c;青阳面临一个问题&#xff1a;某公司发送过来的文件需要我们进行印章流程&#xff0c;但由于该公司系统在电子文件加盖电子公章后会自动…

万户 ezOFFICE wpsservlet SQL注入漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

10V单通道负载开关

概述 EM5220是一款单通道负载开关&#xff0c;具有可编程上升时间和集成输出放电控制。该设备包含一个P沟道NOSFET&#xff0c;可以通过输入进行操作电压范围为4.5V至10V。开关由接通和断开低电平逻辑输入控制&#xff0c;其能够与GPIO信号接口。设备的可编程上升时间可以减少…

代码随想录刷题笔记-Day15

1. 完全二叉树的的节点个数 222. 完全二叉树的节点个数https://leetcode.cn/problems/count-complete-tree-nodes/ 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没…

课时7:shell基础_shell简介

1.3.1 shell简介 学习目标 这一节&#xff0c;我们从 运维、shell语言、小结 三个方面来学习。 运维 简介 运维是什么&#xff1f;所谓的运维&#xff0c;其实就是公司的内部项目当中的一个技术岗位而已&#xff0c;它主要做的是项目的维护性工作。它所涉及的内容范围非常…

Redhat 8.4 一键安装 Oracle 11GR2 单机版

Oracle 一键安装脚本&#xff0c;演示 Redhat 8.4 一键安装 Oracle 11GR2 单机版过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址&#xff1a;Shell脚本安装Oracle数据库 脚本…

插接母线温度在线监测系统研究与应用

摘要&#xff1a;低压封闭式插接母线是供配电设施的关键部件&#xff0c;安装在生产车间内部高空&#xff0c;不易保养和维护&#xff0c;在安装不良或保养不当时易发生故障。插接点温度的异常变化与母线故障的发生有着密切的关系&#xff0c;以汽车整车制造工厂为例&#xff0…

Unity 策略模式(实例详解)

文章目录 简介示例1&#xff1a;角色攻击行为示例2&#xff1a;游戏内购折扣策略示例3&#xff1a;NPC寻路策略示例4&#xff1a;动画过渡策略示例5&#xff1a;敌人AI决策策略 简介 在Unity中使用策略模式&#xff0c;我们可以将不同的行为或算法封装成独立的类&#xff08;策…

SpringMVC 自动配置

SpringMVC 自动配置 一、WebMvcAutoConfiguration&#xff08;SpringMVC自动配置&#xff09;二、DisPatcherServletAutoConfiguration.class&#xff08;中央调度器自动配置&#xff09;三、WebMvcConfigurationSupport&#xff08;SpringMVC组件配置类&#xff09;四、Servle…

iOS 17.4 苹果公司正在加倍投入人工智能

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

网络隔离场景下访问 Pod 网络

接着上文 VPC网络架构下的网络上数据采集 介绍 考虑一个监控系统&#xff0c;它的数据采集 Agent 是以 daemonset 形式运行在物理机上的&#xff0c;它需要采集 Pod 的各种监控信息。现在很流行的一个监控信息是通过 Prometheus 提供指标信息。 一般来说&#xff0c;daemonset …

低功耗蓝牙(BLE) 和 经典蓝牙(SPP) 的区别

低功耗蓝牙(BLE) vs 经典蓝牙(SPP) 区别项低功耗蓝牙(BLE)经典蓝牙(SPP 串行端口协议)蓝牙版本蓝牙版本 > 4.0&#xff0c;又称蓝牙低功耗、蓝牙智能经典蓝牙2.0 或更早版本&#xff0c;经典配对模式在两台蓝牙设备之间建立虚拟串口数据连接&#xff0c;提供一种简单而直接…

06.VLAN、Trunk和Hybrid配置

文章目录 一. 初识VLAN1.1. VLAN概述1.2. VLAN的优势1.3. VLAN的帧格式1.4. 接口链路类型1.5. 默认VLAN1.6. VLAN划分方式 二. 实验题2.1. 实验1&#xff1a;划分VLAN2.1.1. 实验目的2.1.2. 实验拓扑图2.1.3. 实验步骤&#xff08;1&#xff09;配置PC机的IP地址&#xff08;2&…

stable diffusion学习笔记——文生图(二)

LORA和Embeddings都可以对画面内容进行调整。目前LORA主要用来定义画面特征&#xff0c;如具体的人物&#xff0c;衣物&#xff0c;画风等。Embeddings目前主要用于反面提示词中&#xff0c;用来避免错误的画面表现。 LORA lora的全称为&#xff1a;低秩适应模型。lora的基本…

05. 交换机的基本配置

文章目录 一. 初识交换机1.1. 交换机的概述1.2. Ethernet_ll格式1.3. MAC分类1.4. 冲突域1.5. 广播域1.6. 交换机的原理1.7. 交换机的3种转发行为 二. 初识ARP2.1. ARP概述2.2. ARP报文格式2.3. ARP的分类2.4. 免费ARP的作用 三. 实验专题3.1. 实验1&#xff1a;交换机的基本原…

常用芯片学习——AMS1117芯片

AMS1117 1A 低压差线性稳压器 使用说明 AMS1117 是一款低压差线性稳压电路&#xff0c;该电路输出电流能力为1A。该系列电路包含固定输出电压版本和可调输出电压版本&#xff0c;其输出电压精度为士1.5%。为了保证芯片和电源系统的稳定性&#xff0c;XBLWAMS1117 内置热保护和…