RAGFlow 实战(四):REST API 自动化——知识库管理、检索测试与问答脚本 系列导航:(一)部署、鉴权与排障 ;(二)文档解析实战 ;(三)检索调参实录 ;(四)本篇。
一、为什么要走 API Web 界面适合探索,但下面这些场景必须脚本化:
批量上传 :几百篇文档逐个点页面不现实;检索回归测试 :改切片参数/换 embedding 后,用固定问题集跑一遍,量化对比;接入业务系统 :知识库问答能力嵌进自己的应用;运维巡检 :定时检查文档解析状态、索引完整性。RAGFlow 从 0.27 开始提供了新版 REST API(/api/v1/),覆盖知识库、文档、切片、检索、会话全链路。这篇给一套可直接改的 Python 客户端。
二、鉴权:先解决登录 新版 API 用 Bearer Token。两种拿法:
方式一:账号密码登录换 token
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import requestsBASE = "http://127.0.0.1:9380" def login (email: str , password: str ) -> str : r = requests.post(f"{BASE} /api/v1/user/login" , json={"email" : email, "password" : password}) r.raise_for_status() data = r.json() if data.get("code" ) != 0 : raise RuntimeError(f"login failed: {data} " ) return data["data" ]["token" ] TOKEN = login("tangbotao@local.dev" , "your_password" ) HEADERS = {"Authorization" : f"Bearer {TOKEN} " }
方式二:API Key (推荐长期自动化):在 Web「用户设置」里生成 API Key,之后所有请求带 Authorization: Bearer <api-key>,不用管登录态过期。
踩坑提醒 :RAGFlow 的登录响应是 {code, message, data} 三层结构,code == 0 才是成功——直接 r.json()["token"] 会 KeyError。密码忘了可以进容器用 UserService.update_user_password 重置(见系列第三篇)。
三、知识库与文档管理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 def create_dataset (name: str ) -> str : r = requests.post(f"{BASE} /api/v1/datasets" , headers=HEADERS, json={"name" : name, "permission" : "only_me" }) r.raise_for_status() return r.json()["data" ]["id" ] def upload_document (dataset_id: str , file_path: str ): with open (file_path, "rb" ) as f: files = {"file" : f} r = requests.post( f"{BASE} /api/v1/datasets/{dataset_id} /documents" , headers=HEADERS, files=files) r.raise_for_status() return r.json()["data" ] def wait_parsing_done (dataset_id: str , doc_id: str , timeout=600 ): """轮询文档解析状态:pending → running → done""" import time deadline = time.time() + timeout while time.time() < deadline: r = requests.get( f"{BASE} /api/v1/datasets/{dataset_id} /documents" , headers=HEADERS) docs = r.json()["data" ]["docs" ] doc = next (d for d in docs if d["id" ] == doc_id) status = doc.get("progress" , "" ).lower() if status == "done" : return doc if status == "failed" : raise RuntimeError(f"parse failed: {doc} " ) time.sleep(5 ) raise TimeoutError("parsing not finished" )
关键认知:解析是异步的 。上传接口只是投递任务,progress 从 0 爬到 1.0 才是真解析完。批量上传的脚本一定要带轮询和并发控制——一次性扔 500 个文档进去,Executor 和 ES 都会谢。
四、切片查看与调试 解析完成后,直接把文档的 chunk 拉出来审查——这是验证切片质量最直接的方式:
1 2 3 4 5 6 7 8 9 10 11 12 def list_chunks (dataset_id: str , doc_id: str ): r = requests.get( f"{BASE} /api/v1/datasets/{dataset_id} /documents/{doc_id} /chunks" , headers=HEADERS, params={"page" : 1 , "page_size" : 100 }) r.raise_for_status() return r.json()["data" ]["chunks" ] chunks = list_chunks(dataset_id, doc_id) for c in chunks[:3 ]: print (c["content" ][:200 ]) print ("keywords:" , c.get("important_kwd" , [])) print ("---" )
看什么:表格有没有被切断、条款完不完整、标题孤不孤悬——就是系列第二篇那套判断标准,只是从页面搬到了脚本里,可以批量审。
五、检索测试:改参数前的量化依据 1 2 3 4 5 6 7 8 9 10 11 def retrieval_test (question: str , dataset_ids: list , top_k: int = 8 ): r = requests.post(f"{BASE} /api/v1/retrieval" , headers=HEADERS, json={ "question" : question, "dataset_ids" : dataset_ids, "top_k" : top_k, "similarity_threshold" : 0.2 , }) r.raise_for_status() return r.json()["data" ]["chunks" ]
用法 :准备 20~30 个「有标准答案」的问题,改任何配置(切片参数、embedding、混合检索权重)前后各跑一遍,对比命中率和答案完整度。RAG 系统调优最怕「感觉变好了」,这个脚本把感觉变成数字。
六、问答与会话 1 2 3 4 5 6 7 8 9 10 11 12 13 14 def create_chat (name: str , dataset_ids: list ) -> str : r = requests.post(f"{BASE} /api/v1/chats" , headers=HEADERS, json={"name" : name, "dataset_ids" : dataset_ids}) r.raise_for_status() return r.json()["data" ]["id" ] def chat (chat_id: str , question: str , stream: bool = False ): r = requests.post(f"{BASE} /api/v1/chats/{chat_id} /completions" , headers=HEADERS, json={"question" : question, "stream" : stream}, stream=stream) r.raise_for_status() return r
流式响应按 SSE 解析(data: 前缀的行逐行读),非流式直接取 JSON。生产接入建议:加超时、加重试、记录每次请求的 chunk 命中 ——出问题时「检索到了什么」比「模型答了什么」更有排查价值。
七、小结 API 自动化的收益在三个地方:批量操作的效率、调优的量化依据、业务系统的集成能力。把这套脚本和系列第二篇的文档类型策略、第三篇的回归测试组合起来,就是一个完整的知识库工程化工作流。RAGFlow 系列到此收官,下一篇聊聊视频侧的 AI 工程化实战。