4.7 KiB
4.7 KiB
插件开发指南
Cyrene 插件系统允许第三方开发者为昔涟扩展新工具。插件用 Go 编写,只需实现
Plugin和Tool接口即可被自动发现和调用。
核心接口
Plugin(插件入口)
type Plugin interface {
Metadata() PluginMetadata // 插件元信息
Init(ctx context.Context, config PluginConfig) error
Start(ctx context.Context, host HostAPI) error
Tools() []Tool // 返回插件提供的工具列表
}
Tool(工具定义)
type Tool interface {
Definition() ToolDefinition // 工具的 name/description/parameters
Execute(ctx context.Context, args map[string]interface{}) (*ToolResult, error)
Validate(args map[string]interface{}) error
}
LLM 通过 Definition() 返回的 description 判断何时调用此工具——所以描述要写得清晰准确。
ToolDefinition
type ToolDefinition struct {
Name string // 工具名(LLM 用 function_call name 匹配)
Description string // 描述——LLM 据此判断要不要调用
Parameters map[string]interface{} // JSON Schema 参数定义
}
最小示例
package myplugin
import "git.yeij.top/AskaEth/Cyrene-Plugins/sdk"
type HelloPlugin struct{}
func (p *HelloPlugin) Metadata() sdk.PluginMetadata {
return sdk.PluginMetadata{
Name: "hello", Version: "1.0.0", Author: "your-name",
Description: "示例插件:向用户问好",
}
}
func (p *HelloPlugin) Init(ctx context.Context, cfg sdk.PluginConfig) error { return nil }
func (p *HelloPlugin) Start(ctx context.Context, host sdk.HostAPI) error { return nil }
func (p *HelloPlugin) Stop(ctx context.Context) error { return nil }
func (p *HelloPlugin) Tools() []sdk.Tool {
return []sdk.Tool{&HelloTool{}}
}
// --- Tool ---
type HelloTool struct{}
func (t *HelloTool) Definition() sdk.ToolDefinition {
return sdk.ToolDefinition{
Name: "hello",
Description: "向用户打招呼。当用户说你好/嗨/哈喽时调用。",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"name": map[string]string{"type": "string", "description": "用户名字(可选)"},
},
},
}
}
func (t *HelloTool) Execute(ctx context.Context, args map[string]interface{}) (*sdk.ToolResult, error) {
name, _ := args["name"].(string)
if name == "" { name = "开拓者" }
return &sdk.ToolResult{Success: true, Output: name + ",昔涟向你问好♪"}, nil
}
func (t *HelloTool) Validate(args map[string]interface{}) error { return nil }
注册到 Cyrene
方式一:plugins.json(推荐)
- 将插件代码放到
backend/plugins/<插件名>/ - 在
backend/ai-core/plugins.json中添加条目:
{ "name": "my-hello", "import": "git.yeij.top/AskaEth/Cyrene-Plugins/my-hello", "struct": "HelloPlugin" }
- 运行代码生成器:
cd backend/ai-core/cmd && go run gen_plugins.go
- 重新编译 ai-core
方式二:直接注册(需要构造参数的插件)
在 ai-core/cmd/main.go 中添加:
for _, t := range (&myplugin.HelloPlugin{}).Tools() {
toolRegistry.Register(t)
}
插件目录结构
backend/plugins/ ← 第三方插件目录
my-hello/
plugin.json ← 插件声明(name, version, struct)
main.go ← 插件入口
plugin.json 格式:
{
"name": "my-hello",
"version": "1.0.0",
"author": "your-name",
"description": "我的第一个插件"
}
ToolResult 格式
type ToolResult struct {
ToolName string `json:"tool_name"`
Success bool `json:"success"`
Output string `json:"output,omitempty"` // 成功时的结果文本
Error string `json:"error,omitempty"` // 失败时的错误信息
}
Output 会直接注入 LLM 对话,所以要写成自然语言格式。
调用机制
用户: "帮我打个招呼"
→ LLM 看到所有工具的 Definition()
→ 判断需要调用 hello 工具
→ function_call: {name: "hello", arguments: {name: "开拓者"}}
→ ToolRegistry.Execute("hello", {name: "开拓者"})
→ HelloTool.Execute() → "开拓者,昔涟向你问好♪"
→ LLM 将结果融入回复
17 个内置工具也是同样的机制,插件和内置工具对 LLM 来说无区别。
相关仓库
- cyrene-plugins — 插件 SDK + 内置插件源码
- 工具调用系统介绍 — 完整调用链路说明