From 6328ff0f188a33bde9fd4b167a426a77e94bf604 Mon Sep 17 00:00:00 2001 From: Yiyang Kang Date: Sun, 2 Feb 2025 15:30:08 +0900 Subject: [PATCH] feat: add reasoning command --- bot.go | 1 + botcmd_reason.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 1 + 3 files changed, 67 insertions(+) create mode 100644 botcmd_reason.go diff --git a/bot.go b/bot.go index b59b099..2818f4f 100644 --- a/bot.go +++ b/bot.go @@ -38,6 +38,7 @@ func initBot() (*tele.Bot, error) { b.Handle("/year_progress", handleYearProgressCmd) b.Handle("/xr", handleExchangeRateCmd) + b.Handle("/reason", handleReasonCmd) b.Handle("/tr", handleTranslateCmd) for _, tbtn := range translateBtns { b.Handle(tbtn, handleTranslateBtn) diff --git a/botcmd_reason.go b/botcmd_reason.go new file mode 100644 index 0000000..b0763e4 --- /dev/null +++ b/botcmd_reason.go @@ -0,0 +1,65 @@ +package main + +import ( + "regexp" + "strings" + + tele "gopkg.in/telebot.v3" + + "git.gensokyo.cafe/kkyy/tgbot_misaka_5882f7/openai" +) + +var ( + reasonCmdRe = regexp.MustCompile(`^\s*\/reason(@\S*)?\s*`) + reasoningIndicatorMessage = "🤔💭 Thinking..." +) + +func handleReasonCmd(c tele.Context) error { + msg := c.Message() + if msg == nil { + return nil + } + + payload := strings.TrimSpace(reasonCmdRe.ReplaceAllString(msg.Text, "")) + if payload == "" { + return c.Reply("Usage: `/reason `", + &tele.SendOptions{ParseMode: tele.ModeMarkdown}, + tele.Silent, + ) + } + + req := openai.ChatRequest{ + Model: openai.ModelO1Mini, + Messages: []openai.ChatMessage{ + { + Role: openai.ChatRoleUser, + Content: payload, + }, + }, + // reasoning_effort is only available to `o1` and `o3-mini`, which is not yet accessible. + // ReasoningEffort: openai.ReasoningEffortHigh, + } + + replyMsg, err := c.Bot().Reply(msg, reasoningIndicatorMessage, tele.Silent) + if err != nil { + logger.Errorw("assistant: failed to complete reasoning request", "error", err) + return c.Reply("Sorry, there's a technical issue. 😵💫 Please try again later.", tele.Silent) + } + err = assistantStreamedResponse(req, func(text string, finished bool) error { + var err error + replyMsg, err = c.Bot().Edit(replyMsg, text) + if finished && err == nil { + replyMsg.ReplyTo = msg // nasty bug + if err := cacheMessage(replyMsg); err != nil { + logger.Warnw("failed to cache message", "error", err) + } + } + return err + }) + + if err != nil { + logger.Errorw("assistant: failed to complete reasoning request", "error", err) + return c.Reply("Sorry, there's a technical issue. 😵💫 Please try again later.", tele.Silent) + } + return nil +} diff --git a/main.go b/main.go index b009728..38936ba 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ func runBot() { logger.Info("Announcing commands...") if err = bot.SetCommands([]tele.Command{ + {Text: "reason", Description: "Think."}, {Text: "tr", Description: "Translate text"}, {Text: "kanji", Description: "Help with pronunciation of Kanji"}, {Text: "xr", Description: "Currency exchange rates"},