在电商搜索场景中,你是否遇到过这样的困扰:输入“适合夏天穿的透气运动鞋”,返回的却是所有“运动鞋”或“夏天衣服”,完全忽略了“透气”这个核心诉求。传统搜索引擎依赖关键词匹配和统计模型,难以理解用户查询背后复杂的语义组合与逻辑关系,导致搜索结果不尽人意。近期,Onton 公司发布的 Ontology 1 模型,号称在电商搜索准确率上实现了重大突破。本文将深入解析这一“神经符号搜索”模型的技术原理、架构设计,并通过一个简化的实战案例,带你理解其如何将深度学习与符号推理相结合,从而在复杂查询中实现更精准的匹配。无论你是搜索算法工程师、对AI应用感兴趣的后端开发者,还是希望了解前沿技术的技术爱好者,都能从本文获得从理论到实践的清晰认知。

1. 背景与核心概念:什么是神经符号搜索?

在深入 Ontology 1 之前,我们需要厘清两个关键概念:神经搜索与符号搜索,以及它们结合所带来的优势。

神经搜索 通常指基于深度学习的向量化搜索。它将文本(如用户查询和商品描述)通过预训练模型(如 BERT、Sentence-BERT)转换为高维向量(即嵌入)。搜索过程转化为在向量空间中计算查询向量与文档向量的相似度(如余弦相似度)。其优势在于强大的语义理解能力,能够捕捉“同义词”(如“手机”和“智能手机”)和“语义相关性”(如“水果”和“维生素C”)。

符号搜索 则源于传统知识表示和逻辑推理。它将知识表示为结构化的符号(如实体、属性、关系)和规则(如“如果商品类别是‘运动鞋’且材质包含‘网面’,则它具有‘透气’属性”)。搜索过程是基于这些符号和规则进行逻辑推理和匹配。其优势在于精确、可解释,能够严格处理“与”、“或”、“非”等逻辑约束。

然而,两者各有局限:

  • 纯神经搜索 :像一个“黑盒”,虽然语义理解强,但缺乏精确的逻辑约束能力。对于“价格低于500元且不是蓝色的连衣裙”这类查询,模型可能找到所有“连衣裙”,但难以严格保证“非蓝色”这个否定条件。
  • 纯符号搜索 :依赖于预先定义好的、完备的知识图谱和规则体系,难以处理语义多样性、长尾词汇以及非结构化文本中的隐含信息。

神经符号搜索 正是为了融合二者优势而提出的范式。它旨在利用神经网络处理非结构化数据的模糊性和语义性,同时利用符号系统进行精确的逻辑推理和可解释的决策。Onton 的 Ontology 1 模型便是这一范式在电商垂直领域的落地实践,其宣称的“比全球最佳电商搜索引擎准确率高 2.7 倍”的核心,很可能就在于它更好地解决了复杂、多约束查询的精准匹配问题。

2. 环境准备与概念模型

由于 Ontology 1 是闭源的商业模型,我们无法直接复现其完整系统。但为了理解其工作原理并进行技术探索,我们可以搭建一个简化的实验环境,模拟神经符号搜索的核心流程。本文将使用 Python 和一些主流开源库来构建一个演示系统。

核心环境与工具:

  • 操作系统 :Linux / macOS / Windows (WSL2 推荐)
  • Python 版本 :3.8 或以上
  • 关键库
    • transformers / sentence-transformers : 用于获取文本的神经语义向量(模拟神经部分)。
    • spaCy Stanza : 用于进行基础的命名实体识别和依存句法分析,辅助抽取查询中的符号(如实体、属性)。
    • redis faiss : 用于高效存储和检索向量(可选,演示中简化处理)。
    • pydantic / dataclasses : 用于定义符号化的商品结构。
  • IDE :VS Code, PyCharm 或 Jupyter Notebook 均可。

示例项目结构:

neuro_symbolic_search_demo/
├── data/
│   ├── products.jsonl      # 模拟商品数据
│   └── ontology_rules.py   # 模拟符号规则知识
├── src/
│   ├── neural_encoder.py   # 神经编码模块
│   ├── symbolic_parser.py  # 符号解析模块
│   ├── hybrid_retriever.py # 混合检索器
│   └── main.py            # 主程序入口
├── requirements.txt
└── README.md

