From 5d4c8c8711e6cf71a0d393b9f05f252e2c8b7842 Mon Sep 17 00:00:00 2001 From: Cold <16419454+cold502@user.noreply.gitee.com> Date: Tue, 2 Dec 2025 14:59:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9rag=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ragflow/agent.go | 24 ++++++++++++------- ragflow/chat.go | 8 +++---- ragflow/chunk.go | 11 +++++---- ragflow/dataset.go | 9 +++---- ragflow/document.go | 58 +++++++++++++++++++++++++++++++++------------ ragflow/session.go | 8 +++---- 6 files changed, 78 insertions(+), 40 deletions(-) diff --git a/ragflow/agent.go b/ragflow/agent.go index 7e0ed1e..4ce263a 100644 --- a/ragflow/agent.go +++ b/ragflow/agent.go @@ -10,10 +10,17 @@ import ( // Agent Agent 结构体 type Agent struct { - ID string `json:"id"` - Title string `json:"title"` - Description string `json:"description"` - DSL map[string]interface{} `json:"dsl"` // Canvas DSL 对象 + ID string `json:"id"` // Agent ID + Title string `json:"title"` // Agent 标题 + Description string `json:"description"` // Agent 描述 + Avatar string `json:"avatar"` // 头像(Base64 编码) + CanvasType string `json:"canvas_type"` // 画布类型 + CreateDate string `json:"create_date"` // 创建日期(格式化字符串) + CreateTime int64 `json:"create_time"` // 创建时间(Unix 时间戳) + UpdateDate string `json:"update_date"` // 更新日期(格式化字符串) + UpdateTime int64 `json:"update_time"` // 更新时间(Unix 时间戳) + UserID string `json:"user_id"` // 用户 ID + DSL map[string]interface{} `json:"dsl"` // Canvas DSL 对象,定义 Agent 的工作流 } // CreateAgentReq 创建 Agent 请求 @@ -41,10 +48,10 @@ type ListAgentsReq struct { } // ListAgentsRes 列出 Agent 响应 +// 注意:API 不返回 total 字段,仅返回 data 数组 type ListAgentsRes struct { - Code int `json:"code"` - Data []*Agent `json:"data"` - Total int `json:"total"` + Code int `json:"code"` // 状态码,0 表示成功 + Data []*Agent `json:"data"` // Agent 列表 } // CreateAgent 创建 Agent @@ -79,7 +86,8 @@ func (c *Client) UpdateAgent(ctx context.Context, agentID string, req *UpdateAge func (c *Client) DeleteAgent(ctx context.Context, agentID string) error { path := fmt.Sprintf("/api/v1/agents/%s", agentID) var res CommonResponse - if err := c.request(ctx, "DELETE", path, nil, &res); err != nil { + // 官方文档要求传空对象,不是 nil + if err := c.request(ctx, "DELETE", path, map[string]interface{}{}, &res); err != nil { return fmt.Errorf("delete agent failed: %w", err) } if !res.IsSuccess() { diff --git a/ragflow/chat.go b/ragflow/chat.go index bb19251..6f65335 100644 --- a/ragflow/chat.go +++ b/ragflow/chat.go @@ -82,10 +82,10 @@ type ListChatsReq struct { } // ListChatsRes 列出聊天助手响应 +// 注意:API 不返回 total 字段,仅返回 data 数组 type ListChatsRes struct { - Code int `json:"code"` - Data []*Chat `json:"data"` - Total int `json:"total"` // API 文档中未明确 total 字段,但通常列表接口会有 + Code int `json:"code"` // 状态码,0 表示成功 + Data []*Chat `json:"data"` // 聊天助手列表 } // DeleteChatsReq 删除聊天助手请求 @@ -111,7 +111,7 @@ func (c *Client) CreateChat(ctx context.Context, req *CreateChatReq) (*Chat, err // ListChats 列出聊天助手 func (c *Client) ListChats(ctx context.Context, req *ListChatsReq) (*ListChatsRes, error) { - path := "/api/v1/chats?" + path := "/api/v1/chats" params := map[string]interface{}{} if req.Page > 0 { params["page"] = req.Page diff --git a/ragflow/chunk.go b/ragflow/chunk.go index dad9e59..7e0b66e 100644 --- a/ragflow/chunk.go +++ b/ragflow/chunk.go @@ -39,12 +39,13 @@ type ListChunksReq struct { } // ListChunksRes 列出知识块响应 +// 注意:响应结构包含 chunks(知识块列表)、doc(关联文档信息)和 total(总数) type ListChunksRes struct { - Code int `json:"code"` + Code int `json:"code"` // 状态码,0 表示成功 Data struct { - Chunks []*Chunk `json:"chunks"` - Doc interface{} `json:"doc"` // 文档信息,暂时用 interface{} - Total int `json:"total"` + Chunks []*Chunk `json:"chunks"` // 知识块列表 + Doc interface{} `json:"doc"` // 关联文档信息(完整的 Document 对象) + Total int `json:"total"` // 知识块总数 } `json:"data"` } @@ -108,7 +109,7 @@ func (c *Client) AddChunk(ctx context.Context, datasetId, documentId string, req // ListChunks 列出知识块 func (c *Client) ListChunks(ctx context.Context, datasetId, documentId string, req *ListChunksReq) (*ListChunksRes, error) { - path := fmt.Sprintf("/api/v1/datasets/%s/documents/%s/chunks?", datasetId, documentId) + path := fmt.Sprintf("/api/v1/datasets/%s/documents/%s/chunks", datasetId, documentId) params := map[string]interface{}{} if req.Keywords != "" { params["keywords"] = req.Keywords diff --git a/ragflow/dataset.go b/ragflow/dataset.go index 0301d70..83162b7 100644 --- a/ragflow/dataset.go +++ b/ragflow/dataset.go @@ -67,10 +67,11 @@ type ListDatasetsReq struct { } // ListDatasetsRes 列出数据集响应 +// 注意:与 Agent/Chat 等接口不同,Dataset API 会返回 total 字段 type ListDatasetsRes struct { - Code int `json:"code"` - Data []*Dataset `json:"data"` - Total int `json:"total"` + Code int `json:"code"` // 状态码,0 表示成功 + Data []*Dataset `json:"data"` // 数据集列表 + Total int `json:"total"` // 总数据集数 } // DeleteDatasetsReq 删除数据集请求 @@ -97,7 +98,7 @@ func (c *Client) CreateDataset(ctx context.Context, req *CreateDatasetReq) (*Dat // ListDatasets 列出数据集 func (c *Client) ListDatasets(ctx context.Context, req *ListDatasetsReq) (*ListDatasetsRes, error) { // 构建查询参数 - path := "/api/v1/datasets?" + path := "/api/v1/datasets" params := map[string]interface{}{} if req.Page > 0 { params["page"] = req.Page diff --git a/ragflow/document.go b/ragflow/document.go index 44827ca..60d6192 100644 --- a/ragflow/document.go +++ b/ragflow/document.go @@ -3,12 +3,13 @@ package ragflow import ( "context" "fmt" + "strings" ) // 数据集内文件管理 // 参考: https://ragflow.com.cn/docs/dev/http_api_reference#数据集内文件管理 -// Document 文档结构体 +// ... (rest of the code remains the same) type Document struct { Id string `json:"id"` DatasetId string `json:"dataset_id"` @@ -39,22 +40,27 @@ type UploadDocumentReq struct { // ListDocumentsReq 列出文档请求 type ListDocumentsReq struct { - Page int `json:"page,omitempty"` - PageSize int `json:"page_size,omitempty"` - OrderBy string `json:"orderby,omitempty"` - Desc bool `json:"desc,omitempty"` - Keywords string `json:"keywords,omitempty"` - Id string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - CreateTimeFrom int64 `json:"create_time_from,omitempty"` - CreateTimeTo int64 `json:"create_time_to,omitempty"` + Page int `json:"page,omitempty"` // 页码,默认 1 + PageSize int `json:"page_size,omitempty"` // 每页数量,默认 30 + OrderBy string `json:"orderby,omitempty"` // 排序字段:create_time(默认)或 update_time + Desc bool `json:"desc,omitempty"` // 是否降序,默认 true + Keywords string `json:"keywords,omitempty"` // 关键词过滤(匹配文档标题) + Id string `json:"id,omitempty"` // 文档 ID 过滤 + Name string `json:"name,omitempty"` // 文档名称过滤 + CreateTimeFrom int64 `json:"create_time_from,omitempty"` // 创建时间起始(Unix 时间戳),0 表示无限制 + CreateTimeTo int64 `json:"create_time_to,omitempty"` // 创建时间截止(Unix 时间戳),0 表示无限制 + Suffix []string `json:"suffix,omitempty"` // 文件后缀过滤,如 ["pdf", "txt", "docx"] + Run []string `json:"run,omitempty"` // 处理状态过滤,支持 ["UNSTART", "RUNNING", "CANCEL", "DONE", "FAIL"] 或数字格式 ["0", "1", "2", "3", "4"] } // ListDocumentsRes 列出文档响应 +// 注意:响应结构与其他 List 接口不同,data 是一个对象而非数组 type ListDocumentsRes struct { - Code int `json:"code"` - Data []*Document `json:"data"` - Total int `json:"total"` + Code int `json:"code"` // 状态码,0 表示成功 + Data struct { + Docs []*Document `json:"docs"` // 文档列表 + TotalDatasets int `json:"total_datasets"` // 总文档数 + } `json:"data"` } // DeleteDocumentsReq 删除文档请求 @@ -64,7 +70,7 @@ type DeleteDocumentsReq struct { // ListDocuments 列出文档 func (c *Client) ListDocuments(ctx context.Context, datasetId string, req *ListDocumentsReq) (*ListDocumentsRes, error) { - path := fmt.Sprintf("/api/v1/datasets/%s/documents?", datasetId) + path := fmt.Sprintf("/api/v1/datasets/%s/documents", datasetId) params := map[string]interface{}{} if req.Page > 0 { params["page"] = req.Page @@ -96,11 +102,33 @@ func (c *Client) ListDocuments(ctx context.Context, datasetId string, req *ListD params["create_time_to"] = req.CreateTimeTo } + // 构造查询字符串 query := buildQueryString(params) + var queryParts []string if query != "" { - path += "?" + query + queryParts = append(queryParts, query) } + // 处理数组参数:suffix(文件后缀过滤) + // API 要求多个值时重复参数名,如:suffix=pdf&suffix=txt + // 这里使用 fmt.Sprintf 来构造每个参数值 + for _, suffix := range req.Suffix { + queryParts = append(queryParts, fmt.Sprintf("suffix=%s", suffix)) + } + + // 处理数组参数:run(处理状态过滤) + // 支持数字格式("0"-"4")或文本格式("UNSTART", "RUNNING", "CANCEL", "DONE", "FAIL") + // 这里使用 fmt.Sprintf 来构造每个参数值 + for _, run := range req.Run { + queryParts = append(queryParts, fmt.Sprintf("run=%s", run)) + } + + // 构造最终请求路径 + if len(queryParts) > 0 { + path += "?" + strings.Join(queryParts, "&") + } + + // 发送请求并处理响应 var res ListDocumentsRes if err := c.request(ctx, "GET", path, nil, &res); err != nil { return nil, err diff --git a/ragflow/session.go b/ragflow/session.go index 3f8a240..832082a 100644 --- a/ragflow/session.go +++ b/ragflow/session.go @@ -43,10 +43,10 @@ type ListSessionsReq struct { } // ListSessionsRes 列出会话响应 +// 注意:API 不返回 total 字段,仅返回 data 数组 type ListSessionsRes struct { - Code int `json:"code"` - Data []*Session `json:"data"` - Total int `json:"total"` // API 文档未明确 + Code int `json:"code"` // 状态码,0 表示成功 + Data []*Session `json:"data"` // 会话列表 } // DeleteSessionsReq 删除会话请求 @@ -93,7 +93,7 @@ func (c *Client) CreateSession(ctx context.Context, chatId string, req *CreateSe // ListSessions 列出会话 func (c *Client) ListSessions(ctx context.Context, chatId string, req *ListSessionsReq) (*ListSessionsRes, error) { - path := fmt.Sprintf("/api/v1/chats/%s/sessions?", chatId) + path := fmt.Sprintf("/api/v1/chats/%s/sessions", chatId) params := map[string]interface{}{} if req.Page > 0 { params["page"] = req.Page