From ffb6146931e7fcfe6c80a418eaa5ea3ddb8a56c6 Mon Sep 17 00:00:00 2001 From: huangzhuang_3rd Date: Mon, 1 Jun 2026 18:31:26 +0800 Subject: [PATCH] =?UTF-8?q?v1.8.0:=20=E6=A8=A1=E5=9D=97=E5=8C=96=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20+=20=E5=90=8E=E5=8F=B0=E7=99=BB=E5=BD=95=E8=AE=A4?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/routes/api_smart.py | 184 ++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 modules/routes/api_smart.py diff --git a/modules/routes/api_smart.py b/modules/routes/api_smart.py new file mode 100644 index 0000000..55792dd --- /dev/null +++ b/modules/routes/api_smart.py @@ -0,0 +1,184 @@ +""" +智能解析/添加/补充 API +""" +import uuid +from datetime import datetime +from flask import Blueprint, request, jsonify +from config import MODELS_FILE, GPUS_FILE, CPUS_FILE, DATA_DIR +from utils import load_data, save_data +from llm import parse_with_llm, get_parse_prompt_template + +smart_bp = Blueprint('api_smart', __name__) + + +def _smart_update_generic(entity_id, file_path, category_type, entity_name): + """通用智能补充逻辑""" + data = request.get_json() + text = data.get('text', '') + images = data.get('images', []) + if not text and not images: + return jsonify({'error': '文本或图片不能都为空'}), 400 + items = load_data(file_path) + item = next((i for i in items if i['id'] == entity_id), None) + if not item: + return jsonify({'error': f'{entity_name} not found'}), 404 + parsed_list = parse_with_llm(text, category_type, images) + if not parsed_list: + return jsonify({'error': '解析失败'}), 500 + parsed = parsed_list[0] + updated_fields = [] + for key, value in parsed.items(): + if value is not None and value != '' and value != 0: + existing = item.get(key) + if existing is None or existing == '' or existing == 0: + item[key] = value + updated_fields.append(key) + item['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + parse_source = { + 'type': 'smart_update', + 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'images': images, + 'text': text[:500] if text else '', + 'updated_fields': updated_fields + } + if 'parse_sources' not in item: + item['parse_sources'] = [] + item['parse_sources'].append(parse_source) + save_data(file_path, items) + return jsonify({'success': True, 'updated_fields': updated_fields, entity_name.lower(): item}) + + +def _smart_add_generic(category_type, file_path, category_id=None): + """通用智能添加逻辑""" + data = request.get_json() + text = data.get('text', '') + images = data.get('images', []) + subcategory_id = data.get('subcategory_id', '') + custom_prompt = data.get('custom_prompt', '') + if not text and not images: + return jsonify({'error': '文本或图片不能都为空'}), 400 + parsed_list = parse_with_llm(text, category_type, images, category_id=category_id, + subcategory_id=subcategory_id, custom_prompt=custom_prompt) + results = [] + items = load_data(file_path) + parse_source = { + 'type': 'smart_add', + 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'images': images, + 'text': text[:500] if text else '' + } + for parsed in parsed_list: + parsed['id'] = uuid.uuid4().hex[:12] + parsed['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + parsed['visible'] = True + parsed['subcategory_id'] = subcategory_id + parsed['publish_date'] = parsed.get('publish_date', '') + parsed['views'] = 0 + parsed['is_pinned'] = False + parsed['product_images'] = [] + parsed['parse_sources'] = [parse_source] + if category_id: + parsed['category_id'] = category_id + items.append(parsed) + results.append(parsed) + save_data(file_path, items) + return jsonify({'success': True, 'count': len(results), 'products': results}) + + +# ---- Parse Prompt ---- +@smart_bp.route('/api/parse-prompt', methods=['POST']) +def api_get_parse_prompt(): + data = request.get_json() + category_type = data.get('category_type', 'dynamic') + category_id = data.get('category_id') + subcategory_id = data.get('subcategory_id') + template = get_parse_prompt_template(category_type, category_id, subcategory_id) + return jsonify({'success': True, 'template': template}) + + +# ---- Image Parse ---- +@smart_bp.route('/api/parse-images', methods=['POST']) +def api_parse_images(): + data = request.get_json() + text = data.get('text', '') + images = data.get('images', []) + category_type = data.get('category_type', 'dynamic') + subcategory_id = data.get('subcategory_id', '') + custom_prompt = data.get('custom_prompt', '') + if not text and not images: + return jsonify({'error': '文本或图片不能都为空'}), 400 + if not images: + return jsonify({'error': '请上传至少一张图片'}), 400 + type_to_cat_id = {'model': 'ai-models', 'gpu': 'gpus', 'cpu': 'cpus', 'dynamic': None} + category_id = type_to_cat_id.get(category_type) + parsed_list = parse_with_llm(text, category_type, images, category_id=category_id, + subcategory_id=subcategory_id, custom_prompt=custom_prompt) + return jsonify({'success': True, 'count': len(parsed_list), 'products': parsed_list, + 'raw_text': text, 'images': images}) + + +# ---- Smart Update ---- +@smart_bp.route('/api/models//smart-update', methods=['POST']) +def api_smart_update_model(model_id): + return _smart_update_generic(model_id, MODELS_FILE, 'model', 'Model') + +@smart_bp.route('/api/gpus//smart-update', methods=['POST']) +def api_smart_update_gpu(gpu_id): + return _smart_update_generic(gpu_id, GPUS_FILE, 'gpu', 'GPU') + +@smart_bp.route('/api/cpus//smart-update', methods=['POST']) +def api_smart_update_cpu(cpu_id): + return _smart_update_generic(cpu_id, CPUS_FILE, 'cpu', 'CPU') + +@smart_bp.route('/api/items///smart-update', methods=['POST']) +def api_smart_update_item(category_id, item_id): + items_file = DATA_DIR / f'items_{category_id}.json' + items = load_data(items_file) + item = next((i for i in items if i['id'] == item_id), None) + if not item: + return jsonify({'error': 'Item not found'}), 404 + data = request.get_json() + text = data.get('text', '') + images = data.get('images', []) + if not text and not images: + return jsonify({'error': '文本或图片不能都为空'}), 400 + parsed_list = parse_with_llm(text, 'dynamic', images) + if not parsed_list: + return jsonify({'error': '解析失败'}), 500 + parsed = parsed_list[0] + updated_fields = [] + for key, value in parsed.items(): + if value is not None and value != '' and value != 0: + existing = item.get(key) + if existing is None or existing == '' or existing == 0: + item[key] = value + updated_fields.append(key) + item['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + parse_source = { + 'type': 'smart_update', 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'images': images, 'text': text[:500] if text else '', 'updated_fields': updated_fields + } + if 'parse_sources' not in item: + item['parse_sources'] = [] + item['parse_sources'].append(parse_source) + save_data(items_file, items) + return jsonify({'success': True, 'updated_fields': updated_fields, 'item': item}) + + +# ---- Smart Add ---- +@smart_bp.route('/api/models/smart-add', methods=['POST']) +def api_smart_add_model(): + return _smart_add_generic('model', MODELS_FILE, 'ai-models') + +@smart_bp.route('/api/gpus/smart-add', methods=['POST']) +def api_smart_add_gpu(): + return _smart_add_generic('gpu', GPUS_FILE, 'gpus') + +@smart_bp.route('/api/cpus/smart-add', methods=['POST']) +def api_smart_add_cpu(): + return _smart_add_generic('cpu', CPUS_FILE, 'cpus') + +@smart_bp.route('/api/items//smart-add', methods=['POST']) +def api_smart_add_item(category_id): + items_file = DATA_DIR / f'items_{category_id}.json' + return _smart_add_generic('dynamic', items_file, category_id)