版本说明 :本文示例代码基于常见库的稳定版本,重在演示思路。实际工业级系统涉及分布式索引、高性能向量数据库、大规模知识图谱构建等复杂工程,需根据实际情况选型。

3. 核心原理与架构拆解

我们可以将 Ontology 1 这类神经符号搜索模型的核心流程抽象为以下几个步骤,这也将是我们实战案例的构建蓝图:

3.1 查询理解与符号化

这是第一步,也是关键的一步。系统需要将用户的自然语言查询(如“帮我找轻便的防水双肩包,颜色要黑色或灰色”)分解为神经和符号两部分信息。

  • 神经部分 :将整个查询句子通过语义编码模型转换为一个查询向量 Q_vec 。这个向量捕捉了查询的整体语义意图。
  • 符号部分
    1. 实体识别 :识别出“双肩包”(产品类型)、“黑色”、“灰色”(颜色)等实体。
    2. 属性与约束抽取 :抽取出属性“重量”(轻便)、“功能”(防水)、“颜色”(黑色或灰色)。
    3. 逻辑关系解析 :解析出“颜色”属性内部是“或”关系(黑色 或 灰色),而“重量”、“功能”、“颜色”之间是“与”关系。

3.2 商品的知识表示

商品在系统中同样以“神经+符号”双重形式存在。

  • 神经表示 :将商品的标题、描述等文本信息编码为商品向量 P_vec
  • 符号表示 :将商品的结构化信息(如类目、品牌、颜色、材质、价格区间)存储在一个结构化的“商品档案”中。这类似于一个轻量级的、面向搜索的知识图谱。

3.3 混合检索与排序

这是融合发生的环节:

  1. 神经检索(召回) :使用查询向量 Q_vec 在商品向量库中进行近似最近邻搜索,快速召回一批语义相关的候选商品(比如 Top 1000)。这一步保证了语义相关性,覆盖了长尾和非标准表述。
  2. 符号过滤与精排(排序) :对神经召回的结果,应用从查询中解析出的符号规则进行过滤和重排序。
    • 过滤 :严格应用“硬”约束。例如,如果查询要求“防水”,则过滤掉所有“防水”属性为假或未标注的商品。
    • 精排 :应用“软”约束和逻辑评分。例如,对于“轻便”这种模糊属性,可以计算商品重量属性与“轻便”概念的匹配度作为一个分数。对于“黑色或灰色”,符合任一颜色即可,但可以给完全匹配的颜色更高权重。
  3. 分数融合 :将神经语义相似度分数(来自向量检索)和符号匹配分数(来自规则推理)通过一个可学习的或启发式的方式(如加权求和)融合,得到最终排序分数。

3.4 可解释性输出

神经符号系统的优势之一是能提供解释。系统可以返回结果的同时,标注出:“该商品被召回是因为语义匹配‘双肩包’”、“它满足‘防水’规则”、“它的颜色‘灰色’匹配了您的‘黑色或灰色’要求”。

4. 完整实战案例:构建一个简易的电商神经符号搜索演示系统

下面我们通过代码来具体实现上述流程的一个极度简化版本。请注意,此示例仅用于教学和原理演示,距离生产系统有巨大差距。

4.1 准备模拟数据与定义符号结构

首先,我们定义商品的数据结构并创建一些模拟数据。

文件: data/products.jsonl

{"id": 1, "title": "轻便透气网面运动鞋", "description": "夏季男士跑步鞋,超轻网布材质,透气舒适", "category": "运动鞋", "attributes": {"weight": "light", "material": ["mesh"], "function": ["breathable"], "color": ["white", "blue"]}}
{"id": 2, "title": "黑色防水徒步登山包", "description": "大容量双肩背包,采用防水涂层面料,适合户外旅行", "category": "双肩包", "attributes": {"weight": "medium", "material": ["polyester"], "function": ["waterproof"], "color": ["black"]}}
{"id": 3, "title": "灰色简约休闲双肩包", "description": "日常通勤书包,轻便设计,多隔层收纳", "category": "双肩包", "attributes": {"weight": "light", "material": ["nylon"], "function": [], "color": ["grey"]}}
{"id": 4, "title": "蓝色防水夹克", "description": "户外防风防水夹克,适合雨季穿着", "category": "外套", "attributes": {"weight": "medium", "material": ["polyester"], "function": ["waterproof"], "color": ["blue"]}}
{"id": 5, "title": "红色重型登山包", "description": "专业登山背包,自重较大但承重能力强", "category": "双肩包", "attributes": {"weight": "heavy", "material": ["canvas"], "function": [], "color": ["red"]}}

