Files
rag-local/kb/controller/message_controller.go
2026-08-07 13:18:53 +08:00

82 lines
2.1 KiB
Go

package controller
import (
"context"
"encoding/json"
"time"
"rag-local/kb/model/domain"
"rag-local/kb/model/dto"
"rag-local/kb/service"
"github.com/gogf/gf/v2/frame/g"
)
type message struct{}
var Message = &message{}
func (c *message) List(ctx context.Context, req *dto.ListMessageReq) (*dto.ListMessageRes, error) {
list, err := service.MessageService.List(ctx, req.ConversationId)
if err != nil {
return nil, err
}
return &dto.ListMessageRes{List: list}, nil
}
// Chat RAG 问答 SSE 流式:citations → delta* → done / error
func (c *message) Chat(ctx context.Context, req *dto.ChatReq) (*dto.ChatRes, error) {
r := g.RequestFromCtx(ctx)
r.Response.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
r.Response.Header().Set("Cache-Control", "no-cache")
r.Response.Header().Set("X-Accel-Buffering", "no")
r.Response.Header().Set("Connection", "keep-alive")
send := func(event string, data any) bool {
buf, err := json.Marshal(data)
if err != nil {
return false
}
if event != "" {
r.Response.Write("event: " + event + "\n")
}
r.Response.Write("data: " + string(buf) + "\n\n")
r.Response.Flush()
return true
}
// 心跳:长回答期间保持连接,避免网关断流
stopHeartbeat := make(chan struct{})
defer close(stopHeartbeat)
go func() {
ticker := time.NewTicker(15 * time.Second)
defer ticker.Stop()
for {
select {
case <-stopHeartbeat:
return
case <-ticker.C:
r.Response.Write(": ping\n\n")
r.Response.Flush()
}
}
}()
_, _, _, err := service.MessageService.Chat(ctx, req.ConversationId, req.DatasetId, req.Question,
func(citations []domain.Citation, conversationId int64) {
send("citations", map[string]any{"conversation_id": conversationId, "citations": citations})
},
func(delta string) {
send("delta", map[string]string{"content": delta})
},
func(thinking string) {
send("thinking", map[string]string{"type": "thinking", "message": thinking})
})
if err != nil {
send("error", map[string]string{"message": err.Error()})
return nil, nil
}
send("done", map[string]string{"status": "ok"})
return nil, nil
}