From 3b673d5e2b3b47ce8836dce6f36888db9256b707 Mon Sep 17 00:00:00 2001 From: ScuroNeko Date: Fri, 6 Mar 2026 10:02:40 +0300 Subject: [PATCH] small fix --- Dockerfile | 2 ++ openai/api.go | 2 +- openai/sse.go | 37 ---------------------- plugins/rp.go | 78 ++++++++++++++++++++++++++++++++++++++-------- utils/ai/consts.go | 1 + 5 files changed, 69 insertions(+), 51 deletions(-) delete mode 100644 openai/sse.go diff --git a/Dockerfile b/Dockerfile index 08c681d..849c903 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ FROM alpine:3.23 AS runner WORKDIR /app +ENV TZ=Europe/Moscow ENV GOMEMLIMIT=256MiB COPY --from=builder /usr/local/bin/ymgb /app/ymgb CMD ["/app/ymgb"] +USER nobody diff --git a/openai/api.go b/openai/api.go index 24a4783..aa084a6 100644 --- a/openai/api.go +++ b/openai/api.go @@ -144,7 +144,7 @@ func (r *Request[P]) DoStreamWithContext(ctx context.Context, api *API) (iter.Se var zero AIResponse for { line, err := reader.ReadString('\n') - if err != nil && err != io.EOF { + if err != nil { yield(zero, err) return } diff --git a/openai/sse.go b/openai/sse.go deleted file mode 100644 index 60b881f..0000000 --- a/openai/sse.go +++ /dev/null @@ -1,37 +0,0 @@ -package openai - -import ( - "bufio" - "io" - "iter" - "strings" -) - -// Server-sent event - -func ReadSSE(r io.ReadCloser) iter.Seq[string] { - reader := bufio.NewReader(r) - return func(yield func(string) bool) { - for { - line, err := reader.ReadString('\n') - if err != nil { - return - } - if line == "" || line == "\n" { - continue - } - if strings.HasPrefix(line, "data: ") { - line = line[len("data: "):] - } - line = strings.TrimSpace(line) - line = strings.Trim(line, "\r") - line = strings.Trim(line, "\n") - if strings.HasPrefix(line, "[DONE]") { - return - } - if !yield(line) { - return - } - } - } -} diff --git a/plugins/rp.go b/plugins/rp.go index 6a7c899..101c611 100644 --- a/plugins/rp.go +++ b/plugins/rp.go @@ -4,9 +4,11 @@ import ( "database/sql" "errors" "fmt" + "io" "log" "strconv" "strings" + "sync" "time" "ymgb/database" "ymgb/database/mdb" @@ -479,7 +481,6 @@ func newChat(ctx *laniakea.MsgContext, db *database.Context) { return } - log.Println(ctx.Args) chatPrompt := "" settingId, err := strconv.Atoi(ctx.Args[0]) if err != nil { @@ -664,15 +665,50 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) { } answerContent := "" + type DraftQueue struct { + message string + mu sync.Mutex + } draft := ctx.NewDraft() - for r, err := range res { - if m != nil { - m.Delete() - m = nil - } + var mu sync.Mutex + buffer := strings.Builder{} // накапливаем фрагменты + ticker := time.NewTicker(time.Second) + done := make(chan struct{}) // сигнал завершения горутины + // Горутина для периодической отправки + go func() { + flush := func() { + mu.Lock() + msg := buffer.String() + buffer.Reset() + mu.Unlock() + if msg != "" { + if err := draft.Push(msg); err != nil { + log.Println(err) + } + } + } + for { + select { + case <-ticker.C: + // Каждую секунду отправляем накопленное + flush() + ctx.SendAction(tgapi.ChatActionTyping) + case <-done: + // Завершаем работу: отправляем остаток и выходим + flush() + ticker.Stop() + return + } + } + }() + for r, err := range res { if err != nil { + if errors.Is(err, io.EOF) { + break + } ctx.Error(err) + close(done) return } @@ -683,14 +719,30 @@ func generate(ctx *laniakea.MsgContext, db *database.Context) { if content == "" { continue } - answerContent += content - err = draft.Push(content) - if err != nil { - ctx.Error(err) - //draft.Flush() - break + + if m != nil { + m.Delete() + m = nil } - time.Sleep(time.Millisecond * 250) + answerContent += content + + mu.Lock() + buffer.WriteString(content) + mu.Unlock() + + // Если нужна искусственная задержка, оставьте: + // time.Sleep(time.Millisecond * 50) + } + + // Завершаем горутину и отправляем последнюю порцию + close(done) + if answerContent == "" { + if m != nil { + m.Delete() + m = nil + } + ctx.Answer("Не удалось сгенерировать ответ. Попробуйте снова") + return } counter := redisRpRep.GetCounter(ctx.FromID, waifuId) diff --git a/utils/ai/consts.go b/utils/ai/consts.go index eb50775..9ad3abb 100644 --- a/utils/ai/consts.go +++ b/utils/ai/consts.go @@ -3,5 +3,6 @@ package ai const GPTBaseUrl = "https://chat.gpt-chatbot.ru/api/openai" const CompressPrompt = "Сделай подробную выжимку нашего диалога. Сохрани все ключевые моменты(например сколько одежды, расположение, основные действия и фразы и тд.) из каждого сообщения, но никогда не копируй описание персонажа(цвет волос и глаз, характер и т.д.). Для моих сообщений используй обращение во втором лице(ты, вы), для своих в первом(я). Всегда называй вещи своими именами." +//Кратко подведите итоги содержимого беседы для использования в качестве последующего контекстного запроса, не более 200 слов //const PawanBaseURL = "https://api.pawan.krd" //var CosmoRPUrl = fmt.Sprintf("%s/cosmosrp-2.5", PawanBaseURL)