文件: src/symbolic_parser.py (部分) 这里我们定义一个简单的商品属性类和查询解析函数。实际应用中,这部分会复杂得多,可能用到依存句法分析、语义角色标注等。

from dataclasses import dataclass
from typing import List, Optional, Dict, Any
import re

@dataclass
class Product:
    """商品符号表示"""
    id: int
    title: str
    category: str
    attributes: Dict[str, Any]  # 例如: {'color': ['black'], 'function': ['waterproof']}

@dataclass
class ParsedQuery:
    """解析后的查询"""
    raw_query: str
    neural_vector: Optional[List[float]] = None  # 由神经编码器填充
    # 符号部分
    target_category: Optional[str] = None  # 目标类目,如“双肩包”
    attribute_constraints: Optional[Dict[str, List[str]]] = None # 属性约束,如 {'color': ['black', 'grey'], 'function': ['waterproof']}
    # 注意:这里简化了逻辑关系(默认为AND),实际需要更复杂的结构表示OR/NOT

def simple_query_parser(query: str) -> ParsedQuery:
    """一个极其简单的基于规则的查询解析器"""
    pq = ParsedQuery(raw_query=query)
    pq.attribute_constraints = {}

    # 非常初级的规则:关键词匹配
    query_lower = query.lower()
    category_keywords = {'双肩包': ['背包', '双肩包', '书包'],
                         '运动鞋': ['运动鞋', '跑鞋'],
                         '外套': ['夹克', '外套']}
    for cat, kw_list in category_keywords.items():
        if any(kw in query_lower for kw in kw_list):
            pq.target_category = cat
            break

    # 属性关键词匹配
    attribute_map = {
        'color': ['黑', '白', '灰', '蓝', '红', '粉'], # 中文颜色
        'function': ['防水', '透气', '轻便', '保暖'],
        'weight': ['轻便', '轻', '重型', '重'] # weight属性特殊处理
    }

    for attr, kw_list in attribute_map.items():
        matched_values = []
        for kw in kw_list:
            if kw in query_lower:
                # 简单映射:将中文关键词映射到标准值
                if attr == 'color':
                    # 简单映射,实际需要更复杂的词典
                    color_map = {'黑':'black', '白':'white', '灰':'grey', '蓝':'blue', '红':'red'}
                    matched_values.append(color_map.get(kw, kw))
                elif attr == 'weight' and kw in ['轻便', '轻']:
                    matched_values.append('light')
                elif attr == 'function':
                    func_map = {'防水': 'waterproof', '透气': 'breathable'}
                    matched_values.append(func_map.get(kw, kw))
                else:
                    matched_values.append(kw)
        if matched_values:
            pq.attribute_constraints[attr] = matched_values
    return pq

4.2 实现神经编码模块

我们使用 sentence-transformers 来获取文本的语义向量。

文件: src/neural_encoder.py

from sentence_transformers import SentenceTransformer
import numpy as np
from typing import List

class NeuralEncoder:
    def __init__(self, model_name: str = 'paraphrase-multilingual-MiniLM-L12-v2'):
        # 选择一个轻量级的多语言模型进行演示
        self.model = SentenceTransformer(model_name)

    def encode_text(self, texts: List[str]) -> np.ndarray:
        """将文本列表编码为向量矩阵"""
        return self.model.encode(texts, convert_to_numpy=True)

    def encode_single(self, text: str) -> np.ndarray:
        """编码单个文本"""
        return self.encode_text([text])[0]

# 初始化编码器
encoder = NeuralEncoder()

4.3 实现混合检索器

这是核心模块,负责协调神经检索和符号过滤。

文件: src/hybrid_retriever.py

import json
import numpy as np
from typing import List, Dict, Any
from .neural_encoder import encoder
from .symbolic_parser import Product, ParsedQuery, simple_query_parser

