FAQ
所谓FAQ(Frequently Asked Questions)问答,指的是通过构建一个数量巨大的问题答案库来作为语料库,当输入一个问题时,通过计算该问题与语料库中的所有问题的语义相似度,给出语义最相似的问题所对应的答案。两个问题语义相似度的计算方法,有:余弦相似度、Jaccard相似度、BM25相似度等。
Indexing
在AnyQ系统中,索引(Indexing)模块的作用是根据所给定的问题答案数据集,通过将其转换为语义索引库,从而提供检索(Retrieval)、匹配(Matching)模块进行语义相似度计算,匹配出与所提问题最相似的答案。
添加语义索引
语义索引库构建 AnyQ/build/example/conf/
- 将灌库文件faq_file(utf8编码)转换成Json格式,在最初的AnyQ系统中,所提供的问题答案数据集位于
AnyQ/build/solr_script/sample_doc
。
{"question": "XXX", "answer": "XXX", "id": XXX}
cp -rp ../tool/solr ./solr_script
mkdir -p faq
python solr_script/make_json.py solr_script/sample_docs faq/schema_format faq/faq_json
- 对Json文本添加索引id:
awk -F "\t" '{print ++ind"\t"$0}' faq/faq_json > faq/faq_json.index
- 在anyq词典配置dict.conf增加语义表示模型的插件:
dict_config{
name: "fluid_simnet"
type: "PaddleSimAdapter"
path: "./simnet"
}
- 在analysis.conf中增加query语义表示的插件:
analysis_method {
name: "method_simnet_emb"
type: "AnalysisSimNetEmb"
using_dict_name: "fluid_simnet"
dim: 128
query_feed_name: "left"
cand_feed_name: "right"
embedding_fetch_name: "tanh.tmp"
}
- 生成语义索引库:
./annoy_index_build_tool example/conf/ example/conf/analysis.conf faq/faq_json.index 128 10 semantic.annoy 1>std 2>err
语义索引库使用 AnyQ/build/example/conf/
- 把带索引id的faq库文件和语义索引库放到anyq配置目录下
cp faq/faq_json.index semantic.annoy example/conf
- 在dict.conf中配置faq库文件的读取
dict_config {
name: "annoy_knowledge_dict"
type: "String2RetrievalItemAdapter"
path: "./faq_json.index"
}
- 在retrieval.conf中配置语义检索插件
retrieval_plugin {
name : "semantic_recall"
type : "SemanticRetrievalPlugin"
vector_size : 128
search_k : 10000
index_path : "./example/conf/semantic.annoy"
using_dict_name: "annoy_knowledge_dict"
num_result : 10
}
Analysis
问题分析模块(Analysis)是整个系统中对输入问题进行解析的第一个模块。该模块所完成的主要功能有:
- 对句子进行分词;
- 对分词后的每个单词进行词性标注(POS);
- 将每个单词进行词向量表示;
- 命名实体识别(NER)。参考文章
但是,在最初的AnyQ系统中,其仅实现了句子分词及词向量表示功能,并提供了相应功能插件的配置。其他,例如POS和NER的功能需要用户自行实现并添加。
添加分词
用户词典
在策略插件中使用的词典,需在 AnyQ/build/example/dict.conf
中配置。当前系统的词典插件主要包括以下几种:
- 哈希词典:HashAdapter<TYPE1, TYPE2>
- 干预词典:String2RetrievalItemAdapter
- 切词词典: WordsegAdapter
- Paddle SimNet匹配模型词典: PaddleSimAdapter
- Tensorflow模型词典: TFModelAdapter
配置方式如下所示:
# 干预词典
dict_config {
name: "rank_weights"
type: "String2FloatAdapter"
path: "./rank_weights"
}
# 切词词典
dict_config {
name: "lac"
type: "WordsegAdapter"
path: "./wordseg_utf8"
}
# paddle SimNet匹配模型词典
dict_config{
name: "fluid_simnet"
type: "PaddleSimAdapter"
path: "./simnet"
}
分词
在 AnyQ/build/example/analysis.conf
中可以增添query分析策略插件。当前系统的analysis插件主要包括以下几种:
- 切词:AnalysisWordseg
- query语义向量表示:AnalysisSimNetEmb
- query替换: AnalysisQueryIntervene
配置方式如下所示:
# 切词
analysis_method {
name: "method_wordseg"
type: "AnalysisWordseg"
using_dict_name: "lac"
}
添加词向量表示
句子分词功能添加完毕后,要实现分好词的每个单词进行词向量的表示,需要在解析模块的配置文件中(AnyQ/build/example/analysis.conf)添加相应功能插件,其格式如下:
# 语义向量
analysis_method {
name: "method_simnet_emb"
type: "AnalysisSimNetEmb"
using_dict_name: "fluid_simnet"
dim: 128
query_feed_name: "left"
cand_feed_name: "right"
embedding_fetch_name: "tanh.tmp"
}
Retrieval
输入的问题通过分析模块(Analysis)对问题进行分词,词向量表示等操作后,再输入到问题检索模块(Retrieval),由该模块将问题带入到FAQ数据集中进行检索,得到前N个候选问题。
该模块目前所提供的问题检索功能有:
- 基于关键词的检索(Term检索,TermRetrievalPlugin)
- 基于语义的检索(SemanticRetrievalPlugin)
- 人工干预检索(ManualRetrievalPlugin)
基于关键词
基于关键词的检索,即根据已添加的数据集,通过TF-IDF,为该数据集构建倒排索引,当一个已经分词的问题输入后,匹配前N个候选问题。
检索模块的配置路径为 AnyQ/build/example/retrieval.conf
,通过在该文件中添加关键词索引插件:
retrieval_plugin {
name : "term_recall_1"
type : "TermRetrievalPlugin"
search_host : "127.0.0.1"
search_port : 8900
engine_name : "collection1"
solr_result_fl : "id,question,answer"
solr_q : {
type : "EqualSolrQBuilder"
name : "equal_solr_q_1"
solr_field : "question"
source_name : "question"
}
num_result : 15
}
其中,solr_q是solr搜索服务器查询的插件,该插件所提供的搜索类型(type)有:
- EqualSolrQBuilder:字段等于
- BoostSolrQBuilder:字段term加权
- ContainSolrQBuilder:字段包含关键词
- SynonymSolrQBuilder:字段term同义词
- DateCompareSolrQBuilder:日期字段比较
基于语义
基于语义的检索,是由AnyQ中的SimNet模块根据所提供数据集训练好后的模型,来对输入问题(词向量表示)与候选问题进行计算检索。检索模块的配置路径为 AnyQ/build/example/retrieval.conf
,通过在该文件中添加语义索引插件:
retrieval_plugin {
name : "semantic_recall"
type : "SemanticRetrievalPlugin"
vector_size : 128
search_k : 10000
index_path : "./example/conf/semantic.annoy"
using_dict_name: "annoy_knowledge_dict"
num_result : 10
}
Matching
通过检索模块(Retrieval)从索引库中得到N个候选问题以后,需要带入到问题匹配模块(Matching),依次对每个候选问题与输入问题计算其相似度。对于同一个候选问题-输入问题对来说,可以同时计算多种类型的相似度.
该模块目前所提供的相似度计算功能有:
- 编辑距离相似度:EditDistanceSimilarity;
- Cosine相似度:CosineSimilarity
- Jaccard相似度: JaccardSimilarity
- BM25相似度: BM25Similarity
- Paddle SimNet匹配模型相似度: PaddleSimilarity
- Tensorflow匹配模型相似度: TFSimilarity
分词
将候选问题与输入问题带入到问题匹配模块(Matching)以后,为了能够与输入问题进行相似度计算,首先需要对候选问题进行分词,其配置路径为: AnyQ/build/example/rank.conf
。
配置插件为:
# 对候选切词
matching_config {
name : "wordseg_process"
type : "WordsegProcessor"
using_dict_name: "lac"
output_num : 0
rough : false
}
相似度计算
在该模块中,对候选问题与输入问题进行相似度计算主要分为两种:传统的距离度量学习的方法(Cosine相似度、Jaccard相似度等)和深度学习的方法(语义相似度计算)。其配置路径为: AnyQ/build/example/rank.conf
。
配置插件为:
# Jaccard相似度
matching_config {
name : "jaccard_sim"
type : "JaccardSimilarity"
output_num : 1
rough : false
}
# Paddle SimNet匹配模型相似度
matching_config {
name: "fluid_simnet_feature"
type: "PaddleSimilarity"
using_dict_name: "fluid_simnet"
output_num : 1
rough : false
query_feed_name: "left"
cand_feed_name: "right"
score_fetch_name: "cos_sim_0.tmp"
}
# Tensorflow匹配模型相似度
matching_config {
name : "tf_qq_match"
type : "TFSimilarity"
using_dict_name: "tf_qq_match"
output_num : 1
rough : false
tfconf : {
pad_id : 0
sen_len: 32
left_input_name: "left"
right_input_name: "right"
output_name: "output_prob"
}
}
其中output_num表示该插件输出的相似度值个数,对于不输出相似度的插件(如WordsegProcessor),output_num应配置为0; rough配置为true表示该相似度用于粗排,反之则用于精排。
计算相似度需要先对候选切词,因此WordsegProcessor插件应该配置在其他matching_config之前。
需要注意的是,在该模块配置文件中,如果配置了多种相似度计算插件,则对于一个问题对来说,将对其分别计算相应插件的相似度,最终得到多个相似度,每一个相似度可看作该问题对的一个特征,这多个特征最终需要带入到问题打分模块(rank)来对该问题对进行综合的打分。
Ranking
在 AnyQ/build/example/rank.conf
中配置predictorc插件,用于根据多个相似度对候选计算得分。当前系统的rank插件主要包括以下几种:
- 线性预测模型: PredictLinearModel
- XGBoost预测模型: PredictXGBoostModel
- 特征选择预测模型:PredictSelectModel
配置格式如下:
rank_predictor {
type: "PredictLinearModel"
using_dict_name: "rank_weights"
}
网友评论