Files
common/ragflow/client.go
2026-03-12 08:51:00 +08:00

139 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package ragflow
import (
"context"
"net/http"
"net/url"
"strings"
"time"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
)
var (
// globalClient 全局 RAGFlow 客户端(单例,自动初始化)
globalClient *Client
)
// init 包初始化时自动创建全局客户端
func init() {
ctx := context.Background()
// 读取配置
baseURL, apiKey := loadConfig(ctx)
// 如果配置不完整,跳过初始化
if baseURL == "" || apiKey == "" {
g.Log().Warning(ctx, "⚠️ RAGFlow 配置未找到,请在项目 config.yml 中添加 ragflow.base_url 和 ragflow.api_key")
return
}
// 初始化全局客户端
httpClient := gclient.New()
httpClient.SetHeader("Authorization", "Bearer "+apiKey)
httpClient.SetHeader("Content-Type", "application/json")
httpClient.SetTimeout(60 * time.Second) // RAGFlow AI 推理需要较长时间
globalClient = &Client{
BaseURL: strings.TrimSuffix(baseURL, "/"),
APIKey: apiKey,
HTTPClient: httpClient,
}
g.Log().Infof(ctx, "✅ RAGFlow 全局客户端初始化成功: baseURL=%s", baseURL)
}
// loadConfig 从配置文件加载 RAGFlow 配置
func loadConfig(ctx context.Context) (baseURL, apiKey string) {
// 使用 GoFrame 全局配置(从项目的 config.yml 读取)
baseURL = g.Cfg().MustGet(ctx, "ragflow.base_url", "").String()
apiKey = g.Cfg().MustGet(ctx, "ragflow.api_key", "").String()
return
}
// GetGlobalClient 获取全局客户端
// 使用示例client := ragflow.GetGlobalClient()
func GetGlobalClient() *Client {
return globalClient
}
// Client RAGFlow API 客户端
type Client struct {
BaseURL string
APIKey string
HTTPClient *gclient.Client // HTTP 客户端
}
// CommonResponse 通用响应结构
type CommonResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// IsSuccess 检查响应是否成功
func (r *CommonResponse) IsSuccess() bool {
return r.Code == 0
}
// request 发送 HTTP 请求
func (c *Client) request(ctx context.Context, method, path string, body interface{}, result interface{}) (err error) {
fullURL := c.BaseURL + path
var reqBody string
if body != nil {
jsonData, err := gjson.Encode(body)
if err != nil {
return gerror.Newf("marshal request body failed: %v", err)
}
reqBody = string(jsonData)
}
var resp *gclient.Response
switch method {
case "GET":
resp, err = c.HTTPClient.Get(ctx, fullURL)
case "POST":
resp, err = c.HTTPClient.Post(ctx, fullURL, reqBody)
case "PUT":
resp, err = c.HTTPClient.Put(ctx, fullURL, reqBody)
case "DELETE":
resp, err = c.HTTPClient.Delete(ctx, fullURL, reqBody)
default:
return gerror.Newf("unsupported method: %s", method)
}
if err != nil {
return gerror.Newf("http request failed: %v", err)
}
defer resp.Close()
if resp.StatusCode != http.StatusOK {
return gerror.Newf("http request failed with status: %d", resp.StatusCode)
}
respBody := resp.ReadAll()
if err = gjson.DecodeTo(respBody, result); err != nil {
return gerror.Newf("unmarshal response failed: %v", err)
}
return
}
// buildQueryString 构建查询字符串
func buildQueryString(params map[string]interface{}) string {
if len(params) == 0 {
return ""
}
parts := make([]string, 0, len(params))
for k, v := range params {
parts = append(parts, url.QueryEscape(k)+"="+url.QueryEscape(g.NewVar(v).String()))
}
return strings.Join(parts, "&")
}