class HybridRetriever:
    def __init__(self, product_data_path: str):
        self.products = []
        self.product_vectors = None
        self._load_products(product_data_path)
        self._encode_products()

    def _load_products(self, path: str):
        """加载商品数据"""
        with open(path, 'r', encoding='utf-8') as f:
            for line in f:
                data = json.loads(line.strip())
                # 将属性中的列表标准化,确保都是列表形式
                attrs = data['attributes']
                for k, v in attrs.items():
                    if not isinstance(v, list):
                        attrs[k] = [v]
                self.products.append(Product(id=data['id'],
                                              title=data['title'],
                                              category=data['category'],
                                              attributes=attrs))

    def _encode_products(self):
        """为所有商品生成神经向量"""
        texts = [f"{p.title} {p.description}" for p in self.products] # 假设description也在数据中
        self.product_vectors = encoder.encode_text(texts)

    def neural_retrieve(self, query_vector: np.ndarray, top_k: int = 5) -> List[Product]:
        """基于向量相似度的神经检索"""
        # 计算余弦相似度
        similarities = np.dot(self.product_vectors, query_vector) / (
                np.linalg.norm(self.product_vectors, axis=1) * np.linalg.norm(query_vector)
        )
        # 获取相似度最高的top_k个索引
        top_indices = np.argsort(similarities)[::-1][:top_k]
        return [self.products[i] for i in top_indices]

    def symbolic_filter_and_rerank(self, candidates: List[Product], parsed_query: ParsedQuery) -> List[Dict]:
        """对候选商品进行符号过滤和重排序"""
        results = []
        for product in candidates:
            score = 1.0  # 基础分
            match_details = []

            # 1. 类目过滤(硬约束)
            if parsed_query.target_category and product.category != parsed_query.target_category:
                continue  # 不符合类目,直接过滤

            # 2. 属性匹配(软约束)
            if parsed_query.attribute_constraints:
                for attr, query_values in parsed_query.attribute_constraints.items():
                    product_values = product.attributes.get(attr, [])
                    if not product_values:  # 商品没有该属性
                        score *= 0.5  # 惩罚
                        match_details.append(f"缺失属性[{attr}]")
                    else:
                        # 检查是否有交集(简化处理,实际OR逻辑更复杂)
                        matched = any(v in product_values for v in query_values)
                        if matched:
                            score *= 1.2  # 奖励
                            match_details.append(f"匹配属性[{attr}:{query_values}]")
                        else:
                            score *= 0.7  # 惩罚
                            match_details.append(f"不匹配属性[{attr}]")

            results.append({
                'product': product,
                'symbolic_score': score,
                'match_details': match_details
            })

        # 按符号匹配分数排序
        results.sort(key=lambda x: x['symbolic_score'], reverse=True)
        return results

    def hybrid_search(self, query: str, neural_top_k: int = 10, final_top_k: int = 5) -> List[Dict]:
        """混合搜索主流程"""
        # 1. 查询理解
        parsed_query = simple_query_parser(query)
        print(f"[解析结果] 类目: {parsed_query.target_category}, 属性约束: {parsed_query.attribute_constraints}")

        # 2. 神经编码
        query_vector = encoder.encode_single(query)
        parsed_query.neural_vector = query_vector

        # 3. 神经检索(召回)
        neural_candidates = self.neural_retrieve(query_vector, top_k=neural_top_k)
        print(f"[神经召回] 候选商品数: {len(neural_candidates)}")

        # 4. 符号过滤与精排
        filtered_results = self.symbolic_filter_and_rerank(neural_candidates, parsed_query)

        # 5. 返回最终结果(这里简化,未做神经分数与符号分数的加权融合)
        return filtered_results[:final_top_k]

4.4 运行与验证

文件: src/main.py

import sys
import os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from hybrid_retriever import HybridRetriever

def main():
    # 初始化检索器
    retriever = HybridRetriever('../data/products.jsonl')

    # 测试查询
    test_queries = [
        "防水双肩包",
        "轻便的双肩包",
        "黑色或灰色的防水背包",
    ]

    for query in test_queries:
        print(f"\n{'='*50}")
        print(f"查询: 「{query}」")
        print('-'*50)
        results = retriever.hybrid_search(query, neural_top_k=5, final_top_k=3)

        if not results:
            print("未找到匹配商品。")
        else:
            for i, res in enumerate(results):
                p = res['product']
                print(f"{i+1}. [ID:{p.id}] {p.title}")
                print(f"   类目: {p.category}, 属性: {p.attributes}")
                print(f"   匹配详情: {', '.join(res['match_details'])}")
                print(f"   符号匹配分数: {res['symbolic_score']:.2f}")
        print('='*50)

