feat: implement ChatbotService for RAG-based AI interactions and history management
Build and Release / release (push) Successful in 1m17s
Build and Release / release (push) Successful in 1m17s
This commit is contained in:
@@ -2,7 +2,6 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"history-api/internal/dtos/request"
|
"history-api/internal/dtos/request"
|
||||||
"history-api/internal/gen/sqlc"
|
"history-api/internal/gen/sqlc"
|
||||||
@@ -11,8 +10,10 @@ import (
|
|||||||
"history-api/pkg/ai"
|
"history-api/pkg/ai"
|
||||||
"history-api/pkg/constants"
|
"history-api/pkg/constants"
|
||||||
"history-api/pkg/convert"
|
"history-api/pkg/convert"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgtype"
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatbotService interface {
|
type ChatbotService interface {
|
||||||
@@ -43,23 +44,32 @@ func (s *chatbotService) Chat(ctx context.Context, userID string, projectID *str
|
|||||||
}
|
}
|
||||||
|
|
||||||
if usage >= constants.MaxDailyAIUsage {
|
if usage >= constants.MaxDailyAIUsage {
|
||||||
return "", errors.New("you have reached your daily limit of 10 questions. Please come back tomorrow")
|
return "", fmt.Errorf("you have reached your daily limit of %d questions. Please come back tomorrow", constants.MaxDailyAIUsage)
|
||||||
}
|
}
|
||||||
|
|
||||||
qVector, err := s.ragUtils.EmbedQuery(ctx, question)
|
qVector, err := s.ragUtils.EmbedQuery(ctx, question)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to embed question: %w", err)
|
return "", fmt.Errorf("failed to embed question: %w", err)
|
||||||
}
|
}
|
||||||
results, err := s.repo.SearchSimilar(ctx, projectID, qVector, 5, 0.65)
|
|
||||||
|
results, err := s.repo.SearchSimilar(ctx, projectID, qVector, 8, 0.50)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to search similar content: %w", err)
|
return "", fmt.Errorf("failed to search similar content: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
contextStr := ""
|
if len(results) < 3 {
|
||||||
for i, res := range results {
|
broadResults, err := s.repo.SearchSimilar(ctx, projectID, qVector, 8, 0.35)
|
||||||
contextStr += fmt.Sprintf("[Document %d]: %s\n", i+1, res.Content)
|
if err == nil && len(broadResults) > len(results) {
|
||||||
|
results = broadResults
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var contextBuilder strings.Builder
|
||||||
|
for i, res := range results {
|
||||||
|
contextBuilder.WriteString(fmt.Sprintf("[Document %d (score: %.2f)]: %s\n", i+1, res.Similarity, res.Content))
|
||||||
|
}
|
||||||
|
contextStr := contextBuilder.String()
|
||||||
|
|
||||||
pgUserID, err := convert.StringToUUID(userID)
|
pgUserID, err := convert.StringToUUID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("invalid user id: %w", err)
|
return "", fmt.Errorf("invalid user id: %w", err)
|
||||||
@@ -70,13 +80,14 @@ func (s *chatbotService) Chat(ctx context.Context, userID string, projectID *str
|
|||||||
Limit: 10,
|
Limit: 10,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Warning: failed to get chatbot history: %v\n", err)
|
log.Warn().Err(err).Msg("failed to get chatbot history")
|
||||||
}
|
}
|
||||||
|
|
||||||
historyStr := ""
|
var historyBuilder strings.Builder
|
||||||
for _, h := range histories {
|
for _, h := range histories {
|
||||||
historyStr += fmt.Sprintf("User: %s\nAssistant: %s\n\n", h.Question, h.Answer)
|
historyBuilder.WriteString(fmt.Sprintf("User: %s\nAssistant: %s\n\n", h.Question, h.Answer))
|
||||||
}
|
}
|
||||||
|
historyStr := historyBuilder.String()
|
||||||
|
|
||||||
var prompt string
|
var prompt string
|
||||||
if contextStr == "" {
|
if contextStr == "" {
|
||||||
@@ -115,7 +126,9 @@ Question: %s`, contextStr, historyStr, question)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
_, _ = s.usageRepo.IncrementAIUsage(ctx, userID)
|
if _, err := s.usageRepo.IncrementAIUsage(ctx, userID); err != nil {
|
||||||
|
log.Warn().Err(err).Str("userID", userID).Msg("failed to increment AI usage")
|
||||||
|
}
|
||||||
|
|
||||||
_, err = s.chatRepo.CreateChatbotHistory(ctx, sqlc.CreateChatbotHistoryParams{
|
_, err = s.chatRepo.CreateChatbotHistory(ctx, sqlc.CreateChatbotHistoryParams{
|
||||||
UserID: pgUserID,
|
UserID: pgUserID,
|
||||||
@@ -123,7 +136,7 @@ Question: %s`, contextStr, historyStr, question)
|
|||||||
Answer: response,
|
Answer: response,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Warning: failed to save chatbot history: %v\n", err)
|
log.Warn().Err(err).Msg("failed to save chatbot history")
|
||||||
}
|
}
|
||||||
|
|
||||||
return response, nil
|
return response, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user