@query/query_parser.py @scripts/es_debug_search.py 原始query、以及每一个翻译,都要有一个对应的keywords_query(token分词后,得到名词) 参考这段代码,获取每一个长度大于 1 的名词,然后用空格拼接起来,作为keywords_query import hanlp from typing import List, Tuple, Dict, Any class KeywordExtractor: """ 基于 HanLP 的名词关键词提取器 """ def __init__(self): # 加载带位置信息的分词模型(细粒度) self.tok = hanlp.load(hanlp.pretrained.tok.CTB9_TOK_ELECTRA_BASE_CRF) self.tok.config.output_spans = True # 启用位置输出 # 加载词性标注模型 self.pos_tag = hanlp.load(hanlp.pretrained.pos.CTB9_POS_ELECTRA_SMALL) def extract_keywords(self, query: str) -> str: """ 从查询中提取关键词(名词,长度 ≥ 2) Args: query: 输入文本 Returns: 拼接后的关键词字符串,非连续词之间自动插入空格 """ query = query.strip() # 分词结果带位置:[[word, start, end], ...] tok_result_with_position = self.tok(query) tok_result = [x[0] for x in tok_result_with_position] # 词性标注 pos_tag_result = list(zip(tok_result, self.pos_tag(tok_result))) # 需要忽略的词 ignore_keywords = ['玩具'] keywords = [] last_end_pos = 0 for (word, postag), (_, start_pos, end_pos) in zip(pos_tag_result, tok_result_with_position): if len(word) >= 2 and postag.startswith('N'): if word in ignore_keywords: continue # 如果当前词与上一个词在原文中不连续,插入空格 if start_pos != last_end_pos and keywords: keywords.append(" ") keywords.append(word) last_end_pos = end_pos # 可选:打印调试信息 # print(f'分词: {word} | 词性: {postag} | 起始: {start_pos} | 结束: {end_pos}') return "".join(keywords).strip() 最后,在组织检索表达式时,目前是每一个 query (base_query base_query_trans_en base_query_trans_zh 三种情况)。 会组成一个bool查询,以base_query为例: "bool": { "should": [ { "bool": { "_name": "base_query", "must": [ { "combined_fields": { ... } } ], "should": [ { "multi_match": { ... "type": "best_fields", ... }, { "multi_match": { ... "type": "phrase", ... } } ] } }, base_query_trans_en base_query_trans_zh 也是同样 在这个布尔查询的must里面加一项:keywords,搜索的字段和combined_fields一样,命中比例要求50% 结合现有代码做出合理的设计,呈现简单清晰的数据接口,而不是打补丁