1
0
mirror of https://github.com/fumiama/go-onebot-agent.git synced 2026-06-05 02:00:23 +08:00
Files
go-onebot-agent/agent.go
2025-09-21 14:56:03 +08:00

91 lines
2.4 KiB
Go

// Package goba OneBot 11 协议 QQ 聊天 Agent
package goba
import (
"encoding/json"
"fmt"
"io"
"github.com/fumiama/deepinfra"
"github.com/fumiama/deepinfra/chat"
"github.com/fumiama/deepinfra/model"
"github.com/pkg/errors"
zero "github.com/wdvxdr1123/ZeroBot"
)
var (
// ErrPermissionDenied LLM 调用了不该调用的 action
ErrPermissionDenied = errors.New("permission denied")
)
// Agent is a OneBot event context, it is recommended to create one agent
// per group or per user.
type Agent struct {
log chat.Log[fmt.Stringer]
id int64
nickname, sex string
chars string
perm *Perm
}
// NewAgent characteristics 最好是 MD 格式, defaultprompt 是上下文为空时的默认项, 建议为 Event JSON
func NewAgent(
id int64, batchcap, itemscap int,
nickname, sex, characteristics, defaultprompt string,
) Agent {
return Agent{
id: id, nickname: nickname, sex: sex, chars: characteristics,
log: chat.NewLog[fmt.Stringer](batchcap, itemscap, "\n", defaultprompt),
}
}
// AddEvent 添加接收到的事件
func (ag *Agent) AddEvent(grp int64, ev *Event) {
ag.log.Add(grp, ev, false)
}
// AddRequest 一般无需主动调用, 由 GetAction 自动添加
func (ag *Agent) AddRequest(grp int64, req *zero.APIRequest) {
ag.log.Add(grp, req, true)
}
// GetAction get OneBot CallAction from LLM and add it to context.
//
// Note:
//
// 1. The response may be empty, meaning that LLM do not want
// to react with these events. In this case, this function will
// return io.EOF and the context will be left no change.
//
// 2. If LLM returns an invalid action, ErrPermissionDenied will be returned
// with complete req, caller may decide whether to use this req by themselves.
// Whatever, this req will not be added into the context. You may call
// AddRequest to add it but it is not recommended.
func (ag *Agent) GetAction(api deepinfra.API, p model.Protocol, grp int64, role PermRole, isusersystem bool) (
req zero.APIRequest, err error,
) {
sysp, err := ag.system(role)
if err != nil {
return
}
m := ag.log.Modelize(p, grp, sysp, isusersystem)
resp, err := api.Request(m)
if err != nil {
return
}
err = json.Unmarshal([]byte(resp), &req)
if err == nil && req.Action == "" {
err = io.EOF
}
if !ag.perm.allow(role, req.Action) {
err = errors.Wrap(ErrPermissionDenied, req.Action)
} else {
ag.AddRequest(grp, &req)
}
return
}