Skip to content

Commit 3302d8d

Browse files
committed
feat(aichat): agent support fallback to normal chat
1 parent dd328af commit 3302d8d

File tree

6 files changed

+104
-190
lines changed

6 files changed

+104
-190
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,12 +1633,12 @@ print("run[CQ:image,file="+j["img"]+"]")
16331633

16341634
- [x] 设置AI聊天触发概率10
16351635
- [x] 设置AI聊天温度80
1636-
- [x] 设置AI聊天(识图)接口类型[OpenAI|OLLaMA|GenAI]
1636+
- [x] 设置AI聊天(识图|Agent)接口类型[OpenAI|OLLaMA|GenAI]
16371637
- [x] 设置AI聊天(不)使用Agent模式
16381638
- [x] 设置AI聊天(不)支持系统提示词
1639-
- [x] 设置AI聊天(识图)接口地址https://api.siliconflow.cn/v1/chat/completions
1640-
- [x] 设置AI聊天(识图)密钥xxx
1641-
- [x] 设置AI聊天(识图)模型名Qwen/Qwen3-8B
1639+
- [x] 设置AI聊天(识图|Agent)接口地址https://api.siliconflow.cn/v1/chat/completions
1640+
- [x] 设置AI聊天(识图|Agent)密钥xxx
1641+
- [x] 设置AI聊天(识图|Agent)模型名Qwen/Qwen3-8B
16421642
- [x] 查看AI聊天系统提示词
16431643
- [x] 重置AI聊天系统提示词
16441644
- [x] 设置AI聊天系统提示词xxx

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/FloatTech/sqlite v1.7.1
1313
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562
1414
github.com/FloatTech/zbpctrl v1.7.0
15-
github.com/FloatTech/zbputils v1.7.2-0.20250925155009-638ed762e15e
15+
github.com/FloatTech/zbputils v1.7.2-0.20250926153026-d616e2b87477
1616
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7
1717
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
1818
github.com/Tnze/go-mc v1.20.2
@@ -24,7 +24,7 @@ require (
2424
github.com/fumiama/cron v1.3.0
2525
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa
2626
github.com/fumiama/go-base16384 v1.7.0
27-
github.com/fumiama/go-onebot-agent v0.0.0-20250925171858-9c2cb926ec95
27+
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8
2828
github.com/fumiama/go-registry v0.2.7
2929
github.com/fumiama/gotracemoe v0.0.3
3030
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562 h1:snfw7FNFym1eNnLrQ
1717
github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
1818
github.com/FloatTech/zbpctrl v1.7.0 h1:Hxo6EIhJo+pHjcQP9QgIJgluaT1pHH99zkk3njqTNMo=
1919
github.com/FloatTech/zbpctrl v1.7.0/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE=
20-
github.com/FloatTech/zbputils v1.7.2-0.20250925155009-638ed762e15e h1:M+pIxQFztHqrtUVmfctSs/D5ytn0ag6twP6iJg3gdEk=
21-
github.com/FloatTech/zbputils v1.7.2-0.20250925155009-638ed762e15e/go.mod h1:AUDxqs7liBF2H7TpSs+OXZj1Akyh0moUN/J/j8iNFxc=
20+
github.com/FloatTech/zbputils v1.7.2-0.20250926153026-d616e2b87477 h1:T1ugPphuYnLUWvJOw0S200p2tjM2rzVdwIz76rtGt8E=
21+
github.com/FloatTech/zbputils v1.7.2-0.20250926153026-d616e2b87477/go.mod h1:hIXcVZ3CFiL3dnM1QcZUMCjKhVryYY0EnJVN0kicB9A=
2222
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
2323
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU=
2424
github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
@@ -63,8 +63,8 @@ github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa h1:UMMNejpPp8dn9
6363
github.com/fumiama/deepinfra v0.0.0-20250924162107-cf156d49a0fa/go.mod h1:uqsWK/GM9OvKV0pXZOQB63rWugBbiXInY8E1JoRKhkg=
6464
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
6565
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
66-
github.com/fumiama/go-onebot-agent v0.0.0-20250925171858-9c2cb926ec95 h1:ZIS5BF51BkRhwfxmEVdn5mdoH1AKKFodwqpRJWl4mWs=
67-
github.com/fumiama/go-onebot-agent v0.0.0-20250925171858-9c2cb926ec95/go.mod h1:FIhZxVeFAs201W06EgXxx/6b/l/ETSmu2sQOj10kjdk=
66+
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8 h1:aXk5IVXvPy2IfajL6gH+V/6ZOVV1BBVKjnFISLvyw60=
67+
github.com/fumiama/go-onebot-agent v0.0.0-20250926145606-37ebfa6131c8/go.mod h1:oH8DGDpRPjUAu8Fd/K+RxsB+z0Yis+BHeJAh+ZkO5EM=
6868
github.com/fumiama/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs=
6969
github.com/fumiama/go-registry v0.2.7/go.mod h1:m+wp5fF8dYgVoFkBPZl+vlK90loymaJE0JCtocVQLEs=
7070
github.com/fumiama/go-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o=

plugin/aichat/cfg.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,20 @@ func (mk ModelKey) String() string {
9393
type config struct {
9494
ModelName string
9595
ImageModelName string
96+
AgentModelName string
9697
Type ModelType
9798
ImageType ModelType
99+
AgentType ModelType
98100
MaxN uint
99101
TopP float32
100102
SystemP string
101103
API string
102104
ImageAPI string
105+
AgentAPI string
103106
Key ModelKey
104107
ImageKey ModelKey
108+
AgentKey ModelKey
105109
Separator string
106-
NoReplyAT ModelBool
107110
NoSystemP ModelBool
108111
}
109112

@@ -130,7 +133,6 @@ func (c *config) String() string {
130133
sb.WriteString(fmt.Sprintf("• 密钥:%v\n", c.Key))
131134
sb.WriteString(fmt.Sprintf("• 图像密钥:%v\n", c.ImageKey))
132135
sb.WriteString(fmt.Sprintf("• 分隔符:%s\n", c.Separator))
133-
sb.WriteString(fmt.Sprintf("• 响应@:%v\n", !c.NoReplyAT))
134136
sb.WriteString(fmt.Sprintf("• 支持系统提示词:%v\n", !c.NoSystemP))
135137
return sb.String()
136138
}
@@ -267,3 +269,30 @@ func newextrasetfloat32(ptr *float32) func(ctx *zero.Ctx) {
267269
ctx.SendChain(message.Text("成功"))
268270
}
269271
}
272+
273+
func newextrasetmodeltype(ptr *ModelType) func(ctx *zero.Ctx) {
274+
return func(ctx *zero.Ctx) {
275+
args := strings.TrimSpace(ctx.State["args"].(string))
276+
if args == "" {
277+
ctx.SendChain(message.Text("ERROR: empty args"))
278+
return
279+
}
280+
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
281+
if !ok {
282+
ctx.SendChain(message.Text("ERROR: no such plugin"))
283+
return
284+
}
285+
typ, err := newModelType(args)
286+
if err != nil {
287+
ctx.SendChain(message.Text("ERROR: ", err))
288+
return
289+
}
290+
*ptr = typ
291+
err = c.SetExtra(&cfg)
292+
if err != nil {
293+
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
294+
return
295+
}
296+
ctx.SendChain(message.Text("成功"))
297+
}
298+
}

plugin/aichat/main.go

Lines changed: 52 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ var (
3434
Brief: "OpenAI聊天",
3535
Help: "- 设置AI聊天触发概率10\n" +
3636
"- 设置AI聊天温度80\n" +
37-
"- 设置AI聊天(识图)接口类型[OpenAI|OLLaMA|GenAI]\n" +
37+
"- 设置AI聊天(识图|Agent)接口类型[OpenAI|OLLaMA|GenAI]\n" +
3838
"- 设置AI聊天(不)使用Agent模式\n" +
3939
"- 设置AI聊天(不)支持系统提示词\n" +
40-
"- 设置AI聊天(识图)接口地址https://api.siliconflow.cn/v1/chat/completions\n" +
41-
"- 设置AI聊天(识图)密钥xxx\n" +
42-
"- 设置AI聊天(识图)模型名Qwen/Qwen3-8B\n" +
40+
"- 设置AI聊天(识图|Agent)接口地址https://api.siliconflow.cn/v1/chat/completions\n" +
41+
"- 设置AI聊天(识图|Agent)密钥xxx\n" +
42+
"- 设置AI聊天(识图|Agent)模型名Qwen/Qwen3-8B\n" +
4343
"- 查看AI聊天系统提示词\n" +
4444
"- 重置AI聊天系统提示词\n" +
4545
"- 设置AI聊天系统提示词xxx\n" +
@@ -71,18 +71,24 @@ var (
7171

7272
func init() {
7373
en.OnMessage(ensureconfig, func(ctx *zero.Ctx) bool {
74-
return ctx.ExtractPlainText() != "" &&
75-
(bool(!cfg.NoReplyAT) || (bool(cfg.NoReplyAT) && !ctx.Event.IsToMe))
76-
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
7774
gid := ctx.Event.GroupID
7875
if gid == 0 {
7976
gid = -ctx.Event.UserID
8077
}
8178
stor, err := newstorage(ctx, gid)
8279
if err != nil {
8380
logrus.Warnln("ERROR: ", err)
84-
return
81+
return false
82+
}
83+
ctx.State["__aichat_stor__"] = stor
84+
return ctx.ExtractPlainText() != "" &&
85+
(bool(!stor.noreplyat()) || (bool(stor.noreplyat()) && !ctx.Event.IsToMe))
86+
}).SetBlock(false).Handle(func(ctx *zero.Ctx) {
87+
gid := ctx.Event.GroupID
88+
if gid == 0 {
89+
gid = -ctx.Event.UserID
8590
}
91+
stor := ctx.State["__aichat_stor__"].(storage)
8692
rate := stor.rate()
8793
if !ctx.Event.IsToMe && rand.Intn(100) >= int(rate) {
8894
return
@@ -97,14 +103,13 @@ func init() {
97103
temperature := stor.temp()
98104
topp, maxn := cfg.mparams()
99105

100-
x := deepinfra.NewAPI(cfg.API, string(cfg.Key))
101-
mod, err := cfg.Type.protocol(cfg.ModelName, temperature, topp, maxn)
102-
if err != nil {
103-
logrus.Warnln("ERROR: ", err)
104-
return
105-
}
106-
107106
if !stor.noagent() {
107+
x := deepinfra.NewAPI(cfg.AgentAPI, string(cfg.AgentKey))
108+
mod, err := cfg.Type.protocol(cfg.AgentModelName, temperature, topp, maxn)
109+
if err != nil {
110+
logrus.Warnln("ERROR: ", err)
111+
return
112+
}
108113
role := goba.PermRoleUser
109114
if zero.AdminPermission(ctx) {
110115
role = goba.PermRoleAdmin
@@ -123,15 +128,10 @@ func init() {
123128
}
124129
ctx.NoTimeout()
125130
hasresp := false
126-
defer func() {
127-
if hasresp {
128-
ag.AddTerminus(gid)
129-
}
130-
}()
131131
for i := 0; i < 8; i++ { // 最大运行 8 轮因为问答上下文只有 16
132132
reqs := chat.CallAgent(ag, zero.SuperUserPermission(ctx), x, mod, gid, role)
133133
if len(reqs) == 0 {
134-
return
134+
break
135135
}
136136
hasresp = true
137137
for _, req := range reqs {
@@ -146,9 +146,19 @@ func init() {
146146
})
147147
}
148148
}
149-
return
149+
if hasresp {
150+
ag.AddTerminus(gid)
151+
return
152+
}
153+
// no response, fall back to normal chat
150154
}
151155

156+
x := deepinfra.NewAPI(cfg.API, string(cfg.Key))
157+
mod, err := cfg.Type.protocol(cfg.ModelName, temperature, topp, maxn)
158+
if err != nil {
159+
logrus.Warnln("ERROR: ", err)
160+
return
161+
}
152162
data, err := x.Request(chat.GetChatContext(mod, gid, cfg.SystemP, bool(cfg.NoSystemP)))
153163
if err != nil {
154164
logrus.Warnln("[aichat] post err:", err)
@@ -188,68 +198,34 @@ func init() {
188198
}
189199
}
190200
})
191-
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).Handle(newstoragebitmap(bitmaprate, 0, 100))
192-
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).Handle(newstoragebitmap(bitmaptemp, 0, 100))
193-
en.OnPrefix("设置AI聊天接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
194-
args := strings.TrimSpace(ctx.State["args"].(string))
195-
if args == "" {
196-
ctx.SendChain(message.Text("ERROR: empty args"))
197-
return
198-
}
199-
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
200-
if !ok {
201-
ctx.SendChain(message.Text("ERROR: no such plugin"))
202-
return
203-
}
204-
typ, err := newModelType(args)
205-
if err != nil {
206-
ctx.SendChain(message.Text("ERROR: ", err))
207-
return
208-
}
209-
cfg.Type = typ
210-
err = c.SetExtra(&cfg)
211-
if err != nil {
212-
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
213-
return
214-
}
215-
ctx.SendChain(message.Text("成功"))
216-
})
217-
en.OnPrefix("设置AI聊天识图接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
218-
args := strings.TrimSpace(ctx.State["args"].(string))
219-
if args == "" {
220-
ctx.SendChain(message.Text("ERROR: empty args"))
221-
return
222-
}
223-
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
224-
if !ok {
225-
ctx.SendChain(message.Text("ERROR: no such plugin"))
226-
return
227-
}
228-
typ, err := newModelType(args)
229-
if err != nil {
230-
ctx.SendChain(message.Text("ERROR: ", err))
231-
return
232-
}
233-
cfg.ImageType = typ
234-
err = c.SetExtra(&cfg)
235-
if err != nil {
236-
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
237-
return
238-
}
239-
ctx.SendChain(message.Text("成功"))
240-
})
201+
en.OnPrefix("设置AI聊天触发概率", zero.AdminPermission).SetBlock(true).
202+
Handle(ctxext.NewStorageSaveBitmapHandler(bitmaprate, 0, 100))
203+
en.OnPrefix("设置AI聊天温度", zero.AdminPermission).SetBlock(true).
204+
Handle(ctxext.NewStorageSaveBitmapHandler(bitmaptemp, 0, 100))
205+
en.OnPrefix("设置AI聊天接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
206+
Handle(newextrasetmodeltype(&cfg.Type))
207+
en.OnPrefix("设置AI聊天识图接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
208+
Handle(newextrasetmodeltype(&cfg.ImageType))
209+
en.OnPrefix("设置AI聊天Agent接口类型", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
210+
Handle(newextrasetmodeltype(&cfg.AgentType))
241211
en.OnPrefix("设置AI聊天接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
242212
Handle(newextrasetstr(&cfg.API))
243213
en.OnPrefix("设置AI聊天识图接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
244214
Handle(newextrasetstr(&cfg.ImageAPI))
215+
en.OnPrefix("设置AI聊天Agent接口地址", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
216+
Handle(newextrasetstr(&cfg.AgentAPI))
245217
en.OnPrefix("设置AI聊天密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
246218
Handle(newextrasetstr(&cfg.Key))
247219
en.OnPrefix("设置AI聊天识图密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
248220
Handle(newextrasetstr(&cfg.ImageKey))
221+
en.OnPrefix("设置AI聊天Agent密钥", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
222+
Handle(newextrasetstr(&cfg.ImageKey))
249223
en.OnPrefix("设置AI聊天模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
250224
Handle(newextrasetstr(&cfg.ModelName))
251225
en.OnPrefix("设置AI聊天识图模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
252226
Handle(newextrasetstr(&cfg.ImageModelName))
227+
en.OnPrefix("设置AI聊天Agent模型名", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
228+
Handle(newextrasetstr(&cfg.ImageModelName))
253229
en.OnPrefix("设置AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
254230
Handle(newextrasetstr(&cfg.SystemP))
255231
en.OnFullMatch("查看AI聊天系统提示词", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
@@ -272,17 +248,17 @@ func init() {
272248
en.OnPrefix("设置AI聊天分隔符", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
273249
Handle(newextrasetstr(&cfg.Separator))
274250
en.OnRegex("^设置AI聊天(不)?响应AT$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
275-
Handle(newextrasetbool(&cfg.NoReplyAT))
251+
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnrat))
276252
en.OnRegex("^设置AI聊天(不)?支持系统提示词$", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
277253
Handle(newextrasetbool(&cfg.NoSystemP))
278254
en.OnRegex("^设置AI聊天(不)?使用Agent模式$", ensureconfig, zero.SuperUserPermission).SetBlock(true).
279-
Handle(newstoragebool(bitmapnagt))
255+
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnagt))
280256
en.OnPrefix("设置AI聊天最大长度", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
281257
Handle(newextrasetuint(&cfg.MaxN))
282258
en.OnPrefix("设置AI聊天TopP", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
283259
Handle(newextrasetfloat32(&cfg.TopP))
284260
en.OnRegex("^设置AI聊天(不)?以AI语音输出$", ensureconfig, zero.AdminPermission).SetBlock(true).
285-
Handle(newstoragebool(bitmapnrec))
261+
Handle(ctxext.NewStorageSaveBoolHandler(bitmapnrec))
286262
en.OnFullMatch("查看AI聊天配置", ensureconfig, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).
287263
Handle(func(ctx *zero.Ctx) {
288264
gid := ctx.Event.GroupID
@@ -298,6 +274,7 @@ func init() {
298274
"• 温度:", stor.temp(), "\n",
299275
"• 以AI语音输出:", ModelBool(!stor.norecord()), "\n",
300276
"• 使用Agent:", ModelBool(!stor.noagent()), "\n",
277+
"• 响应@:", ModelBool(!stor.noreplyat()), "\n",
301278
),
302279
message.Text("【当前AI聊天全局配置】\n", &cfg),
303280
)

0 commit comments

Comments
 (0)