if __name__ == "__main__":
    main()

4.5 运行结果说明

运行 python src/main.py ,预期会得到类似以下的输出(具体分数可能因模型差异而不同):

==================================================
查询: 「防水双肩包」
--------------------------------------------------
[解析结果] 类目: 双肩包, 属性约束: {'function': ['waterproof']}
[神经召回] 候选商品数: 5
1. [ID:2] 黑色防水徒步登山包
   类目: 双肩包, 属性: {'weight': ['medium'], 'material': ['polyester'], 'function': ['waterproof'], 'color': ['black']}
   匹配详情: 匹配属性[function:['waterproof']]
   符号匹配分数: 1.20
2. [ID:3] 灰色简约休闲双肩包
   类目: 双肩包, 属性: {'weight': ['light'], 'material': ['nylon'], 'function': [], 'color': ['grey']}
   匹配详情: 不匹配属性[function]
   符号匹配分数: 0.70
...
==================================================
查询: 「黑色或灰色的防水背包」
--------------------------------------------------
[解析结果] 类目: 双肩包, 属性约束: {'color': ['black', 'grey'], 'function': ['waterproof']}
[神经召回] 候选商品数: 5
1. [ID:2] 黑色防水徒步登山包
   类目: 双肩包, 属性: {'weight': ['medium'], 'material': ['polyester'], 'function': ['waterproof'], 'color': ['black']}
   匹配详情: 匹配属性[color:['black', 'grey']], 匹配属性[function:['waterproof']]
   符号匹配分数: 1.44
2. [ID:4] 蓝色防水夹克
   类目: 外套, 属性: {'weight': ['medium'], 'material': ['polyester'], 'function': ['waterproof'], 'color': ['blue']}
   匹配详情: 不匹配属性[color], 匹配属性[function:['waterproof']]
   符号匹配分数: 0.84
...

结果分析

  • 对于查询“防水双肩包”,系统成功识别了类目“双肩包”和功能“防水”。ID为2的商品(黑色防水徒步登山包)完全匹配,排名第一。ID为3的商品(灰色双肩包)因不具备“防水”功能而被惩罚,排名靠后。
  • 对于更复杂的查询“黑色或灰色的防水背包”,系统识别出了颜色约束(黑色或灰色)和功能约束(防水)。ID为2的商品同时满足颜色(黑色)和功能(防水),获得最高分。ID为4的商品(蓝色防水夹克)虽然防水,但颜色不匹配且类目是“外套”而非“双肩包”,因此被过滤或排在后面(取决于是否进行类目硬过滤)。

这个简易系统演示了神经符号搜索的核心思想: 用神经网络广泛召回语义相关项,再用符号规则进行精确的约束满足判断和排序

5. 常见问题与排查思路

在实现或理解神经符号搜索系统时,你可能会遇到以下问题:

问题现象 可能原因 排查思路与解决方案
符号解析错误 :查询中的关键属性未被识别。 1. 规则词典覆盖不全。
2. 自然语言处理(NLP)模型能力不足,无法理解复杂句式。
1. 扩充词典与规则 :持续维护和更新领域内的实体、属性词典。使用同义词库。
2. 升级NLP模块 :采用更先进的NER(命名实体识别)和依存句法分析模型,或引入小样本学习来适应新表述。
神经召回结果差 :语义相似的物品没有被召回。 1. 文本编码模型不适合当前领域(如电商)。
2. 商品文本信息质量差或缺失。
3. 向量索引性能或参数问题。
1. 领域微调 :使用领域内的数据对预训练语义模型(如BERT)进行微调。
2. 特征工程 :优化用于生成向量的文本,融合标题、品牌、属性、用户点击等多模态信息。
3. 调整检索参数 :检查向量索引的构建参数(如HNSW的 efConstruction , M ),确保召回率。
符号过滤过于严格 :大量相关商品被误过滤。 1. 属性约束被错误地当作“硬”过滤。
2. 商品属性数据标注不全或存在噪声。
1. 软化约束 :引入置信度或匹配度分数,将二值过滤改为加权评分。对于非核心约束,可以降级为排序因子而非过滤条件。
2. 数据清洗与补全 :建立商品属性补全流程,利用模型预测缺失属性。
分数融合不合理 :最终排序结果不符合直觉。 神经分数和符号分数的权重或融合方式不合理。 1. 有监督学习 :收集人工标注的查询-商品相关性数据,训练一个排序模型(如LambdaMART)来学习如何融合多路特征。
2. A/B测试调优 :在线实验不同的融合策略,以业务指标(如点击率、转化率)为优化目标进行调优。
系统延迟高 1. 神经编码耗时。
2. 符号推理逻辑复杂。
3. 多阶段串行处理。
1. 模型优化 :使用更轻量的模型、模型蒸馏或向量量化技术。
2. 异步与缓存 :对查询向量和热门商品向量进行缓存。将神经检索和部分符号推理并行化。
3. 工程优化 :使用高性能向量数据库(如Milvus, Weaviate)和规则引擎。

