ai_provider.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. package service
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net/http"
  9. "time"
  10. )
  11. // AIProvider AI 服务提供商接口(可扩展设计)
  12. // 不同的 AI 服务提供商需要实现这个接口
  13. type AIProvider interface {
  14. // GenerateResponse 生成 AI 回复
  15. // conversationHistory: 对话历史(用于上下文)
  16. // userMessage: 用户当前消息
  17. // 返回: AI 回复内容
  18. GenerateResponse(conversationHistory []MessageHistory, userMessage string) (string, error)
  19. }
  20. // AdapterConfig 适配器配置(用于适配不同服务商的 API 格式差异)
  21. type AdapterConfig struct {
  22. // 认证头格式(默认:Bearer)
  23. AuthHeader string `json:"auth_header"` // 例如:"Bearer"、"X-API-Key"、"Authorization"
  24. // 响应解析路径(默认:choices[0].message.content)
  25. ResponsePath string `json:"response_path"` // 例如:"choices[0].message.content"、"data.text"、"result.content"
  26. // 请求格式自定义(可选)
  27. RequestFormat map[string]interface{} `json:"request_format"` // 用于覆盖默认的请求格式
  28. }
  29. // MessageHistory 对话历史记录
  30. type MessageHistory struct {
  31. Role string `json:"role"` // "user" 或 "assistant"
  32. Content string `json:"content"` // 消息内容
  33. }
  34. // AIConfig 用于 AI 调用的配置信息
  35. type AIConfig struct {
  36. APIURL string
  37. APIKey string
  38. Model string
  39. ModelType string
  40. Provider string
  41. AdapterConfig *AdapterConfig // 适配器配置(用于适配不同服务商的差异)
  42. }
  43. // UniversalAIProvider 通用 AI 服务提供商(支持所有 OpenAI 兼容格式)
  44. // 通过适配器配置来适配不同服务商的细微差异
  45. // 这样 90% 的服务商都可以用同一个 Provider,无需单独实现
  46. type UniversalAIProvider struct {
  47. config AIConfig
  48. client *http.Client
  49. adapter *AdapterConfig
  50. }
  51. // NewUniversalAIProvider 创建通用 AI 提供商实例。
  52. func NewUniversalAIProvider(config AIConfig) *UniversalAIProvider {
  53. // 设置默认适配器配置
  54. adapter := config.AdapterConfig
  55. if adapter == nil {
  56. adapter = &AdapterConfig{
  57. AuthHeader: "Bearer", // 默认使用 Bearer Token
  58. ResponsePath: "choices[0].message.content", // 默认 OpenAI 格式
  59. }
  60. } else {
  61. // 设置默认值
  62. if adapter.AuthHeader == "" {
  63. adapter.AuthHeader = "Bearer"
  64. }
  65. if adapter.ResponsePath == "" {
  66. adapter.ResponsePath = "choices[0].message.content"
  67. }
  68. }
  69. return &UniversalAIProvider{
  70. config: config,
  71. client: &http.Client{
  72. Timeout: 30 * time.Second, // 30 秒超时
  73. },
  74. adapter: adapter,
  75. }
  76. }
  77. // GenerateResponse 生成 AI 回复(支持 OpenAI 兼容格式,通过适配器适配不同服务商)。
  78. func (p *UniversalAIProvider) GenerateResponse(conversationHistory []MessageHistory, userMessage string) (string, error) {
  79. // 根据模型类型选择不同的处理逻辑
  80. switch p.config.ModelType {
  81. case "text":
  82. return p.generateTextResponse(conversationHistory, userMessage)
  83. case "image":
  84. // 图片生成(未来扩展)
  85. return "", fmt.Errorf("图片模型暂未支持")
  86. case "audio":
  87. // 语音识别/合成(未来扩展)
  88. return "", fmt.Errorf("语音模型暂未支持")
  89. case "video":
  90. // 视频生成(未来扩展)
  91. return "", fmt.Errorf("视频模型暂未支持")
  92. default:
  93. return "", fmt.Errorf("不支持的模型类型: %s", p.config.ModelType)
  94. }
  95. }
  96. // generateTextResponse 生成文本回复(通用实现,支持所有 OpenAI 兼容格式)。
  97. func (p *UniversalAIProvider) generateTextResponse(conversationHistory []MessageHistory, userMessage string) (string, error) {
  98. // 构建消息列表(包含历史对话和当前消息)
  99. messages := make([]map[string]string, 0)
  100. // 添加历史对话
  101. for _, history := range conversationHistory {
  102. messages = append(messages, map[string]string{
  103. "role": history.Role,
  104. "content": history.Content,
  105. })
  106. }
  107. // 添加当前用户消息
  108. messages = append(messages, map[string]string{
  109. "role": "user",
  110. "content": userMessage,
  111. })
  112. // 构建请求体(OpenAI 兼容格式)
  113. requestBody := map[string]interface{}{
  114. "model": p.config.Model,
  115. "messages": messages,
  116. }
  117. jsonData, err := json.Marshal(requestBody)
  118. if err != nil {
  119. return "", fmt.Errorf("序列化请求失败: %v", err)
  120. }
  121. // 创建 HTTP 请求
  122. req, err := http.NewRequest("POST", p.config.APIURL, bytes.NewBuffer(jsonData))
  123. if err != nil {
  124. return "", fmt.Errorf("创建请求失败: %v", err)
  125. }
  126. // 设置请求头
  127. req.Header.Set("Content-Type", "application/json")
  128. // 根据适配器配置设置认证头
  129. authValue := p.config.APIKey
  130. if p.adapter.AuthHeader == "Bearer" {
  131. authValue = "Bearer " + p.config.APIKey
  132. req.Header.Set("Authorization", authValue)
  133. } else if p.adapter.AuthHeader == "X-API-Key" {
  134. req.Header.Set("X-API-Key", p.config.APIKey)
  135. } else {
  136. // 默认使用 Authorization: Bearer
  137. req.Header.Set("Authorization", "Bearer "+p.config.APIKey)
  138. }
  139. // 发送请求
  140. resp, err := p.client.Do(req)
  141. if err != nil {
  142. return "", fmt.Errorf("请求失败: %v", err)
  143. }
  144. defer resp.Body.Close()
  145. // 读取响应
  146. body, err := io.ReadAll(resp.Body)
  147. if err != nil {
  148. return "", fmt.Errorf("读取响应失败: %v", err)
  149. }
  150. // 检查 HTTP 状态码
  151. if resp.StatusCode != http.StatusOK {
  152. return "", fmt.Errorf("API 返回错误: %s (状态码: %d)", string(body), resp.StatusCode)
  153. }
  154. // 解析响应(支持灵活的响应路径)
  155. var responseData map[string]interface{}
  156. if err := json.Unmarshal(body, &responseData); err != nil {
  157. return "", fmt.Errorf("解析响应失败: %v", err)
  158. }
  159. // 检查是否有错误字段
  160. if errorMsg, ok := responseData["error"].(map[string]interface{}); ok {
  161. if msg, ok := errorMsg["message"].(string); ok {
  162. return "", fmt.Errorf("API 错误: %s", msg)
  163. }
  164. }
  165. // 根据适配器配置的响应路径提取内容
  166. content, err := p.extractResponseContent(responseData, p.adapter.ResponsePath)
  167. if err != nil {
  168. return "", err
  169. }
  170. if content == "" {
  171. return "", errors.New("API 返回空内容")
  172. }
  173. return content, nil
  174. }
  175. // extractResponseContent 根据响应路径提取内容(支持灵活的路径配置)。
  176. // 例如:"choices[0].message.content" 或 "data.text" 或 "result.content"
  177. func (p *UniversalAIProvider) extractResponseContent(data map[string]interface{}, path string) (string, error) {
  178. // 默认路径:choices[0].message.content(OpenAI 格式)
  179. if path == "" || path == "choices[0].message.content" {
  180. // 尝试 OpenAI 格式
  181. if choices, ok := data["choices"].([]interface{}); ok && len(choices) > 0 {
  182. if choice, ok := choices[0].(map[string]interface{}); ok {
  183. if message, ok := choice["message"].(map[string]interface{}); ok {
  184. if content, ok := message["content"].(string); ok {
  185. return content, nil
  186. }
  187. }
  188. }
  189. }
  190. }
  191. // 尝试其他常见格式
  192. // 格式1: data.text
  193. if dataObj, ok := data["data"].(map[string]interface{}); ok {
  194. if text, ok := dataObj["text"].(string); ok {
  195. return text, nil
  196. }
  197. }
  198. // 格式2: result.content
  199. if result, ok := data["result"].(map[string]interface{}); ok {
  200. if content, ok := result["content"].(string); ok {
  201. return content, nil
  202. }
  203. }
  204. // 格式3: content(直接字段)
  205. if content, ok := data["content"].(string); ok {
  206. return content, nil
  207. }
  208. // 格式4: text(直接字段)
  209. if text, ok := data["text"].(string); ok {
  210. return text, nil
  211. }
  212. return "", errors.New("无法从响应中提取内容,请检查响应格式或配置适配器")
  213. }
  214. // AIProviderFactory AI 提供商工厂(用于创建不同类型的提供商)
  215. type AIProviderFactory struct{}
  216. // NewAIProviderFactory 创建 AI 提供商工厂实例。
  217. func NewAIProviderFactory() *AIProviderFactory {
  218. return &AIProviderFactory{}
  219. }
  220. // CreateProvider 根据配置创建对应的 AI 提供商。
  221. // 设计理念:
  222. // 所有主流 AI 服务商都使用 REST API(HTTP/HTTPS),统一使用 UniversalAIProvider 处理
  223. // 通过 AdapterConfig 适配不同服务商的细微差异(认证头、响应路径等)
  224. func (f *AIProviderFactory) CreateProvider(config AIConfig) (AIProvider, error) {
  225. // 所有服务商都使用 REST API,统一处理
  226. return NewUniversalAIProvider(config), nil
  227. }