Skip to content

Commit 9875b6e

Browse files
authored
Merge pull request #87 from Leizhenpeng/feat_pic_varity
feat : support image variation
2 parents 0069ff1 + 6709c77 commit 9875b6e

18 files changed

+994
-424
lines changed

code/handlers/common.go

+14
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,17 @@ func parseFileKey(content string) string {
8484
fileKey := contentMap["file_key"].(string)
8585
return fileKey
8686
}
87+
88+
func parseImageKey(content string) string {
89+
var contentMap map[string]interface{}
90+
err := json.Unmarshal([]byte(content), &contentMap)
91+
if err != nil {
92+
fmt.Println(err)
93+
return ""
94+
}
95+
if contentMap["image_key"] == nil {
96+
return ""
97+
}
98+
imageKey := contentMap["image_key"].(string)
99+
return imageKey
100+
}

code/handlers/event_action.go

+59-8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"start-feishubot/initialization"
99
"start-feishubot/services"
10+
"start-feishubot/services/openai"
1011
"start-feishubot/utils"
1112
"start-feishubot/utils/audio"
1213
)
@@ -18,6 +19,7 @@ type MsgInfo struct {
1819
chatId *string
1920
qParsed string
2021
fileKey string
22+
imageKey string
2123
sessionId *string
2224
mention []*larkim.MentionEvent
2325
}
@@ -93,7 +95,7 @@ func (*RolePlayAction) Execute(a *ActionInfo) bool {
9395
if system, foundSystem := utils.EitherCutPrefix(a.info.qParsed,
9496
"/system ", "角色扮演 "); foundSystem {
9597
a.handler.sessionCache.Clear(*a.info.sessionId)
96-
systemMsg := append([]services.Messages{}, services.Messages{
98+
systemMsg := append([]openai.Messages{}, openai.Messages{
9799
Role: "system", Content: system,
98100
})
99101
a.handler.sessionCache.SetMsg(*a.info.sessionId, systemMsg)
@@ -133,8 +135,59 @@ func (*PicAction) Execute(a *ActionInfo) bool {
133135
return false
134136
}
135137

136-
// 生成图片
137138
mode := a.handler.sessionCache.GetMode(*a.info.sessionId)
139+
//fmt.Println("mode: ", mode)
140+
141+
// 收到一张图片,且不在图片创作模式下, 提醒是否切换到图片创作模式
142+
if a.info.msgType == "image" && mode != services.ModePicCreate {
143+
sendPicModeCheckCard(*a.ctx, a.info.sessionId, a.info.msgId)
144+
return false
145+
}
146+
147+
if a.info.msgType == "image" && mode == services.ModePicCreate {
148+
//保存图片
149+
imageKey := a.info.imageKey
150+
//fmt.Printf("fileKey: %s \n", imageKey)
151+
msgId := a.info.msgId
152+
//fmt.Println("msgId: ", *msgId)
153+
req := larkim.NewGetMessageResourceReqBuilder().MessageId(
154+
*msgId).FileKey(imageKey).Type("image").Build()
155+
resp, err := initialization.GetLarkClient().Im.MessageResource.Get(context.Background(), req)
156+
//fmt.Println(resp, err)
157+
if err != nil {
158+
//fmt.Println(err)
159+
fmt.Sprintf("🤖️:图片下载失败,请稍后再试~\n 错误信息: %v", err)
160+
return false
161+
}
162+
163+
f := fmt.Sprintf("%s.png", imageKey)
164+
resp.WriteFile(f)
165+
defer os.Remove(f)
166+
resolution := a.handler.sessionCache.GetPicResolution(*a.
167+
info.sessionId)
168+
169+
openai.ConvertJpegToPNG(f)
170+
openai.ConvertToRGBA(f, f)
171+
172+
//图片校验
173+
err = openai.VerifyPngs([]string{f})
174+
if err != nil {
175+
replyMsg(*a.ctx, fmt.Sprintf("🤖️:无法解析图片,请发送原图并尝试重新操作~"),
176+
a.info.msgId)
177+
return false
178+
}
179+
bs64, err := a.handler.gpt.GenerateOneImageVariation(f, resolution)
180+
if err != nil {
181+
replyMsg(*a.ctx, fmt.Sprintf(
182+
"🤖️:图片生成失败,请稍后再试~\n错误信息: %v", err), a.info.msgId)
183+
return false
184+
}
185+
replayImagePlainByBase64(*a.ctx, bs64, a.info.msgId)
186+
return false
187+
188+
}
189+
190+
// 生成图片
138191
if mode == services.ModePicCreate {
139192
resolution := a.handler.sessionCache.GetPicResolution(*a.
140193
info.sessionId)
@@ -145,10 +198,8 @@ func (*PicAction) Execute(a *ActionInfo) bool {
145198
"🤖️:图片生成失败,请稍后再试~\n错误信息: %v", err), a.info.msgId)
146199
return false
147200
}
148-
replayImageByBase64(*a.ctx, bs64, a.info.msgId, a.info.sessionId,
201+
replayImageCardByBase64(*a.ctx, bs64, a.info.msgId, a.info.sessionId,
149202
a.info.qParsed)
150-
151-
//replayImageByBase64(*a.ctx, "", a.info.msgId, a.info.qParsed)
152203
return false
153204
}
154205

@@ -160,7 +211,7 @@ type MessageAction struct { /*消息*/
160211

161212
func (*MessageAction) Execute(a *ActionInfo) bool {
162213
msg := a.handler.sessionCache.GetMsg(*a.info.sessionId)
163-
msg = append(msg, services.Messages{
214+
msg = append(msg, openai.Messages{
164215
Role: "user", Content: a.info.qParsed,
165216
})
166217
completions, err := a.handler.gpt.Completions(msg)
@@ -224,10 +275,10 @@ func (*AudioAction) Execute(a *ActionInfo) bool {
224275
text, err := a.handler.gpt.AudioToText(output)
225276
if err != nil {
226277
fmt.Println(err)
227-
sendMsg(*a.ctx, "🤖️:语音转换失败,请稍后再试~", a.info.msgId)
278+
279+
sendMsg(*a.ctx, fmt.Sprintf("🤖️:语音转换失败,请稍后再试~\n错误信息: %v", err), a.info.msgId)
228280
return false
229281
}
230-
//删除文件
231282
//fmt.Println("text: ", text)
232283
a.info.qParsed = text
233284
return true

code/handlers/handler.go

+68-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"start-feishubot/initialization"
88
"start-feishubot/services"
9+
"start-feishubot/services/openai"
910
"strings"
1011

1112
larkcard "github.com/larksuite/oapi-sdk-go/v3/card"
@@ -26,7 +27,7 @@ func chain(data *ActionInfo, actions ...Action) bool {
2627
type MessageHandler struct {
2728
sessionCache services.SessionServiceCacheInterface
2829
msgCache services.MsgCacheInterface
29-
gpt *services.ChatGPT
30+
gpt *openai.ChatGPT
3031
config initialization.Config
3132
}
3233

@@ -36,6 +37,7 @@ func (m MessageHandler) cardHandler(_ context.Context,
3637
actionValue := cardAction.Action.Value
3738
actionValueJson, _ := json.Marshal(actionValue)
3839
json.Unmarshal(actionValueJson, &cardMsg)
40+
//fmt.Println("cardMsg: ", cardMsg)
3941
if cardMsg.Kind == ClearCardKind {
4042
newCard, err, done := CommonProcessClearCache(cardMsg, m.sessionCache)
4143
if done {
@@ -44,15 +46,28 @@ func (m MessageHandler) cardHandler(_ context.Context,
4446
return nil, nil
4547
}
4648
if cardMsg.Kind == PicResolutionKind {
47-
CommonProcessPicResolution(cardMsg, cardAction, m.sessionCache)
49+
//todo: 暂时不允许 以图搜图 模式下的 再来一张
50+
//CommonProcessPicResolution(cardMsg, cardAction, m.sessionCache)
4851
return nil, nil
4952
}
50-
if cardMsg.Kind == PicMoreKind {
53+
if cardMsg.Kind == PicTextMoreKind {
5154
go func() {
5255
m.CommonProcessPicMore(cardMsg)
5356
}()
5457
}
58+
if cardMsg.Kind == PicVarMoreKind {
59+
go func() {
60+
m.CommonProcessPicMore(cardMsg)
61+
}()
62+
}
63+
if cardMsg.Kind == PicModeChangeKind {
64+
newCard, err, done := CommonProcessPicModeChange(cardMsg, m.sessionCache)
65+
if done {
66+
return newCard, err
67+
}
68+
return nil, nil
5569

70+
}
5671
return nil, nil
5772

5873
}
@@ -63,7 +78,7 @@ func (m MessageHandler) CommonProcessPicMore(msg CardMsg) {
6378
//fmt.Println("msg: ", msg)
6479
question := msg.Value.(string)
6580
bs64, _ := m.gpt.GenerateOneImage(question, resolution)
66-
replayImageByBase64(context.Background(), bs64, &msg.MsgId,
81+
replayImageCardByBase64(context.Background(), bs64, &msg.MsgId,
6782
&msg.SessionId, question)
6883
}
6984

@@ -100,18 +115,60 @@ func CommonProcessClearCache(cardMsg CardMsg, session services.SessionServiceCac
100115
return nil, nil, false
101116
}
102117

118+
func CommonProcessPicModeChange(cardMsg CardMsg,
119+
session services.SessionServiceCacheInterface) (
120+
interface{}, error, bool) {
121+
if cardMsg.Value == "1" {
122+
123+
sessionId := cardMsg.SessionId
124+
session.Clear(sessionId)
125+
session.SetMode(sessionId,
126+
services.ModePicCreate)
127+
session.SetPicResolution(sessionId,
128+
services.Resolution256)
129+
130+
newCard, _ :=
131+
newSendCard(
132+
withHeader("🖼️ 已进入图片创作模式", larkcard.TemplateBlue),
133+
withPicResolutionBtn(&sessionId),
134+
withNote("提醒:回复文本或图片,让AI生成相关的图片。"))
135+
return newCard, nil, true
136+
}
137+
if cardMsg.Value == "0" {
138+
newCard, _ := newSendCard(
139+
withHeader("️🎒 机器人提醒", larkcard.TemplateGreen),
140+
withMainMd("依旧保留此话题的上下文信息"),
141+
withNote("我们可以继续探讨这个话题,期待和您聊天。如果您有其他问题或者想要讨论的话题,请告诉我哦"),
142+
)
143+
return newCard, nil, true
144+
}
145+
return nil, nil, false
146+
}
147+
func judgeMsgType(event *larkim.P2MessageReceiveV1) (string, error) {
148+
msgType := event.Event.Message.MessageType
149+
150+
switch *msgType {
151+
case "text", "image", "audio":
152+
return *msgType, nil
153+
default:
154+
return "", fmt.Errorf("unknown message type: %v", *msgType)
155+
}
156+
157+
}
158+
103159
func (m MessageHandler) msgReceivedHandler(ctx context.Context, event *larkim.P2MessageReceiveV1) error {
104160
handlerType := judgeChatType(event)
105161
if handlerType == "otherChat" {
106162
fmt.Println("unknown chat type")
107163
return nil
108164
}
109-
msgType := judgeMsgType(event)
110-
if msgType != "text" && msgType != "audio" {
111-
fmt.Println("unknown msg type")
165+
//fmt.Println(larkcore.Prettify(event.Event.Message))
166+
167+
msgType, err := judgeMsgType(event)
168+
if err != nil {
169+
fmt.Printf("error getting message type: %v\n", err)
112170
return nil
113171
}
114-
//fmt.Println(larkcore.Prettify(event.Event.Message))
115172

116173
content := event.Event.Message.Content
117174
msgId := event.Event.Message.MessageId
@@ -130,6 +187,7 @@ func (m MessageHandler) msgReceivedHandler(ctx context.Context, event *larkim.P2
130187
chatId: chatId,
131188
qParsed: strings.Trim(parseContent(*content), " "),
132189
fileKey: parseFileKey(*content),
190+
imageKey: parseImageKey(*content),
133191
sessionId: sessionId,
134192
mention: mention,
135193
}
@@ -142,11 +200,11 @@ func (m MessageHandler) msgReceivedHandler(ctx context.Context, event *larkim.P2
142200
&ProcessedUniqueAction{}, //避免重复处理
143201
&ProcessMentionAction{}, //判断机器人是否应该被调用
144202
&AudioAction{}, //语音处理
203+
&PicAction{}, //图片处理
145204
&EmptyAction{}, //空消息处理
146205
&ClearAction{}, //清除消息处理
147206
&HelpAction{}, //帮助处理
148207
&RolePlayAction{}, //角色扮演处理
149-
&PicAction{}, //图片处理
150208
&MessageAction{}, //消息处理
151209

152210
}
@@ -156,7 +214,7 @@ func (m MessageHandler) msgReceivedHandler(ctx context.Context, event *larkim.P2
156214

157215
var _ MessageHandlerInterface = (*MessageHandler)(nil)
158216

159-
func NewMessageHandler(gpt *services.ChatGPT,
217+
func NewMessageHandler(gpt *openai.ChatGPT,
160218
config initialization.Config) MessageHandlerInterface {
161219
return &MessageHandler{
162220
sessionCache: services.GetSessionCache(),

code/handlers/init.go

+2-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package handlers
33
import (
44
"context"
55
"start-feishubot/initialization"
6-
"start-feishubot/services"
6+
"start-feishubot/services/openai"
77

88
larkcard "github.com/larksuite/oapi-sdk-go/v3/card"
99
larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
@@ -24,7 +24,7 @@ const (
2424
// handlers 所有消息类型类型的处理器
2525
var handlers MessageHandlerInterface
2626

27-
func InitHandlers(gpt *services.ChatGPT, config initialization.Config) {
27+
func InitHandlers(gpt *openai.ChatGPT, config initialization.Config) {
2828
handlers = NewMessageHandler(gpt, config)
2929
}
3030

@@ -69,18 +69,3 @@ func judgeChatType(event *larkim.P2MessageReceiveV1) HandlerType {
6969
}
7070
return "otherChat"
7171
}
72-
73-
func judgeMsgType(event *larkim.P2MessageReceiveV1) string {
74-
msgType := event.Event.Message.MessageType
75-
if *msgType == "text" {
76-
return "text"
77-
}
78-
if *msgType == "image" {
79-
return "image"
80-
}
81-
if *msgType == "audio" {
82-
return "audio"
83-
}
84-
85-
return ""
86-
}

0 commit comments

Comments
 (0)