@@ -240,3 +240,70 @@ def search_resources(data: dict):
240240 'details' : str (e )
241241 }), 500
242242
243+
244+ @resource_bp .route ('/match' , methods = ['POST' ])
245+ @validate_json_request (['svg_content' ], {
246+ 'svg_content' : lambda x : isinstance (x , str ) and len (x .strip ()) > 0 ,
247+ 'top_k' : lambda x : isinstance (x , int ) and x > 0 ,
248+ 'threshold' : lambda x : isinstance (x , (int , float )) and x >= 0 # 距离阈值无上限
249+ })
250+ @ensure_coordinator_initialized
251+ def match_resources (data : dict ):
252+ """
253+ 图片匹配图片(基于向量距离)
254+
255+ 接受JSON数据:
256+ {
257+ "svg_content": "<svg>...</svg>", // 输入的SVG图片内容
258+ "top_k": 10, // 可选,返回结果数量,默认10
259+ "threshold": 0.0 // 可选,最大距离阈值,默认0.0(距离越小越相似)
260+ }
261+
262+ 注意:与文本搜索不同,此接口使用L2距离度量图片相似度
263+ - threshold表示最大允许距离(0表示不过滤)
264+ - 返回结果按距离排序,距离越小表示越相似
265+ """
266+ try :
267+ svg_content = data ['svg_content' ].strip ()
268+ top_k = data .get ('top_k' , 10 )
269+ threshold = data .get ('threshold' , 0.0 )
270+
271+ logger .info (f"收到图片匹配请求: top_k={ top_k } , threshold={ threshold } , svg_length={ len (svg_content )} " )
272+
273+ # 执行图片匹配
274+ result = coordinator .match_by_image (
275+ svg_content = svg_content ,
276+ top_k = top_k ,
277+ threshold = threshold
278+ )
279+
280+ if result ['success' ]:
281+ return jsonify ({
282+ 'success' : True ,
283+ 'top_k' : top_k ,
284+ 'threshold' : threshold ,
285+ 'results_count' : result ['results_count' ],
286+ 'results' : result ['results' ]
287+ })
288+ else :
289+ return jsonify ({
290+ 'success' : False ,
291+ 'error' : result .get ('error' , '图片匹配失败' ),
292+ 'code' : 'MATCH_FAILED'
293+ }), 500
294+
295+ except ValueError as e :
296+ logger .error (f"图片匹配参数异常: { e } " )
297+ return jsonify ({
298+ 'error' : str (e ),
299+ 'code' : 'INVALID_PARAMETER'
300+ }), 400
301+
302+ except Exception as e :
303+ logger .error (f"图片匹配系统异常: { e } " )
304+ return jsonify ({
305+ 'error' : '内部服务器错误' ,
306+ 'code' : 'INTERNAL_ERROR' ,
307+ 'details' : str (e )
308+ }), 500
309+
0 commit comments