Skip to content

Commit 3c41c18

Browse files
committed
feat(aichat): agent 支持识图
1 parent 7640f0c commit 3c41c18

File tree

6 files changed

+364
-252
lines changed

6 files changed

+364
-252
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聊天(识图)接口类型[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聊天(识图)接口地址https://api.siliconflow.cn/v1/chat/completions
1640+
- [x] 设置AI聊天(识图)密钥xxx
1641+
- [x] 设置AI聊天(识图)模型名Qwen/Qwen3-8B
16421642
- [x] 查看AI聊天系统提示词
16431643
- [x] 重置AI聊天系统提示词
16441644
- [x] 设置AI聊天系统提示词xxx

go.mod

Lines changed: 3 additions & 3 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.20250922144137-bf2b9bb6a8d9
15+
github.com/FloatTech/zbputils v1.7.2-0.20250923162319-dcba1aa52b1d
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
@@ -22,9 +22,9 @@ require (
2222
github.com/disintegration/imaging v1.6.2
2323
github.com/fumiama/ahsai v0.1.0
2424
github.com/fumiama/cron v1.3.0
25-
github.com/fumiama/deepinfra v0.0.0-20250923161832-8757564fe76c
25+
github.com/fumiama/deepinfra v0.0.0-20250924134153-348633b5c6fb
2626
github.com/fumiama/go-base16384 v1.7.0
27-
github.com/fumiama/go-onebot-agent v0.0.0-20250922152742-c40bb3512d63
27+
github.com/fumiama/go-onebot-agent v0.0.0-20250924153727-0cdc929590cf
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: 6 additions & 10 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.20250922144137-bf2b9bb6a8d9 h1:iR36inettls14aMOADNQ7PHNlGvgyDRRYp2dBgZCp8A=
21-
github.com/FloatTech/zbputils v1.7.2-0.20250922144137-bf2b9bb6a8d9/go.mod h1:L1Rvdf6JUXGRIdKaXVtBWa0iW481zccCjYdYeDSaMXs=
20+
github.com/FloatTech/zbputils v1.7.2-0.20250923162319-dcba1aa52b1d h1:B7pvVpZSSfCjSNLONq0dWTm5JahCdE2017hzDP/DmzY=
21+
github.com/FloatTech/zbputils v1.7.2-0.20250923162319-dcba1aa52b1d/go.mod h1:CpwrdL0xCiUfN1819TDKk470WGMYQZZanLjAYVfHCEM=
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=
@@ -59,14 +59,12 @@ github.com/fumiama/ahsai v0.1.0 h1:LXD61Kaj6kJHa3AEGsLIfKNzcgaVxg7JB72OR4yNNZ4=
5959
github.com/fumiama/ahsai v0.1.0/go.mod h1:fFeNnqgo44i8FIaguK659aQryuZeFy+4klYLQu/rfdk=
6060
github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo=
6161
github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY=
62-
github.com/fumiama/deepinfra v0.0.0-20250920170049-e3d1b92cc3a1 h1:6PglFpNVm3DalGyRldacW2/v4jGWwn3v3q1tr2PhbVQ=
63-
github.com/fumiama/deepinfra v0.0.0-20250920170049-e3d1b92cc3a1/go.mod h1:wW05PQSn8mo1mZIoa6LBUE+3xIBjkoONvnfPTV5ZOhY=
64-
github.com/fumiama/deepinfra v0.0.0-20250923161832-8757564fe76c h1:ypY8ynfghPMamNfG1qS+XJ52BSBrA1HVR1c7aL5dUkI=
65-
github.com/fumiama/deepinfra v0.0.0-20250923161832-8757564fe76c/go.mod h1:HgRu6n9XgeyNki7wHHlTa75ORiv3UlYZafqOAoazhOI=
62+
github.com/fumiama/deepinfra v0.0.0-20250924134153-348633b5c6fb h1:d0gl31nyOER4O3K0wpepont8flrDtzZsKACeWGxARX0=
63+
github.com/fumiama/deepinfra v0.0.0-20250924134153-348633b5c6fb/go.mod h1:HgRu6n9XgeyNki7wHHlTa75ORiv3UlYZafqOAoazhOI=
6664
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
6765
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
68-
github.com/fumiama/go-onebot-agent v0.0.0-20250922152742-c40bb3512d63 h1:ZdPMPIgZMH4HV4A/JIBb8G7UpLM4iUHWQ8qGjKnKiVI=
69-
github.com/fumiama/go-onebot-agent v0.0.0-20250922152742-c40bb3512d63/go.mod h1:wVMgFWkR3GpipL05FkokvrV/jWFIgoEWN1jzUGa0bWg=
66+
github.com/fumiama/go-onebot-agent v0.0.0-20250924153727-0cdc929590cf h1:yFkCBQlFBCRQLru/ANWvvWDTRpT3qLhBP94aAJnlmaY=
67+
github.com/fumiama/go-onebot-agent v0.0.0-20250924153727-0cdc929590cf/go.mod h1:FIhZxVeFAs201W06EgXxx/6b/l/ETSmu2sQOj10kjdk=
7068
github.com/fumiama/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs=
7169
github.com/fumiama/go-registry v0.2.7/go.mod h1:m+wp5fF8dYgVoFkBPZl+vlK90loymaJE0JCtocVQLEs=
7270
github.com/fumiama/go-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o=
@@ -75,8 +73,6 @@ github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoG
7573
github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk=
7674
github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc=
7775
github.com/fumiama/gotracemoe v0.0.3/go.mod h1:tyqahdUzHf0bQIAVY/GYmDWvYYe5ik1ZbhnGYh+zl40=
78-
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
79-
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
8076
github.com/fumiama/imgsz v0.0.4 h1:Lsasu2hdSSFS+vnD+nvR1UkiRMK7hcpyYCC0FzgSMFI=
8177
github.com/fumiama/imgsz v0.0.4/go.mod h1:bISOQVTlw9sRytPwe8ir7tAaEmyz9hSNj9n8mXMBG0E=
8278
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 h1:sQuR2+N5HurnvsZhiKdEg+Ig354TaqgCQRxd/0KgIOQ=

plugin/aichat/cfg.go

Lines changed: 124 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package aichat
22

33
import (
4+
"errors"
45
"fmt"
56
"strconv"
67
"strings"
@@ -18,19 +19,89 @@ var (
1819
cfg = newconfig()
1920
)
2021

22+
var (
23+
apitypes = map[string]uint8{
24+
"OpenAI": 0,
25+
"OLLaMA": 1,
26+
"GenAI": 2,
27+
}
28+
apilist = [3]string{"OpenAI", "OLLaMA", "GenAI"}
29+
)
30+
31+
type ModelType int
32+
33+
func newModelType(typ string) (ModelType, error) {
34+
t, ok := apitypes[typ]
35+
if !ok {
36+
return 0, errors.New("未知类型 " + typ)
37+
}
38+
return ModelType(t), nil
39+
}
40+
41+
func (mt ModelType) String() string {
42+
return apilist[mt]
43+
}
44+
45+
func (mt ModelType) protocol(modn string, temp float32, topp float32, maxn uint) (mod model.Protocol, err error) {
46+
switch cfg.Type {
47+
case 0:
48+
mod = model.NewOpenAI(
49+
modn, cfg.Separator,
50+
temp, topp, maxn,
51+
)
52+
case 1:
53+
mod = model.NewOLLaMA(
54+
modn, cfg.Separator,
55+
temp, topp, maxn,
56+
)
57+
case 2:
58+
mod = model.NewGenAI(
59+
modn,
60+
temp, topp, maxn,
61+
)
62+
default:
63+
err = errors.New("unsupported model type " + strconv.Itoa(int(cfg.Type)))
64+
}
65+
return
66+
}
67+
68+
type ModelBool bool
69+
70+
func (mb ModelBool) String() string {
71+
if mb {
72+
return "是"
73+
}
74+
return "否"
75+
}
76+
77+
type ModelKey string
78+
79+
func (mk ModelKey) String() string {
80+
if len(mk) == 0 {
81+
return "未设置"
82+
}
83+
if len(mk) <= 4 {
84+
return "****"
85+
}
86+
key := string(mk)
87+
return key[:2] + strings.Repeat("*", len(key)-4) + key[len(key)-2:]
88+
}
89+
2190
type config struct {
22-
ModelName string
23-
Type int
24-
MaxN uint
25-
TopP float32
26-
SystemP string
27-
API string
28-
Key string
29-
Separator string
30-
NoReplyAT bool
31-
NoSystemP bool
32-
NoRecord bool
33-
NoAgent bool
91+
ModelName string
92+
ImageModelName string
93+
Type ModelType
94+
ImageType ModelType
95+
MaxN uint
96+
TopP float32
97+
SystemP string
98+
API string
99+
ImageAPI string
100+
Key ModelKey
101+
ImageKey ModelKey
102+
Separator string
103+
NoReplyAT ModelBool
104+
NoSystemP ModelBool
34105
}
35106

36107
func newconfig() config {
@@ -41,10 +112,47 @@ func newconfig() config {
41112
}
42113
}
43114

115+
func (c *config) String() string {
116+
topp, maxn := c.mparams()
117+
sb := strings.Builder{}
118+
sb.WriteString(fmt.Sprintf("• 模型名:%s\n", c.ModelName))
119+
sb.WriteString(fmt.Sprintf("• 图像模型名:%s\n", c.ImageModelName))
120+
sb.WriteString(fmt.Sprintf("• 接口类型:%v\n", c.Type))
121+
sb.WriteString(fmt.Sprintf("• 图像接口类型:%v\n", c.ImageType))
122+
sb.WriteString(fmt.Sprintf("• 最大长度:%d\n", maxn))
123+
sb.WriteString(fmt.Sprintf("• TopP:%.1f\n", topp))
124+
sb.WriteString(fmt.Sprintf("• 系统提示词:%s\n", c.SystemP))
125+
sb.WriteString(fmt.Sprintf("• 接口地址:%s\n", c.API))
126+
sb.WriteString(fmt.Sprintf("• 图像接口地址:%s\n", c.ImageAPI))
127+
sb.WriteString(fmt.Sprintf("• 密钥:%v\n", c.Key))
128+
sb.WriteString(fmt.Sprintf("• 图像密钥:%v\n", c.ImageKey))
129+
sb.WriteString(fmt.Sprintf("• 分隔符:%s\n", c.Separator))
130+
sb.WriteString(fmt.Sprintf("• 响应@:%v\n", !c.NoReplyAT))
131+
sb.WriteString(fmt.Sprintf("• 支持系统提示词:%v\n", !c.NoSystemP))
132+
return sb.String()
133+
}
134+
44135
func (c *config) isvalid() bool {
45136
return c.ModelName != "" && c.API != "" && c.Key != ""
46137
}
47138

139+
// 获取全局模型参数:TopP和最大长度
140+
func (c *config) mparams() (topp float32, maxn uint) {
141+
// 处理TopP参数
142+
topp = c.TopP
143+
if topp == 0 {
144+
topp = 0.9
145+
}
146+
147+
// 处理最大长度参数
148+
maxn = c.MaxN
149+
if maxn == 0 {
150+
maxn = 4096
151+
}
152+
153+
return topp, maxn
154+
}
155+
48156
func ensureconfig(ctx *zero.Ctx) bool {
49157
c, ok := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
50158
if !ok {
@@ -62,7 +170,7 @@ func ensureconfig(ctx *zero.Ctx) bool {
62170
return true
63171
}
64172

65-
func newextrasetstr(ptr *string) func(ctx *zero.Ctx) {
173+
func newextrasetstr[T ~string](ptr *T) func(ctx *zero.Ctx) {
66174
return func(ctx *zero.Ctx) {
67175
args := strings.TrimSpace(ctx.State["args"].(string))
68176
if args == "" {
@@ -74,7 +182,7 @@ func newextrasetstr(ptr *string) func(ctx *zero.Ctx) {
74182
ctx.SendChain(message.Text("ERROR: no such plugin"))
75183
return
76184
}
77-
*ptr = args
185+
*ptr = T(args)
78186
err := c.SetExtra(&cfg)
79187
if err != nil {
80188
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
@@ -84,7 +192,7 @@ func newextrasetstr(ptr *string) func(ctx *zero.Ctx) {
84192
}
85193
}
86194

87-
func newextrasetbool(ptr *bool) func(ctx *zero.Ctx) {
195+
func newextrasetbool[T ~bool](ptr *T) func(ctx *zero.Ctx) {
88196
return func(ctx *zero.Ctx) {
89197
args := ctx.State["regex_matched"].([]string)
90198
isno := args[1] == "不"
@@ -93,7 +201,7 @@ func newextrasetbool(ptr *bool) func(ctx *zero.Ctx) {
93201
ctx.SendChain(message.Text("ERROR: no such plugin"))
94202
return
95203
}
96-
*ptr = isno
204+
*ptr = T(isno)
97205
err := c.SetExtra(&cfg)
98206
if err != nil {
99207
ctx.SendChain(message.Text("ERROR: set extra err: ", err))
@@ -156,44 +264,3 @@ func newextrasetfloat32(ptr *float32) func(ctx *zero.Ctx) {
156264
ctx.SendChain(message.Text("成功"))
157265
}
158266
}
159-
160-
func printConfig(rate int64, temperature int64, cfg config) string {
161-
maxn := cfg.MaxN
162-
if maxn == 0 {
163-
maxn = 4096
164-
}
165-
topp := cfg.TopP
166-
if topp == 0 {
167-
topp = 0.9
168-
}
169-
var builder strings.Builder
170-
builder.WriteString("当前AI聊天配置:\n")
171-
builder.WriteString(fmt.Sprintf("• 模型名:%s\n", cfg.ModelName))
172-
builder.WriteString(fmt.Sprintf("• 接口类型:%d(%s)\n", cfg.Type, apilist[cfg.Type]))
173-
builder.WriteString(fmt.Sprintf("• 触发概率:%d%%\n", rate))
174-
builder.WriteString(fmt.Sprintf("• 温度:%.2f\n", float32(temperature)/100))
175-
builder.WriteString(fmt.Sprintf("• 最大长度:%d\n", maxn))
176-
builder.WriteString(fmt.Sprintf("• TopP:%.1f\n", topp))
177-
builder.WriteString(fmt.Sprintf("• 系统提示词:%s\n", cfg.SystemP))
178-
builder.WriteString(fmt.Sprintf("• 接口地址:%s\n", cfg.API))
179-
builder.WriteString(fmt.Sprintf("• 密钥:%s\n", maskKey(cfg.Key)))
180-
builder.WriteString(fmt.Sprintf("• 分隔符:%s\n", cfg.Separator))
181-
builder.WriteString(fmt.Sprintf("• 响应@:%s\n", yesNo(!cfg.NoReplyAT)))
182-
builder.WriteString(fmt.Sprintf("• 支持系统提示词:%s\n", yesNo(!cfg.NoSystemP)))
183-
builder.WriteString(fmt.Sprintf("• 以AI语音输出:%s\n", yesNo(!cfg.NoRecord)))
184-
return builder.String()
185-
}
186-
187-
func maskKey(key string) string {
188-
if len(key) <= 4 {
189-
return "****"
190-
}
191-
return key[:2] + strings.Repeat("*", len(key)-4) + key[len(key)-2:]
192-
}
193-
194-
func yesNo(b bool) string {
195-
if b {
196-
return "是"
197-
}
198-
return "否"
199-
}

0 commit comments

Comments
 (0)