首页
/ NLP课程实践:基于检索的问答系统构建指南

NLP课程实践:基于检索的问答系统构建指南

2025-07-06 06:30:42作者:冯爽妲Honey

引言

在自然语言处理(NLP)领域,构建高效的问答系统一直是一个重要研究方向。本文将基于Yandex数据科学学院的NLP课程内容,详细介绍如何构建一个基于检索的问答系统。这类系统通常由两个核心组件组成:检索器(Retriever)和生成器(Generator),我们将重点讲解检索器部分的实现。

系统概述

基于检索的问答系统工作原理如下:

  1. 检索器子系统:从给定数据库(如公开知识库)中搜索与问题相关的文本
  2. 生成器子系统:利用检索器找到的文本生成自然语言答案

数据集准备

我们使用斯坦福问答数据集(SQuAD)作为训练和测试数据。SQuAD包含文本段落和相关问题,系统的任务是选择回答问题的文本片段。

数据加载与查看

import data
train, test = data.build_dataset('./squad-v2.0.json')

# 查看示例数据
pid, question, options, correct_indices, wrong_indices = train.iloc[40]
print('QUESTION', question, '\n')
print('TEXT SENTENCES')
for i, cand in enumerate(options):
    print(['[ ]', '[v]'][i in correct_indices], cand)

示例输出可能显示一个问题及多个候选句子,其中标记"[v]"的是正确答案所在句子。

预训练模型选择

我们使用预训练的BERT模型(sentence-transformers/bert-base-nli-mean-tokens)来获取文本表示,而不是从头训练模型。预训练模型通常能提供更高质量的文本表示。

from transformers import AutoTokenizer, AutoModel

model_name = 'sentence-transformers/bert-base-nli-mean-tokens'
tokenizer = AutoTokenizer.from_pretrained(model_name)
bert = AutoModel.from_pretrained(model_name)

文本相似度计算

BERT模型可以将文本转换为向量表示,我们可以通过计算向量间的相似度来评估文本相关性。

# 示例文本
dummy_lines = [
    "How old are you?",                                                 # 0
    "In what mythology do two canines watch over the Chinvat Bridge?",  # 1
    "I'm sorry, okay, I'm not perfect, but I'm trying.",                # 2
    "What is your age?",                                                # 3
    "Beware, for I am fearless, and therefore powerful.",               # 4
]

# 获取文本向量表示
with torch.no_grad():
    batch_tensors = tokenizer(dummy_lines, padding=True, truncation=True, return_tensors="pt")
    out = bert(**batch_tensors)
    token_embs = out.last_hidden_state
    cls_embs = out.pooler_output
    
# 计算相似度矩阵
mask = batch_tensors['attention_mask'][..., None].to(torch.float32)
naive_phrase_embs = (token_embs * mask).sum(1) / mask.sum(1)

# 可视化相似度
plt.title('phrase similarity')
plt.imshow((naive_phrase_embs @ naive_phrase_embs.t()).cpu().data.numpy(), 
           interpolation='none', cmap='gray')

从相似度矩阵可以看出,"How old are you?"和"What is your age?"这两句话具有最高的相似度,这与我们的语义理解一致。

检索器模型实现

检索器模型的核心任务是:给定一个问题,从候选句子中找到最可能包含答案的句子。实现步骤包括:

  1. 将问题和所有候选句子转换为向量表示
  2. 计算问题向量与每个候选句子向量的相似度
  3. 选择相似度最高的句子作为结果

关键实现细节

  • 向量化处理:使用BERT模型获取问题和句子的向量表示
  • 相似度计算:通常使用余弦相似度或点积相似度
  • 性能优化:批量处理可以显著提高计算效率

模型评估与改进

评估检索器性能的指标通常包括:

  • 准确率(Accuracy):正确检索的比例
  • 召回率(Recall):相关结果被检索到的比例
  • 平均排名(Mean Rank):正确答案的平均排名位置

可能的改进方向:

  1. 尝试不同的预训练模型
  2. 调整向量聚合方式(如使用[CLS]标记向量代替平均池化)
  3. 引入重排序机制
  4. 使用更复杂的相似度计算方法

总结

本文详细介绍了基于检索的问答系统中检索器组件的实现方法。通过使用预训练的BERT模型和简单的相似度计算,我们就能构建一个基础的检索系统。在实际应用中,可以根据具体需求对系统进行扩展和优化,例如引入更复杂的模型架构或结合生成器组件构建端到端的问答系统。

对于希望深入学习的读者,建议进一步研究:

  • 不同预训练模型在检索任务上的表现差异
  • 如何处理长文档的检索问题
  • 结合语义理解和事实核查的混合问答系统
  • 低延迟检索系统的优化方法