1
0
mirror of https://github.com/fumiama/go-onebot-agent.git synced 2026-06-06 02:30:24 +08:00
Files
go-onebot-agent/agent.go
2025-09-22 23:19:05 +08:00

107 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package goba OneBot 11 协议 QQ 聊天 Agent
package goba
import (
"encoding/json"
"fmt"
"strings"
"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
manualaddreq bool
}
// NewAgent 创建一个 Agent 实例。
//
// - characteristics 推荐使用 Markdown 格式,描述 Agent 个性。
// - defaultprompt 为上下文为空时的默认提示,建议为事件的 JSON一般不会用到因此也可留空。
// - manualaddreq 表示是否由用户手动添加请求。
func NewAgent(
id int64, batchcap, itemscap int,
nickname, sex, characteristics, defaultprompt string,
manualaddreq bool,
) (ag Agent) {
ag = Agent{
id: id, nickname: nickname, sex: sex, chars: characteristics,
log: chat.NewLog[fmt.Stringer](batchcap, itemscap, "\n", defaultprompt),
manualaddreq: manualaddreq,
}
_ = ag.LoadPermTable()
return
}
// 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:
//
// - If LLM returns an invalid action, ErrPermissionDenied will be returned
// with complete reqs before invalid call, caller may decide whether to use
// these reqs by themselves. Whatever, invalid 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) (
reqs []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
}
reqs = make([]zero.APIRequest, 0, 2)
dec := json.NewDecoder(strings.NewReader(resp))
dec.UseNumber()
for dec.More() {
r := zero.APIRequest{}
err = dec.Decode(&r)
if err != nil {
break
}
if r.Action == "" {
continue
}
switch {
case !ag.perm.allow(role, r.Action):
err = errors.Wrap(ErrPermissionDenied, r.Action)
return
case !ag.manualaddreq:
ag.AddRequest(grp, &r)
}
reqs = append(reqs, r)
}
return
}