15个版本
0.3.8 | 2024年6月26日 |
---|---|
0.3.7 | 2024年5月14日 |
0.3.6 | 2024年3月27日 |
0.3.5 | 2023年10月24日 |
0.1.2 | 2023年8月31日 |
#338 在 数据库接口
每月1,253次下载
73KB
1.5K SLoC
bnf_sampler
此软件包已弃用。请使用kbnf代替。
这是一个使用递归下降算法确保大型语言模型产生的标记遵循基于巴科斯-诺尔范式(BNF)的方案的采样语言模型。
标记必须以UTF-8编码。
特性
- 非常快速。
- 与任何类型的语言模型词汇兼容。
- 易于使用。
如何尝试?
- 安装Rust.
- 运行
cargo run --release
来运行console_playground程序。您的控制台输入被视为标记。运行cargo run --release -- --help
来检查所有可能的命令行配置。修改`assets/grammar.bnf`来更改方案。(见语法方案部分和可能的标记列表部分)
或者您可以从发布页面下载预编译的二进制文件并运行。
在您的项目中使用
要在您的Rust项目中使用,只需在您的Cargo.toml
中将bnf_sampler = "0.3.1"
作为依赖项添加即可。
示例
将这些示例之一复制粘贴到assets/grammar.bnf
中,自行尝试。
DNA序列
<start>::=<sequence>
<sequence>::=<base>|<base><sequence>
<base>::="A"|"C"|"G"|"T"
整数
<start>::=<integer>
<integer>::=<positive_digit><digits>|'0'
<digits>::=<digit>|<digit><digits>
<digit>::='0'|<positive_digit>
<positive_digit>::="1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"
字符串
<start>::=<string>
<string>::='"'<content>'"'
<content>::=<except!([escaped_literals])>|<except!([escaped_literals])><content>|'\\"'<content>|'\\"'
<escaped_literals>::='\t'|'\n'|'\r'|'"'
语法方案
在本项目中,使用了一个略微修改的BNF版本。主要区别是
-
不支持左递归。(计划在未来支持。)
-
连续的终结符合并为一个终结符。例如,
'b''o''y'
变为'boy'
。 -
<any!>
被添加为一个特殊的非终结符,它可以匹配给定词汇表中的任何标记。 -
<except!(excepted_literals)>
被添加为一个特殊的非终结符,它可以-
匹配给定词汇表中不包含任何
excepted_literals
的任何标记。 -
如果标记包含任何
excepted_literals
,并且至少有一个可能的子串前缀等于给定词汇表中的任何标记,则匹配子串token[:the beginning of the first appearing excepted literal]
。 -
<except!(excepted_literals)>
有两种形式<except!('excepted_literal')>
或<except!("excepted_literal")>
,它指定一个且仅有一个excepted_literal
。- 例如,
<except!('excepted_literal')>
将ar
指定为 excepted_literal。它将匹配card
中的c
(假设c
是一个有效的标记),并将ard
传递给下一个语法项。
- 例如,
<except!([nonterminal])>
指定任何非终结符接受的标记属于 excepted_literals。- 警告:非终结符本身以及从非终结符扩展的所有非终结符不应为
<except!([nonterminal])>
,否则程序可能会崩溃。 - 例如,给定
<abc> ::= 'a'|'b'|'c'
,<sequence>::= <abc>|<abc><sequence>
<except!([sequence])>
指定所有仅包含a
、b
和c
的标记作为 excepted_literals。
- 警告:非终结符本身以及从非终结符扩展的所有非终结符不应为
-
-
在终端和
excepted_literals
中,识别并转换如下转义序列为相应的UTF-8字节:\t
、\r
、\n
、\u1234
。然而,如\x<hex><hex>
、\x00
这样的序列会被转换成原始字节。
列出可能的标记
列出的可能是当前状态下采样器可以接受的标记。以下规则定义了标记是否以给定BNF列在 Sampler::all_possible_tokens
的返回值中。
-
采样器未终止或进入无效状态。换句话说,当前输入标记可以被采样器接受,且不存在一条路径使得所有终端和非终端都在这条路径上被消耗。
- 例如,使用
<start>::=<A><B><C>, <A>::='boy', <B>::='next', <C>::='door'
,当以精确的顺序输入boy
、next
、door
时,将创建一个在输入后终止的采样器,否则将进入无效状态。 - 例如,
<sequence>::=<any!>|<any!><sequence>
将创建一个在任意输入标记后终止的采样器,因为路径中的<sequence>
变为<any!>
。换句话说,<any!>
是路径中的唯一非终端,且被消耗。
- 例如,使用
-
对于给定的终端,只列出可能的最长标记。
- 例如,终端
'apple'
仅在存在该标记的情况下列出标记apple
。标记如a
、ap
、app
不会被列出。
- 例如,终端
-
终端可以部分匹配和消耗。
- 例如,终端
apple66666
只会列出标记apple
(见规则 1),因为apple66666
不是一个有效的标记。输入apple
之后,终端变为66666
,因为前缀apple
已匹配。
- 例如,终端
-
一个标记可以在字节级别上被多个终端匹配。
- 例如,给定
<byte> ::= '\xf0'|'\xa0'|'xb0'
,<sequence>::= <byte>|<byte><sequence>
,<sequence>
将列出所有只包含字节值240
、160
和176
的 UTF-8 编码的标记。
- 例如,给定
路线图
- 添加更多示例和现成的 BNF 架构。
- 添加更多测试。
- 测试更高级的解析算法(如 Earley)并查看是否可以提高速度。
- Python 绑定。
- Huggingface transformers 集成。
依赖项
~5–8MB
~145K SLoC