6. 最佳实践与工程建议

要将神经符号搜索从 demo 推向生产,需要考虑以下工程和实践要点:

1. 分层级的符号知识体系

  • 本体(Ontology)设计 :这正是“Ontology 1”模型名称的由来。需要为电商领域设计严谨的本体,明确定义“商品”、“类目”、“品牌”、“属性”、“属性值”之间的继承、组合关系。例如,“手机”是“电子产品”的子类,“颜色”是“手机”的一个属性,“星空黑”是“颜色”的一个值。
  • 属性标准化 :建立统一的属性值枚举体系。避免“深空灰”、“灰色”、“灰”同时存在,应映射到标准值“grey”。
  • 规则管理平台 :开发一个界面,允许业务运营人员配置和调整某些排序规则(如大促期间提升“折扣”属性的权重),而无需工程师修改代码。

2. 神经与符号的深度耦合

  • 符号感知的神经模型 :在训练语义编码模型时,不仅使用文本,也将商品的结构化符号(如类目、属性标签)作为输入的一部分,让模型隐式地学习这些符号知识。
  • 神经辅助的符号获取 :利用神经网络(如信息抽取模型)从非结构化的商品描述、用户评论中自动抽取属性和关系,反哺和丰富符号知识库。

3. 在线服务架构

  • 召回层(Recall) :通常采用多路召回策略。一路是神经向量召回,一路是符号检索(如基于Elasticsearch的布尔查询),还可能有人工运营的精选召回。各路召回的结果合并后进入排序层。
  • 排序层(Ranking) :排序模型接收来自召回层的候选商品,以及丰富的特征(神经语义分、符号匹配分、商品热度、用户画像等),进行精细打分。神经符号融合常在此阶段通过特征工程或模型结构实现。
  • 实时更新 :商品上下架、价格变动、属性修改需要实时同步到向量索引和符号数据库,保证搜索结果的即时性。

4. 评估与迭代

  • 离线评估 :构建丰富的测试集,包含各种类型的查询(简单关键词、复杂组合、带否定的查询等),定期评估搜索系统的准确率、召回率。
  • 在线评估 :通过A/B测试,关注点击率(CTR)、转化率(CVR)、搜索引导GMV等核心业务指标。
  • 错误分析 :定期抽样分析bad case,判断是神经召回问题、符号解析问题还是分数融合问题,有针对性地迭代模型或规则。

5. 可解释性与Debug

  • 搜索结果打标 :像我们demo中那样,为每个返回结果提供简单的解释,如“匹配了您的颜色要求”、“因为同类目且销量高”。
  • 查询分析报告 :在后台提供工具,展示系统是如何解析当前查询的,召回了哪些路的结果,各自分数如何,最终为何如此排序。这对于算法调试和运营理解系统至关重要。

神经符号搜索代表了搜索技术向更智能、更可控、更可解释方向发展的重要趋势。Onton Ontology 1 在电商领域的成功,验证了这种混合方法在解决复杂、精准需求场景下的巨大潜力。作为开发者或算法工程师,理解其核心思想——即利用神经网络的“模糊感知”能力解决语义泛化,同时利用符号系统的“精确推理”能力满足硬性约束——并能动手搭建一个原型系统,是迈向掌握这一前沿技术的关键一步。你可以从完善本文的简易demo开始,尝试接入真实的商品数据,引入更强大的NLP解析工具,或者实验不同的分数融合策略,逐步深入这一充满挑战和机遇的领域。

更多推荐