Files
rag-local/kb/service/message_service.go
T
2026-08-05 10:28:44 +08:00

84 lines
2.4 KiB
Go

package service
import (
"context"
"encoding/json"
"rag-local/kb/dao"
"rag-local/kb/model/domain"
"rag-local/kb/model/entity"
"github.com/cloudwego/eino/schema"
"github.com/gogf/gf/v2/errors/gerror"
)
var MessageService = &messageService{}
type messageService struct{}
func (s *messageService) List(ctx context.Context, conversationId int64) ([]*entity.Message, error) {
return dao.Message.List(ctx, conversationId)
}
// Chat RAG 问答:会话解析 → 用户消息落库 → 工作流流式生成 → 助手消息+引用落库。
// onCitations 在检索完成后回调(先于流式输出);onDelta 接收模型增量文本。
func (s *messageService) Chat(ctx context.Context, conversationId, datasetId int64, question string, onCitations func([]domain.Citation, int64), onDelta func(string)) (string, []domain.Citation, int64, error) {
if conversationId <= 0 {
title := question
if r := []rune(title); len(r) > 20 {
title = string(r[:20])
}
id, err := dao.Conversation.Insert(ctx, datasetId, title)
if err != nil {
return "", nil, 0, err
}
conversationId = id
}
conv, err := dao.Conversation.GetOne(ctx, conversationId)
if err != nil {
return "", nil, 0, err
}
if conv == nil {
return "", nil, 0, gerror.New("会话不存在")
}
if conv.DatasetId == 0 && datasetId > 0 {
_ = dao.Conversation.UpdateDataset(ctx, conversationId, datasetId)
conv.DatasetId = datasetId
}
if conv.DatasetId > 0 {
datasetId = conv.DatasetId
}
if datasetId <= 0 {
return "", nil, 0, gerror.New("请选择知识库数据集")
}
if _, err := dao.Message.Insert(ctx, conversationId, "user", question, ""); err != nil {
return "", nil, 0, err
}
history, err := dao.Message.List(ctx, conversationId)
if err != nil {
return "", nil, 0, err
}
messages := make([]*schema.Message, 0, len(history))
for _, m := range history {
messages = append(messages, &schema.Message{Role: schema.RoleType(m.Role), Content: m.Content})
}
answer, citations, err := ChatService.Ask(ctx, datasetId, question, messages,
func(c []domain.Citation) {
if onCitations != nil {
onCitations(c, conversationId)
}
}, onDelta)
if err != nil {
return "", nil, 0, err
}
citJson, _ := json.Marshal(citations)
if _, err := dao.Message.Insert(ctx, conversationId, "assistant", answer, string(citJson)); err != nil {
return "", nil, 0, err
}
return answer, citations, conversationId, nil
}