ai_service.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package service
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "github.com/2930134478/AI-CS/backend/models"
  8. "github.com/2930134478/AI-CS/backend/repository"
  9. "github.com/2930134478/AI-CS/backend/utils"
  10. "gorm.io/gorm"
  11. )
  12. // AIService AI 服务(负责调用 AI 生成回复)
  13. type AIService struct {
  14. aiConfigRepo *repository.AIConfigRepository
  15. messageRepo *repository.MessageRepository
  16. conversationRepo *repository.ConversationRepository
  17. providerFactory *AIProviderFactory
  18. }
  19. // NewAIService 创建 AI 服务实例。
  20. func NewAIService(
  21. aiConfigRepo *repository.AIConfigRepository,
  22. messageRepo *repository.MessageRepository,
  23. conversationRepo *repository.ConversationRepository,
  24. ) *AIService {
  25. return &AIService{
  26. aiConfigRepo: aiConfigRepo,
  27. messageRepo: messageRepo,
  28. conversationRepo: conversationRepo,
  29. providerFactory: NewAIProviderFactory(),
  30. }
  31. }
  32. // GenerateAIResponse 为对话生成 AI 回复。
  33. // conversationID: 对话ID
  34. // userMessage: 用户消息
  35. // userID: 用户ID(用于回退查找 AI 配置)
  36. // 返回: AI 回复内容,如果失败返回错误
  37. func (s *AIService) GenerateAIResponse(conversationID uint, userMessage string, userID uint) (string, error) {
  38. // 1. 获取对话信息,优先使用对话绑定的 AI 配置
  39. conversation, err := s.conversationRepo.GetByID(conversationID)
  40. if err != nil {
  41. return "", fmt.Errorf("获取对话失败: %v", err)
  42. }
  43. var config *models.AIConfig
  44. if conversation.AIConfigID != nil {
  45. // 使用对话绑定的配置(多厂商支持)
  46. config, err = s.aiConfigRepo.GetByID(*conversation.AIConfigID)
  47. if err != nil {
  48. return "", fmt.Errorf("获取 AI 配置失败: %v", err)
  49. }
  50. // 验证配置是否启用
  51. if !config.IsActive {
  52. return "", errors.New("该模型配置已禁用")
  53. }
  54. } else {
  55. // 回退:使用用户默认配置(向后兼容)
  56. config, err = s.aiConfigRepo.GetActiveByUserID(userID, "text")
  57. if err != nil {
  58. if errors.Is(err, gorm.ErrRecordNotFound) {
  59. return "", errors.New("未找到 AI 配置,请先在设置中配置 AI 服务")
  60. }
  61. return "", fmt.Errorf("获取 AI 配置失败: %v", err)
  62. }
  63. }
  64. // 2. 解密 API Key
  65. apiKey, err := utils.DecryptAPIKey(config.APIKey)
  66. if err != nil {
  67. return "", fmt.Errorf("解密 API Key 失败: %v", err)
  68. }
  69. // 3. 获取对话历史(用于上下文)
  70. history, err := s.buildConversationHistory(conversationID)
  71. if err != nil {
  72. log.Printf("⚠️ 获取对话历史失败: %v", err)
  73. // 即使获取历史失败,也继续处理(使用空历史)
  74. history = []MessageHistory{}
  75. }
  76. // 4. 解析适配器配置(如果有)
  77. var adapterConfig *AdapterConfig
  78. if config.AdapterConfig != "" {
  79. if err := json.Unmarshal([]byte(config.AdapterConfig), &adapterConfig); err != nil {
  80. log.Printf("⚠️ 解析适配器配置失败: %v,使用默认配置", err)
  81. }
  82. }
  83. // 5. 创建 AI 提供商
  84. aiConfig := AIConfig{
  85. APIURL: config.APIURL,
  86. APIKey: apiKey,
  87. Model: config.Model,
  88. ModelType: config.ModelType,
  89. Provider: config.Provider,
  90. AdapterConfig: adapterConfig,
  91. }
  92. provider, err := s.providerFactory.CreateProvider(aiConfig)
  93. if err != nil {
  94. return "", fmt.Errorf("创建 AI 提供商失败: %v", err)
  95. }
  96. // 6. 调用 AI 生成回复
  97. response, err := provider.GenerateResponse(history, userMessage)
  98. if err != nil {
  99. // AI 调用失败,返回友好的错误消息
  100. log.Printf("❌ AI 调用失败: %v", err)
  101. return "AI客服好像出了点差错,请联系人工客服解决", nil
  102. }
  103. return response, nil
  104. }
  105. // buildConversationHistory 构建对话历史(用于 AI 上下文)。
  106. func (s *AIService) buildConversationHistory(conversationID uint) ([]MessageHistory, error) {
  107. // 获取最近的对话消息(最多 10 条,避免上下文过长)
  108. messages, err := s.messageRepo.ListByConversationID(conversationID)
  109. if err != nil {
  110. return nil, err
  111. }
  112. // 只取最近 10 条消息
  113. startIdx := 0
  114. if len(messages) > 10 {
  115. startIdx = len(messages) - 10
  116. }
  117. history := make([]MessageHistory, 0)
  118. for i := startIdx; i < len(messages); i++ {
  119. msg := messages[i]
  120. // 跳过系统消息
  121. if msg.MessageType == "system_message" {
  122. continue
  123. }
  124. role := "user"
  125. if msg.SenderIsAgent {
  126. role = "assistant"
  127. }
  128. history = append(history, MessageHistory{
  129. Role: role,
  130. Content: msg.Content,
  131. })
  132. }
  133. return history, nil
  134. }