跳转至

472_问答系统设计


一句话说明

问答系统(QA System)让机器自动回答用户问题,从抽取式(在文章中找答案片段)到生成式(LLM直接生成回答)形态多样。


核心知识点

  • 开放域QA vs 阅读理解QA
  • 阅读理解:给定文章找答案(SQuAD数据集)
  • 开放域:从大规模文档库检索+阅读(Retriever-Reader架构)
  • RAG(检索增强生成):当前最主流方案,先检索相关文档再交给LLM生成答案
  • 抽取式QA:预测答案在原文中的起始和结束位置(span prediction)
  • 知识库QA(KBQA):从结构化知识图谱(如Wikidata)查询答案

经典方法对比

方法核心思路优点缺点
抽取式 BERT-QA预测span起止位置忠实度高答案只能来自原文
生成式(T5/GPT)直接生成答案文本灵活,可推理可能幻觉
RAG检索 + 生成知识可更新检索质量影响大
KBQA解析问题为SPARQL查询精确可解释KB覆盖有限

代码示例

# ---- 方案1:抽取式QA(BERT在原文中定位答案)----
from transformers import pipeline

# 加载QA流水线
qa_pipeline = pipeline(
    "question-answering",
    model="deepset/roberta-base-squad2"
)

context = """
BERT (Bidirectional Encoder Representations from Transformers) was introduced
by Google in 2018. It uses a bidirectional Transformer encoder and is pre-trained
on masked language modeling and next sentence prediction tasks.
"""
question = "When was BERT introduced?"

result = qa_pipeline(question=question, context=context)
print(f"答案: {result['answer']}")        # 2018
print(f"置信度: {result['score']:.4f}")   # 对应位置的概率

# ---- 方案2:RAG系统(检索+生成)----
# pip install langchain chromadb sentence-transformers

from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.schema import Document

# 2a. 构建向量知识库
embedding_model = HuggingFaceEmbeddings(
    model_name='sentence-transformers/all-MiniLM-L6-v2'  # 轻量embedding模型
)

# 模拟文档库(实际从PDF/数据库加载)
docs = [
    Document(page_content="BERT于2018年由Google发布,基于双向Transformer。"),
    Document(page_content="GPT系列由OpenAI开发,使用自回归语言模型。"),
    Document(page_content="T5把所有NLP任务统一成文本到文本的格式。"),
]

# 构建向量数据库(FAISS或Chroma)
vectorstore = Chroma.from_documents(
    docs,
    embedding=embedding_model,
    persist_directory="./chroma_db"  # 持久化到磁盘
)

# 2b. 检索最相关文档
retriever = vectorstore.as_retriever(
    search_kwargs={"k": 2}  # 返回最相似的2个文档
)
query = "BERT是什么时候发布的?"
retrieved_docs = retriever.get_relevant_documents(query)
for doc in retrieved_docs:
    print("检索到:", doc.page_content)

# 2c. 用LLM生成最终答案(需配置API)
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA

llm = OpenAI(temperature=0)  # temperature=0 减少随机性
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",     # 把所有检索文档塞进prompt
    retriever=retriever
)
answer = qa_chain.run(query)
print("RAG答案:", answer)

# ---- 方案3:BERT-QA的span预测原理演示 ----
from transformers import BertForQuestionAnswering, BertTokenizer
import torch

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForQuestionAnswering.from_pretrained('bert-large-uncased-whole-word-masking-finetuned-squad')

q = "What is BERT?"
c = "BERT is a language model developed by Google in 2018."

# 问题和上下文一起编码,用[SEP]分隔
enc = tokenizer(q, c, return_tensors='pt')
with torch.no_grad():
    outputs = model(**enc)
    # start_logits 和 end_logits 对每个token位置打分
    start_idx = outputs.start_logits.argmax()   # 答案起始token位置
    end_idx = outputs.end_logits.argmax()       # 答案终止token位置

tokens = tokenizer.convert_ids_to_tokens(enc['input_ids'][0])
answer_tokens = tokens[start_idx: end_idx + 1]
print("答案tokens:", tokenizer.convert_tokens_to_string(answer_tokens))

面试常问点

  1. RAG相比纯LLM的优势?
  2. 知识可更新(不需要重新训练)、来源可追溯、减少幻觉

  3. 如何评估QA系统质量?

  4. 抽取式:Exact Match(EM)和 F1
  5. 生成式:ROUGE、BERTScore、人工评估

  6. 检索质量差导致RAG效果差怎么办?

  7. HyDE(假设文档嵌入):先让LLM生成假设答案再检索
  8. 重排序(Reranking):cross-encoder对候选文档二次排序

  9. KBQA和阅读理解QA的适用场景?

  10. KBQA:精确事实性问题("哪个城市是法国首都")
  11. 阅读理解:开放性文档理解、需要推理

速查表

需求推荐方案
小规模QA验证BERT-QA pipeline
企业知识库问答RAG(LangChain + FAISS/Chroma)
精确事实查询SPARQL + 知识图谱
医学文献问答PubMedBERT-QA
评估工具SQuAD评估脚本、RAGAS