GopherLua:Go语言编写的Lua虚拟机和编译器。
===============================================================================
GopherLua是一个用Go语言编写的Lua 5.1(加上Lua 5.2中的goto
语句)虚拟机和编译器。GopherLua与Lua有着相同的目标:成为一种具有可扩展语义的脚本语言。它提供了Go语言API,让您可以轻松地将脚本语言嵌入到您的Go宿主程序中。
目录 :depth: 1
我认为GopherLua虽然不是最快的,但也不算太慢。
在微基准测试中,GopherLua的性能几乎与Python3相当(或略好)。
在wiki页面 <https://github.com/yuin/gopher-lua/wiki/Benchmarks>
_上有一些基准测试结果。
.. code-block:: bash
go get github.com/yuin/gopher-lua
GopherLua支持Go 1.9及以上版本。
GopherLua的API与Lua的使用方式非常相似,但栈仅用于传递参数和接收返回值。
GopherLua支持通道操作。请参阅**"Goroutines"**部分。
导入包。
.. code-block:: go
import ( "github.com/yuin/gopher-lua" )
在虚拟机中运行脚本。
.. code-block:: go
L := lua.NewState()
defer L.Close()
if err := L.DoString(print("hello")
); err != nil {
panic(err)
}
.. code-block:: go
L := lua.NewState() defer L.Close() if err := L.DoFile("hello.lua"); err != nil { panic(err) }
更多信息请参考Lua参考手册 <http://www.lua.org/manual/5.1/>
和Go文档 <http://godoc.org/github.com/yuin/gopher-lua>
。
请注意,Go文档 <http://godoc.org/github.com/yuin/gopher-lua>
中未注释的元素等同于Lua参考手册 <http://www.lua.org/manual/5.1/>
,但GopherLua使用对象而不是Lua栈索引。
数据模型
GopherLua程序中的所有数据都是LValue
。LValue
是一个接口类型,具有以下方法:
String() string
Type() LValueType
实现LValue接口的对象有:
================ ========================= ================== =======================
类型名称 Go类型 Type()值 常量
================ ========================= ================== =======================
LNilType
(常量) LTNil
LNil
LBool
(常量) LTBool
LTrue
, LFalse
LNumber
float64 LTNumber
-
LString
string LTString
-
LFunction
结构体指针 LTFunction
-
LUserData
结构体指针 LTUserData
-
LState
结构体指针 LTThread
-
LTable
结构体指针 LTTable
-
LChannel
chan LValue LTChannel
-
================ ========================= ================== =======================
您可以通过Go的方式(类型断言)或使用Type()
值来测试对象类型。
.. code-block:: go
lv := L.Get(-1) // 获取栈顶的值 if str, ok := lv.(lua.LString); ok { // lv 是 LString fmt.Println(string(str)) } if lv.Type() != lua.LTString { panic("需要字符串。") }
.. code-block:: go
lv := L.Get(-1) // 获取栈顶的值 if tbl, ok := lv.(*lua.LTable); ok { // lv 是 LTable fmt.Println(L.ObjLen(tbl)) }
注意,LBool
、LNumber
、LString
不是指针。
要测试LNilType
和LBool
,您必须使用预定义的常量。
.. code-block:: go
lv := L.Get(-1) // 获取栈顶的值
if lv == lua.LTrue { // 正确 }
if bl, ok := lv.(lua.LBool); ok && bool(bl) { // 错误 }
在Lua中,nil
和false
都使条件为假。LVIsFalse
和LVAsBool
实现了这个规范。
.. code-block:: go
lv := L.Get(-1) // 获取栈顶的值 if lua.LVIsFalse(lv) { // lv 是 nil 或 false }
if lua.LVAsBool(lv) { // lv 既不是 nil 也不是 false }
基于Go结构体的对象(LFunction
、LUserData
、LTable
)有一些公共方法和字段。您可以出于性能和调试的目的使用这些方法和字段,但有一些限制:
调用栈和注册表大小
LState
的调用栈大小控制脚本中Lua函数的最大调用深度(Go函数调用不计入)。
LState
的注册表为调用函数(包括Lua和Go函数)以及表达式中的临时变量实现了栈存储。它的存储需求会随着调用栈的使用和代码复杂度的增加而增加。
注册表和调用栈都可以设置为固定大小或自动调整大小。
当您在一个进程中实例化了大量LState
时,值得花时间调整注册表和调用栈的 选项。
+++++++++ 注册表 +++++++++
注册表可以在每个LState
的基础上配置初始大小、最大大小和步进大小。这将允许注册表根据需要增长。增长后不会再缩小。
.. code-block:: go
L := lua.NewState(lua.Options{
RegistrySize: 1024 * 20, // 这是注册表的初始大小
RegistryMaxSize: 1024 * 80, // 这是注册表可以增长到的最大大小。如果设置为`0`(默认值),则注册表不会自动增长
RegistryGrowStep: 32, // 这是每次注册表空间不足时增加的步长。默认值为`32`。
})
defer L.Close()
对于给定的脚本,如果注册表太小,最终会导致崩溃。如果注册表太大,会浪费内存(如果实例化了多个LState
,这可能会很显著)。
自动增长的注册表在调整大小时会稍微影响性能,但不会影响其他方面的性能。
+++++++++ 调用栈 +++++++++ 调用栈可以以两种不同的模式运行:固定大小或自动调整大小。
固定大小的调用栈具有最高的性能,并且内存开销固定。
自动调整大小的调用栈会根据需求分配和释放调用栈页,确保在任何时候都使用最少的内存。缺点是每次分配新的调用帧页时都会产生一些性能影响。
默认情况下,LState 会以 8 个为一页分配和释放调用栈帧,因此不会在每次函数调用时都产生分配开销。对于大多数用例来说,自动调整大小的调用栈的性能影响可能微不足道。
.. code-block:: go
L := lua.NewState(lua.Options{
CallStackSize: 120, // 这是该 LState 的最大调用栈大小
MinimizeStackMemory: true, // 如果未指定则默认为 `false`。如果设置,调用栈将根据需要自动增长和收缩,最大不超过 `CallStackSize`。如果未设置,调用栈将固定为 `CallStackSize`。
})
defer L.Close()
++++++++++++++++ 选项默认值 ++++++++++++++++
上面的例子展示了如何为每个 LState 自定义调用栈和注册表大小。你也可以通过修改 lua.RegistrySize、lua.RegistryGrowStep 和 lua.CallStackSize 的值来调整未指定选项时的一些默认值。
由 *LState#NewThread() 创建的 LState 对象会继承父 LState 对象的调用栈和注册表大小。
其他 lua.NewState 选项
API
有关更多信息,请参阅 Lua 参考手册和 Go 文档(LState 方法)。
+++++++++++++++++++++++++++++++++++++++++ 从 Lua 调用 Go +++++++++++++++++++++++++++++++++++++++++
.. code-block:: go
func Double(L lua.LState) int { lv := L.ToInt(1) / 获取参数 / L.Push(lua.LNumber(lv * 2)) / 推送结果 / return 1 / 结果数量 */ }
func main() { L := lua.NewState() defer L.Close() L.SetGlobal("double", L.NewFunction(Double)) /* 原始的 lua_setglobal 使用栈... */ }
.. code-block:: lua
print(double(20)) -- > "40"
任何在 GopherLua 中注册的函数都是一个 lua.LGFunction,定义在 value.go 中
.. code-block:: go
type LGFunction func(*LState) int
使用协程。
.. code-block:: go
co, _ := L.NewThread() /* 创建一个新线程 */ fn := L.GetGlobal("coro").(lua.LFunction) / 从 lua 获取函数 */ for { st, err, values := L.Resume(co, fn) if st == lua.ResumeError { fmt.Println("yield break(error)") fmt.Println(err.Error()) break }
for i, lv := range values {
fmt.Printf("%v : %v\n", i, lv)
}
if st == lua.ResumeOK {
fmt.Println("yield break(ok)")
break
}
}
+++++++++++++++++++++++++++++++++++++++++ 打开内置模块的子集 +++++++++++++++++++++++++++++++++++++++++
以下演示了如何在 Lua 中打开内置模块的子集,例如,为了避免启用具有访问本地文件或系统调用权限的模块。
main.go
.. code-block:: go
func main() {
L := lua.NewState(lua.Options{SkipOpenLibs: true})
defer L.Close()
for _, pair := range []struct {
n string
f lua.LGFunction
}{
{lua.LoadLibName, lua.OpenPackage}, // 必须是第一个
{lua.BaseLibName, lua.OpenBase},
{lua.TabLibName, lua.OpenTable},
} {
if err := L.CallByParam(lua.P{
Fn: L.NewFunction(pair.f),
NRet: 0,
Protect: true,
}, lua.LString(pair.n)); err != nil {
panic(err)
}
}
if err := L.DoFile("main.lua"); err != nil {
panic(err)
}
}
+++++++++++++++++++++++++++++++++++++++++ 用 Go 创建模块 +++++++++++++++++++++++++++++++++++++++++
mymodule.go
.. code-block:: go
package mymodule
import (
"github.com/yuin/gopher-lua"
)
func Loader(L *lua.LState) int {
// 向表中注册函数
mod := L.SetFuncs(L.NewTable(), exports)
// 注册其他内容
L.SetField(mod, "name", lua.LString("value"))
// 返回模块
L.Push(mod)
return 1
}
var exports = map[string]lua.LGFunction{
"myfunc": myfunc,
}
func myfunc(L *lua.LState) int {
return 0
}
mymain.go
.. code-block:: go
package main
import (
"./mymodule"
"github.com/yuin/gopher-lua"
)
func main() {
L := lua.NewState()
defer L.Close()
L.PreloadModule("mymodule", mymodule.Loader)
if err := L.DoFile("main.lua"); err != nil {
panic(err)
}
}
main.lua
.. code-block:: lua
local m = require("mymodule")
m.myfunc()
print(m.name)
+++++++++++++++++++++++++++++++++++++++++ 从 Go 调用 Lua +++++++++++++++++++++++++++++++++++++++++
.. code-block:: go
L := lua.NewState() defer L.Close() if err := L.DoFile("double.lua"); err != nil { panic(err) } if err := L.CallByParam(lua.P{ Fn: L.GetGlobal("double"), NRet: 1, Protect: true, }, lua.LNumber(10)); err != nil { panic(err) } ret := L.Get(-1) // 返回值 L.Pop(1) // 移除接收到的值
如果 Protect 为 false,GopherLua 将会 panic 而不是返回 error 值。
+++++++++++++++++++++++++++++++++++++++++ 用户定义类型 +++++++++++++++++++++++++++++++++++++++++ 你可以用 Go 编写新类型来扩展 GopherLua。 为此提供了 LUserData。
.. code-block:: go
type Person struct {
Name string
}
const luaPersonTypeName = "person"
// 向给定的 L 注册我的 person 类型。
func registerPersonType(L *lua.LState) {
mt := L.NewTypeMetatable(luaPersonTypeName)
L.SetGlobal("person", mt)
// 静态属性
L.SetField(mt, "new", L.NewFunction(newPerson))
// 方法
L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods))
}
// 构造函数
func newPerson(L *lua.LState) int {
person := &Person{L.CheckString(1)}
ud := L.NewUserData()
ud.Value = person
L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName))
L.Push(ud)
return 1
}
// 检查第一个 lua 参数是否为带有 *Person 的 *LUserData,并返回这个 *Person。
func checkPerson(L *lua.LState) *Person {
ud := L.CheckUserData(1)
if v, ok := ud.Value.(*Person); ok {
return v
}
L.ArgError(1, "person expected")
return nil
}
var personMethods = map[string]lua.LGFunction{
"name": personGetSetName,
}
// Person#Name 的 getter 和 setter
func personGetSetName(L *lua.LState) int {
p := checkPerson(L)
if L.GetTop() == 2 {
p.Name = L.CheckString(2)
return 0
}
L.Push(lua.LString(p.Name))
return 1
}
func main() {
L := lua.NewState()
defer L.Close()
registerPersonType(L)
if err := L.DoString( p = person.new("Steeve") print(p:name()) -- "Steeve" p:name("Alice") print(p:name()) -- "Alice"
); err != nil {
panic(err)
}
}
+++++++++++++++++++++++++++++++++++++++++ 终止运行中的LState +++++++++++++++++++++++++++++++++++++++++ GopherLua支持"Go并发模式:上下文"。
.. code-block:: go
L := lua.NewState()
defer L.Close()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
// 将上下文设置到我们的LState
L.SetContext(ctx)
err := L.DoString(`
local clock = os.clock
function sleep(n) -- 秒
local t0 = clock()
while clock() - t0 <= n do end
end
sleep(3)
`)
// err.Error()包含"context deadline exceeded"
使用协程
.. code-block:: go
L := lua.NewState()
defer L.Close()
ctx, cancel := context.WithCancel(context.Background())
L.SetContext(ctx)
defer cancel()
L.DoString(`
function coro()
local i = 0
while true do
coroutine.yield(i)
i = i+1
end
return i
end
`)
co, cocancel := L.NewThread()
defer cocancel()
fn := L.GetGlobal("coro").(*LFunction)
_, err, values := L.Resume(co, fn) // err为nil
cancel() // 取消父上下文
_, err, values = L.Resume(co, fn) // err不为nil:子上下文被取消
注意使用上下文会导致性能下降。
.. code-block::
time ./glua-with-context.exe fib.lua
9227465
0.01s user 0.11s system 1% cpu 7.505 total
time ./glua-without-context.exe fib.lua
9227465
0.01s user 0.01s system 0% cpu 5.306 total
+++++++++++++++++++++++++++++++++++++++++
在LState之间共享Lua字节码
+++++++++++++++++++++++++++++++++++++++++
调用DoFile
将加载Lua脚本,将其编译为字节码并在LState
中运行字节码。
如果你有多个需要运行相同脚本的LState
,你可以在它们之间共享字节码,这将节省内存。
共享字节码是安全的,因为它是只读的,不能被Lua脚本修改。
.. code-block:: go
// CompileLua从磁盘读取传入的lua文件并编译它。
func CompileLua(filePath string) (*lua.FunctionProto, error) {
file, err := os.Open(filePath)
defer file.Close()
if err != nil {
return nil, err
}
reader := bufio.NewReader(file)
chunk, err := parse.Parse(reader, filePath)
if err != nil {
return nil, err
}
proto, err := lua.Compile(chunk, filePath)
if err != nil {
return nil, err
}
return proto, nil
}
// DoCompiledFile接受CompileLua返回的FunctionProto,并在LState中运行它。
// 这相当于在LState上用原始源文件调用DoFile。
func DoCompiledFile(L *lua.LState, proto *lua.FunctionProto) error {
lfunc := L.NewFunctionFromProto(proto)
L.Push(lfunc)
return L.PCall(0, lua.MultRet, nil)
}
// 示例展示了如何在多个VM之间共享Lua脚本的编译字节码。
func Example() {
codeToShare := CompileLua("mylua.lua")
a := lua.NewState()
b := lua.NewState()
c := lua.NewState()
DoCompiledFile(a, codeToShare)
DoCompiledFile(b, codeToShare)
DoCompiledFile(c, codeToShare)
}
+++++++++++++++++++++++++++++++++++++++++
Goroutines
+++++++++++++++++++++++++++++++++++++++++
LState
不是goroutine安全的。建议每个goroutine使用一个LState,并通过使用通道在goroutine之间通信。
在GopherLua中,通道由channel
对象表示。channel
表提供了执行通道操作的函数。
由于内部包含非goroutine安全的对象,某些对象不能通过通道发送。
你不能从Go API将这些对象发送到通道。
.. code-block:: go
func receiver(ch, quit chan lua.LValue) {
L := lua.NewState()
defer L.Close()
L.SetGlobal("ch", lua.LChannel(ch))
L.SetGlobal("quit", lua.LChannel(quit))
if err := L.DoString(`
local exit = false
while not exit do
channel.select(
{"|<-", ch, function(ok, v)
if not ok then
print("channel closed")
exit = true
else
print("received:", v)
end
end},
{"|<-", quit, function(ok, v)
print("quit")
exit = true
end}
)
end
`); err != nil {
panic(err)
}
}
func sender(ch, quit chan lua.LValue) {
L := lua.NewState()
defer L.Close()
L.SetGlobal("ch", lua.LChannel(ch))
L.SetGlobal("quit", lua.LChannel(quit))
if err := L.DoString(`
ch:send("1")
ch:send("2")
`); err != nil {
panic(err)
}
ch <- lua.LString("3")
quit <- lua.LTrue
}
func main() {
ch := make(chan lua.LValue)
quit := make(chan lua.LValue)
go receiver(ch, quit)
go sender(ch, quit)
time.Sleep(3 * time.Second)
}
''''''''''''''' Go API '''''''''''''''
可以使用ToChannel
、CheckChannel
、OptChannel
。
更多信息请参考 Go doc(LState方法) <http://godoc.org/github.com/yuin/gopher-lua>
_。
''''''''''''''' Lua API '''''''''''''''
channel.make([buf:int]) -> ch:channel
buf
的新通道。默认情况下,buf
为0。channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}
select
语句相同。它返回所选case的索引,如果该case是接收操作,则返回接收到的值和一个布尔值,指示通道是否已关闭。case
是一个如下所述的表。
{"|<-", ch:channel [, handler:func(ok, data:any)]}
{"<-|", ch:channel, data:any [, handler:func(data:any)]}
{"default" [, handler:func()]}
channel.select
示例:
.. code-block:: lua
local idx, recv, ok = channel.select(
{"|<-", ch1},
{"|<-", ch2}
)
if not ok then
print("closed")
elseif idx == 1 then -- 从ch1接收
print(recv)
elseif idx == 2 then -- 从ch2接收
print(recv)
end
.. code-block:: lua
channel.select(
{"|<-", ch1, function(ok, data)
print(ok, data)
end},
{"<-|", ch2, "value", function(data)
print(data)
end},
{"default", function()
print("default action")
end}
)
data
。''''''''''''''''''''''''''''''
LState池模式
''''''''''''''''''''''''''''''
要创建每个线程的LState实例,你可以使用类似sync.Pool
的机制。
.. code-block:: go
type lStatePool struct {
m sync.Mutex
saved []*lua.LState
}
func (pl *lStatePool) Get() *lua.LState { pl.m.Lock() defer pl.m.Unlock() n := len(pl.saved) if n == 0 { return pl.New() } x := pl.saved[n-1] pl.saved = pl.saved[0 : n-1] return x }
func (pl *lStatePool) New() *lua.LState { L := lua.NewState() // 在此处设置L // 加载脚本,设置全局变量,共享通道等... return L }
func (pl *lStatePool) Put(L *lua.LState) { pl.m.Lock() defer pl.m.Unlock() pl.saved = append(pl.saved, L) }
func (pl *lStatePool) Shutdown() { for _, L := range pl.saved { L.Close() } }
// 全局LState池 var luaPool = &lStatePool{ saved: make([]*lua.LState, 0, 4), }
现在,你可以从 luaPool
中获取每个线程的LState对象。
.. code-block:: go
func MyWorker() {
L := luaPool.Get()
defer luaPool.Put(L)
/* 你的代码在这里 */
}
func main() {
defer luaPool.Shutdown()
go MyWorker()
go MyWorker()
/* 等等... */
}
协程
channel
的类型。channel
表提供了执行通道操作的函数。不支持的函数
string.dump
os.setlocale
lua_Debug.namewhat
package.loadlib
其他注意事项
collectgarbage
不接受任何参数,会为整个Go程序运行垃圾收集器。file:setvbuf
不支持行缓冲。os.setenv(name, value)
goto
和 ::label::
语句。
goto
是关键字,不是有效的变量名。Lua有一个名为 lua
的解释器。GopherLua有一个名为 glua
的解释器。
.. code-block:: bash
go get github.com/yuin/gopher-lua/cmd/glua
glua
具有与 lua
相同的选项。
请参阅 贡献者指南 <https://github.com/yuin/gopher-lua/tree/master/.github/CONTRIBUTING.md>
_ 。
gopher-luar <https://github.com/layeh/gopher-luar>
_ :简化了与gopher-lua之间的数据传递gluamapper <https://github.com/yuin/gluamapper>
_ :将Lua表映射到Go结构体gluare <https://github.com/yuin/gluare>
_ :gopher-lua的正则表达式gluahttp <https://github.com/cjoudrey/gluahttp>
_ :gopher-lua的HTTP请求模块gopher-json <https://github.com/layeh/gopher-json>
_ :gopher-lua的简单JSON编码器/解码器gluayaml <https://github.com/kohkimakimoto/gluayaml>
_ :gopher-lua的Yaml解析器glua-lfs <https://github.com/layeh/gopher-lfs>
_ :部分实现了gopher-lua的luafilesystem模块gluaurl <https://github.com/cjoudrey/gluaurl>
_ :gopher-lua的URL解析器/构建器模块gluahttpscrape <https://github.com/felipejfc/gluahttpscrape>
_ :gopher-lua的简单HTML抓取模块gluaxmlpath <https://github.com/ailncode/gluaxmlpath>
_ :gopher-lua的xmlpath模块gmoonscript <https://github.com/rucuriousyet/gmoonscript>
_ :Gopher Lua VM的Moonscript编译器loguago <https://github.com/rucuriousyet/loguago>
_ :Gopher-Lua的Zerolog封装器gluacrypto <https://github.com/tengattack/gluacrypto>
_ :GopherLua VM的原生Go加密库实现gluasql <https://github.com/tengattack/gluasql>
_ :GopherLua VM的原生Go SQL客户端实现purr <https://github.com/leyafo/purr>
_ :HTTP模拟测试工具vadv/gopher-lua-libs <https://github.com/vadv/gopher-lua-libs>
_ :GopherLua VM的一些有用库gluasocket <https://gitlab.com/megalithic-llc/gluasocket>
_ :GopherLua VM的原生Go LuaSocket实现glua-async <https://github.com/CuberL/glua-async>
_ :gopher-lua的async/await实现gopherlua-debugger <https://github.com/edolphin-ydf/gopherlua-debugger>
_ :gopher-lua的调试器gluamahonia <https://github.com/super1207/gluamahonia>
_ :gopher-lua的编码转换器BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB
MIT
Yusuke Inuzuka
AI数字人视频创作平台
Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。
一站式AI创作平台
提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作
AI办公助手,复杂任务高效处理
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确 地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商 务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星 火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号