fix(search): VDB v2.0嵌套响应解析(data.data.rows)+output_fields用显式text(Milvus Lite不支持*通配)

This commit is contained in:
ymq 2026-09-04 18:38:15 +08:00
parent 15db4e2e1a
commit 2113066631
2 changed files with 17 additions and 2 deletions

View File

@ -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 */;

View File

@ -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.rowsvdb 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: