diff --git a/init/uapi_seed.sql b/init/uapi_seed.sql index b6ead64..d8fed04 100644 --- a/init/uapi_seed.sql +++ b/init/uapi_seed.sql @@ -22,7 +22,7 @@ INSERT IGNORE INTO `upapp` (`id`, `name`, `description`, `ownerid`, `auth_apinam /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -INSERT IGNORE INTO `uapi` (`id`, `name`, `title`, `description`, `need_auth`, `stream`, `path`, `httpmethod`, `chunk_match`, `headers`, `params`, `data`, `response`, `ioid`, `callbackurl`, `upappid`) VALUES ('emb-embed','embed','文本向量化',NULL,'0',NULL,'/api/embed','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"texts\": {{json.dumps(texts)}}, \"images\": {{json.dumps(images)}}}',NULL,'io-embedding',NULL,'rag-embedding'),('face-compare','compare','人脸比对',NULL,'0',NULL,'/api/compare','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"image1\": \"{{image1}}\", \"image2\": \"{{image2}}\"}',NULL,'io-face',NULL,'rag-face'),('face-detect','detect','人脸检测',NULL,'0',NULL,'/api/detect','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"images\": {{json.dumps(images)}}}',NULL,'io-face',NULL,'rag-face'),('face-recognize','recognize','人脸识别',NULL,'0',NULL,'/api/recognize','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"images\": {{json.dumps(images)}}}',NULL,'io-face',NULL,'rag-face'),('graph-add-edge','add_edge','添加边',NULL,'0',NULL,'/api/graph/add_edge','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"source\": \"{{source}}\", \"target\": \"{{target}}\", \"attrs\": {{json.dumps(attrs)}}}',NULL,'io-graph',NULL,'rag-graph'),('graph-add-node','add_node','添加节点',NULL,'0',NULL,'/api/graph/add_node','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"node_id\": \"{{node_id}}\", \"attrs\": {{json.dumps(attrs)}}}',NULL,'io-graph',NULL,'rag-graph'),('graph-delete','delete','删除图',NULL,'0',NULL,'/api/graph/delete','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\"}',NULL,'io-graph',NULL,'rag-graph'),('graph-neighbors','neighbors','邻居查询',NULL,'0',NULL,'/api/graph/neighbors','GET',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"node_id\": \"{{node_id}}\"}',NULL,'io-graph',NULL,'rag-graph'),('graph-query','query','查询图',NULL,'0',NULL,'/api/graph/query','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"query\": \"{{query}}\"}',NULL,'io-graph',NULL,'rag-graph'),('graph-save','save','保存图',NULL,'0',NULL,'/api/graph/save','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"data\": {{json.dumps(data)}}}',NULL,'io-graph',NULL,'rag-graph'),('ner-entities','entities','实体识别',NULL,'0',NULL,'/api/extract','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"text\": \"{{text}}\", \"entities\": {{json.dumps(entities)}}, \"threshold\": {{threshold}}}',NULL,'io-ner',NULL,'rag-ner'),('reranker-rerank','rerank','文本重排序',NULL,'0',NULL,'/api/rerank','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"query\": \"{{query}}\", \"documents\": {{json.dumps(documents)}}, \"top_k\": {{top_k}}}',NULL,'io-reranker',NULL,'rag-reranker'),('vdb-delete','delete','向量删除',NULL,'0',NULL,'/v1/delete','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"colname\": \"{{colname}}\", \"pks\": {{json.dumps(ids)}}}',NULL,'io-vdb-vector',NULL,'rag-vdb'),('vdb-search','search','向量检索',NULL,'0',NULL,'/v1/query','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"colname\": \"{{colname}}\", \"vector\": {{json.dumps(vector)}}, \"pagerows\": {{top_k}}, \"output_fields\": [\"*\"]}',NULL,'io-vdb-vector',NULL,'rag-vdb'),('vdb-upsert','upsert','向量插入',NULL,'0',NULL,'/v1/upsert','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"colname\": \"{{colname}}\", \"data\": {{json.dumps(data)}}}',NULL,'io-vdb-vector',NULL,'rag-vdb'),('voiceprint-extract','voiceprint-extract','声纹提取',NULL,'0',NULL,'/voiceprint/extract/submit','POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'rag-voiceprint'),('voiceprint-status','voiceprint-status','声纹状态查询',NULL,'0',NULL,'/voiceprint/extract/status','GET',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'rag-voiceprint'); +INSERT IGNORE INTO `uapi` (`id`, `name`, `title`, `description`, `need_auth`, `stream`, `path`, `httpmethod`, `chunk_match`, `headers`, `params`, `data`, `response`, `ioid`, `callbackurl`, `upappid`) VALUES ('emb-embed','embed','文本向量化',NULL,'0',NULL,'/api/embed','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"texts\": {{json.dumps(texts)}}, \"images\": {{json.dumps(images)}}}',NULL,'io-embedding',NULL,'rag-embedding'),('face-compare','compare','人脸比对',NULL,'0',NULL,'/api/compare','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"image1\": \"{{image1}}\", \"image2\": \"{{image2}}\"}',NULL,'io-face',NULL,'rag-face'),('face-detect','detect','人脸检测',NULL,'0',NULL,'/api/detect','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"images\": {{json.dumps(images)}}}',NULL,'io-face',NULL,'rag-face'),('face-recognize','recognize','人脸识别',NULL,'0',NULL,'/api/recognize','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"images\": {{json.dumps(images)}}}',NULL,'io-face',NULL,'rag-face'),('graph-add-edge','add_edge','添加边',NULL,'0',NULL,'/api/graph/add_edge','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"source\": \"{{source}}\", \"target\": \"{{target}}\", \"attrs\": {{json.dumps(attrs)}}}',NULL,'io-graph',NULL,'rag-graph'),('graph-add-node','add_node','添加节点',NULL,'0',NULL,'/api/graph/add_node','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"node_id\": \"{{node_id}}\", \"attrs\": {{json.dumps(attrs)}}}',NULL,'io-graph',NULL,'rag-graph'),('graph-delete','delete','删除图',NULL,'0',NULL,'/api/graph/delete','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\"}',NULL,'io-graph',NULL,'rag-graph'),('graph-neighbors','neighbors','邻居查询',NULL,'0',NULL,'/api/graph/neighbors','GET',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"node_id\": \"{{node_id}}\"}',NULL,'io-graph',NULL,'rag-graph'),('graph-query','query','查询图',NULL,'0',NULL,'/api/graph/query','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"query\": \"{{query}}\"}',NULL,'io-graph',NULL,'rag-graph'),('graph-save','save','保存图',NULL,'0',NULL,'/api/graph/save','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"graph\": \"{{graph}}\", \"data\": {{json.dumps(data)}}}',NULL,'io-graph',NULL,'rag-graph'),('ner-entities','entities','实体识别',NULL,'0',NULL,'/api/extract','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"text\": \"{{text}}\", \"entities\": {{json.dumps(entities)}}, \"threshold\": {{threshold}}}',NULL,'io-ner',NULL,'rag-ner'),('reranker-rerank','rerank','文本重排序',NULL,'0',NULL,'/api/rerank','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"query\": \"{{query}}\", \"documents\": {{json.dumps(documents)}}, \"top_k\": {{top_k}}}',NULL,'io-reranker',NULL,'rag-reranker'),('vdb-delete','delete','向量删除',NULL,'0',NULL,'/v1/delete','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"colname\": \"{{colname}}\", \"pks\": {{json.dumps(ids)}}}',NULL,'io-vdb-vector',NULL,'rag-vdb'),('vdb-search','search','向量检索',NULL,'0',NULL,'/v1/query','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"colname\": \"{{colname}}\", \"vector\": {{json.dumps(vector)}}, \"pagerows\": {{top_k}}, \"output_fields\": [\"text\"]}',NULL,'io-vdb-vector',NULL,'rag-vdb'),('vdb-upsert','upsert','向量插入',NULL,'0',NULL,'/v1/upsert','POST',NULL,'{\n \"Content-Type\": \"application/json\"\n}',NULL,'{\"colname\": \"{{colname}}\", \"data\": {{json.dumps(data)}}}',NULL,'io-vdb-vector',NULL,'rag-vdb'),('voiceprint-extract','voiceprint-extract','声纹提取',NULL,'0',NULL,'/voiceprint/extract/submit','POST',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'rag-voiceprint'),('voiceprint-status','voiceprint-status','声纹状态查询',NULL,'0',NULL,'/voiceprint/extract/status','GET',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'rag-voiceprint'); /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; diff --git a/rag/init.py b/rag/init.py index 4837dbc..f9a263f 100644 --- a/rag/init.py +++ b/rag/init.py @@ -227,7 +227,13 @@ async def _build_search_vector(query, file_data, file_name, env=None, kb_id=''): def _parse_vdb_hits(vdb_resp, kb_id): - """Parse VDB search response into uniform hit format""" + """Parse VDB search response into uniform hit format. + + 兼容两种响应结构: + - 旧(平铺):{"results": [...]} / 顶层直接是数组 + - vdb v2.0(嵌套):{"status":"SUCCEEDED","data":{"rows":[...]}} + ——顶层 data 是 dict 而非 list,须再进一层找 rows。 + """ hits = [] data = vdb_resp if isinstance(data, dict): @@ -236,6 +242,15 @@ def _parse_vdb_hits(vdb_resp, kb_id): if isinstance(candidates, list): data = candidates break + else: + # 嵌套结构兜底:data.data.rows(vdb v2.0 query 响应) + inner = data.get("data") + if isinstance(inner, dict): + for key in ("rows", "results", "hits", "data"): + candidates = inner.get(key) + if isinstance(candidates, list): + data = candidates + break if not isinstance(data, list): return hits for item in data: