# 抽象化问答

# 简介

抽象化问答(Abstractive QA)是一种自然语言处理(NLP)技术,它涉及通过总结和综合来自各种来源的信息,而不仅仅是从现有文本中选择答案,以自然语言生成对给定问题的回答。

与提取式问答不同,提取式问答依赖于从文档语料库中识别和提取相关文本段落来回答问题,而抽象化问答系统能够生成捕捉回答问题所需的关键信息和含义的新的原创句子。

在这个项目中,您将学习如何使用 MyScale 在 openai api 上创建一个抽象化问答应用程序。构建问答系统需要三个主要组件:

  1. 用于语义搜索存储和执行的向量索引。
  2. 用于嵌入上下文段落的检索模型。
  3. 用于答案提取的 OpenAI API。

我们将使用 bitcoin_articles 数据集 (opens new window),该数据集包含了通过使用 Newscatcher API 从互联网上的不同来源进行网络抓取获得的有关比特币的新闻文章的集合。我们将使用检索模型为上下文段落创建嵌入,将它们索引到向量数据库中,并执行语义搜索以检索与我们的问题相关的前 k 个最相关的上下文,其中可能包含答案。然后,我们将使用 OpenAI API 基于返回的上下文生成答案。

如果您更感兴趣于探索 MyScale 的功能,请随意跳过 构建数据集 部分,直接进入 将数据填充到 MyScale 部分。

您可以按照 导入数据 部分中提供的说明,在 MyScale 控制台上导入此数据集。导入后,您可以直接进入 查询 MyScale 部分,享受这个示例应用程序。

# 先决条件

在开始之前,我们需要安装诸如 clickhouse python client (opens new window)、openai、sentence-transformer 和其他依赖项的工具。

# 安装依赖项

pip install clickhouse-connect openai sentence-transformers torch requests pandas tqdm

# 设置 Openai

import openai
openai.api_key = "YOUR_OPENAI_API_KEY"

# 设置检索模型

我们需要初始化我们的检索模型,它主要执行两个任务,第一个是可选的:

  1. 为每个上下文段落生成嵌入(上下文向量/嵌入)
  2. 为我们的查询生成嵌入(查询向量/嵌入)
import torch
from sentence_transformers import SentenceTransformer
# 如果可用,将设备设置为 GPU
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 从 huggingface 模型库加载检索模型
retriever = SentenceTransformer('multi-qa-MiniLM-L6-cos-v1', device=device)

# 构建数据集

# 下载和处理数据

该数据集包含了通过使用 Newscatcher API 从互联网上的不同来源进行网络抓取获得的有关比特币的新闻文章。

信息以 CSV 文件的形式给出,包括文章 ID、标题、作者、发布日期、链接、摘要、主题、国家、语言等详细信息。最初,我们创建一个紧凑的数据库来检索数据。

为了使这个笔记本更容易,我们在 S3 上保留了 Kaggle 数据集 bitcoin-news-articles-text-corpora (opens new window) 的完整副本,以节省配置 Kaggle 的公共 API (opens new window) 凭据的时间。

因此,我们可以通过以下命令下载数据集:

wget https://myscale-saas-assets.s3.ap-southeast-1.amazonaws.com/testcases/clickhouse/bitcoin-news-articles-text-corpora.zip
# 解压下载的文件
unzip -o bitcoin-news-articles-text-corpora.zip 
import pandas as pd
data_raw = pd.read_csv('bitcoin_articles.csv')
data_raw.drop_duplicates(subset=['summary'], keep='first', inplace=True)
data_raw.dropna(subset=['summary'], inplace=True)
data_raw.dropna(subset=['author'], inplace=True)
print(data_raw.info())

输出:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 1731 entries, 0 to 2499
Data columns (total 18 columns):
    #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
    0   article_id       1731 non-null   object 
    1   title            1731 non-null   object 
    2   author           1731 non-null   object 
    3   published_date   1731 non-null   object 
    4   link             1731 non-null   object 
    5   clean_url        1731 non-null   object 
    6   excerpt          1730 non-null   object 
    7   summary          1731 non-null   object 
    8   rights           1730 non-null   object 
    9   article_rank     1731 non-null   int64  
    10  topic            1731 non-null   object 
    11  country          1731 non-null   object 
    12  language         1731 non-null   object 
    13  authors          1731 non-null   object 
    14  media            1725 non-null   object 
    15  twitter_account  1368 non-null   object 
    16  article_score    1731 non-null   float64
    17  summary_feature  1731 non-null   object 
dtypes: float64(1), int64(1), object(16)
memory usage: 256.9+ KB

# 生成文章摘要嵌入

处理数据后,我们使用之前定义的检索模型为文章摘要生成嵌入。

from tqdm.auto import tqdm
summary_raw = data_raw['summary'].values.tolist()
summary_feature = []
for i in tqdm(range(0, len(summary_raw), 1)):
    i_end = min(i+1, len(summary_raw))
    # 为摘要生成嵌入
    emb = retriever.encode(summary_raw[i:i_end]).tolist()[0]
    summary_feature.append(emb)
data_raw['summary_feature'] = summary_feature

# 创建数据集

最后,我们将数据帧转换为 csv 文件,并将其压缩为 zip 文件,然后上传到 s3 以供以后使用。

data = data_raw[['article_id', 'title', 'author', 'link', 'summary', 'article_rank', 'summary_feature']]
data = data.reset_index().rename(columns={'index': 'id'})
data.to_csv('bitcoin_articles_embd.csv', index=False)
zip abstractive-qa-examples.zip bitcoin_articles_embd.csv

# 将数据填充到 MyScale

# 加载数据

要将数据填充到 MyScale,首先,我们下载在上一节中创建的数据集。以下代码片段显示了如何下载数据并将其转换为 panda DataFrames。

注意:summary_feature 是一个 384 维浮点向量,表示使用 multi-qa-MiniLM-L6-cos-v1 模型从文章摘要中提取的文本特征。

wget https://myscale-saas-assets.s3.ap-southeast-1.amazonaws.com/testcases/clickhouse/abstractive-qa-examples.zip
unzip -o abstractive-qa-examples.zip
import pandas as pd
import ast
data = pd.read_csv('bitcoin_articles_embd.csv')
data['summary_feature'] = data['summary_feature'].apply(ast.literal_eval)
print(data.info())

输出:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1731 entries, 0 to 1730
Data columns (total 8 columns):
    #   Column           Non-Null Count  Dtype 
---  ------           --------------  ----- 
    0   id               1731 non-null   int64 
    1   article_id       1731 non-null   object
    2   title            1731 non-null   object
    3   author           1731 non-null   object
    4   link             1731 non-null   object
    5   summary          1731 non-null   object
    6   article_rank     1731 non-null   int64 
    7   summary_feature  1731 non-null   object
dtypes: int64(2), object(6)
memory usage: 108.3+ KB

# 创建表

接下来,我们在 MyScale 中创建表。在开始之前,您需要从 MyScale 控制台中获取集群主机、用户名和密码信息。

以下代码片段创建了比特币文章信息表。

import clickhouse_connect
client = clickhouse_connect.get_client(
    host='YOUR_CLUSTER_HOST',
    port=443,
    username='YOUR_USERNAME',
    password='YOUR_CLUSTER_PASSWORD'
)
# 为比特币文本创建表
client.command("DROP TABLE IF EXISTS default.myscale_llm_bitcoin_qa")
client.command("""
CREATE TABLE default.myscale_llm_bitcoin_qa
(
    id UInt64,
    article_id String,
    title String,
    author String,
    link String,
    summary String,
    article_rank UInt64,
    summary_feature Array(Float32),
    CONSTRAINT vector_len CHECK length(summary_feature) = 384
)
ORDER BY id
""")

# 上传数据

在创建表之后,我们将从数据集中加载的数据插入到表中,并创建一个向量索引以加速后续的向量搜索查询。以下代码片段显示了如何将数据插入到表中,并使用余弦距离度量创建一个向量索引。

# 从数据集上传数据
client.insert("default.myscale_llm_bitcoin_qa", 
              data.to_records(index=False).tolist(), 
              column_names=data.columns.tolist())
# 检查插入数据的数量
print(f"文章数量: {client.command('SELECT count(*) FROM default.myscale_llm_bitcoin_qa')}")
# 文章数量: 1731
# 使用余弦距离创建向量索引
client.command("""
ALTER TABLE default.myscale_llm_bitcoin_qa 
ADD VECTOR INDEX summary_feature_index summary_feature
TYPE MSTG
('metric_type=Cosine')
""")
# 检查向量索引的状态,确保向量索引处于 'Built' 状态
get_index_status="SELECT status FROM system.vector_indices WHERE name='summary_feature_index'"
print(f"index build status: {client.command(get_index_status)}")

# 查询 MyScale

# 搜索和过滤

使用检索模型生成查询问题的嵌入。

question = 'what is the difference between bitcoin and traditional money?'
emb_query = retriever.encode(question).tolist()

然后,使用向量搜索识别与问题最相似的前 K 个候选项,并使用 article_rank < 500 对结果进行过滤。

top_k = 10
results = client.query(f"""
SELECT summary, distance(summary_feature, {emb_query}) as dist
FROM default.myscale_llm_bitcoin_qa
WHERE article_rank < 500
ORDER BY dist LIMIT {top_k}
""")
summaries = []
for res in results.named_results():
    summaries.append(res["summary"])

# 获取 GPT-3.5 的 CoT

将从 MyScale 搜索到的摘要组合成有效的提示。

CoT = ''
for summary in summaries:
    CoT += summary
CoT += '\n' +'Based on the context above '+'\n' +' Q: '+ question + '\n' +' A: The answer is'
print(CoT)

输出:

有些人甚至看到了数字支付革命正在展开。尽管通货膨胀上升,对加密货币的兴趣仍在增长,采用也在不断扩大。将加密货币和普通人之间的鸿沟缩小的行业之一是零售外汇交易。在全球经济和政治的不确定性和动荡之际,人们越来越多地寻求探索加密货币市场的内部运作、原则和财务潜力。投资者使用加密货币来实现投资组合的多样化,而母币比特币甚至已经确立了自己作为“价值储存”的地位。在美联储的紧缩政策下,比特币价格近期保持相对稳定。getty
比特币价格最近一直在相对稳定的范围内交易,即使美联储的政策威胁到风险资产的价值。这是全球最知名的数字货币,在撰写本文时的总市值接近3750亿美元,CoinDesk的数据显示,自上个月以来,它一直在接近2万美元的水平附近交易。最近一段时间,这种加密货币的价格有所波动,但这些波动幅度较小。:比特币和英镑纸币的图像 - Dado Ruvic/ REUTERS
比特币是英国银行等机构大规模量化宽松政策的“产物”,前保守党财务大臣声称。
迈克尔·斯宾斯勋爵将央行大规模购债计划归咎于为加密货币(如比特币)创造了价格泡沫,他说英国银行“印了太多钱”,导致“货币供应迅速增长”。
廉价货币将加密货币市场膨胀成了“现代版的荷兰郁金香泡沫”,斯宾斯勋爵说,他是交易公司ICAP的创始人。分析师就新月开始时的关键考虑因素发表了讲话。getty
新月开始时,投资者一直密切关注宏观经济发展和央行的政策决策,此时比特币仍在相对较小的范围内交易。根据TradingView的数据,全球最知名的数字货币自10月初以来一直在大约18,950美元和19,650.00美元之间波动。今天下午3:00左右,它达到了这个范围的上限,额外的TradingView数据显示。现在一些豪华酒店提供了一项新的福利:使用加密货币支付的能力。从迪拜到瑞士阿尔卑斯山脉,几家高端酒店允许客人用数字资产交换信用卡。
金融的未来:Z世代及其与金钱的关系
在熊市中寻求多样化?考虑这6种替代投资
瑞士安德马特的5星级酒店The Chedi Andermatt就是其中之一。
总经理Jean-Yves Blatt表示,该酒店从2021年8月开始提供这种支付方式,目前接受比特币和ETH,这是该酒店为客人提供个性化服务的延续。比特币BTC不仅仅是一种去中心化的点对点电子现金系统。它还是一种关于经济学、哲学、政治、人权和社会的新思维方式。
匈牙利雕塑家和创作者Reka Gergely(左)和Tamas Gilly(右)在布达佩斯Graphisoft Park揭幕的比特币虚拟货币发明者Satoshi Nakamoto的雕像旁边合影。- Dado Ruvic/ REUTERS
加密货币可以存储在在线交易所,如Coinbase和PayPal,或者加密货币所有者可以将其加密现金存储在硬件钱包中。Trezor和Ledger是销售这些小型设备以安全存储加密令牌的公司的例子。这些钱包可以是“热钱包”,意味着用户连接到互联网,并更容易访问他们的加密令牌,也可以是“冷钱包”,意味着加密令牌被加密在没有存储在连接到互联网的计算机上的私钥钱包中。强劲的美元和上升的国债收益率使比特币和黄金在价格上有了共同之处:两种资产今年都出现了下跌。根据道琼斯市场数据,黄金GC00,+2.23%,传统上被视为避险资产,今年迄今已经下跌了近7%。根据CoinDesk的数据,比特币BTCUSD,+1.59%今年迄今下跌了近60%。尽管一些比特币支持者将加密货币吹捧为对抗通胀的避险工具和“数字黄金”,但这两种资产之间的相关性很小,它们的相关性主要在负0之间摇摆。比特币、以太坊和其他加密货币被描述为提供价值储存,但在2022年还没有实现(Jakub Porzycki通过Getty Images进行的照片插图)NurPhoto通过Getty Images
2022年,比特币BTC和以太坊ETH的价值都已经下跌了约三分之二。这是在美国通胀率约为8%、市场风险升高的时候。比特币和以太坊作为价值储存的特点到底发生了什么?值得注意的是,这种波动水平并不新鲜。强劲的美元和上升的国债收益率使比特币和黄金在价格上有了共同之处:两种资产今年都出现了下跌。根据道琼斯市场数据,黄金GC00,+2.30%,传统上被视为避险资产,今年迄今已经下跌了近7%。根据CoinDesk的数据,比特币BTCUSD,+1.47%今年迄今下跌了近60%。
Based on the context above 
    Q: 比特币和传统货币之间的区别是什么?
    A: The answer is

# 从 GPT-3.5 获取结果

然后,使用生成的 CoT 查询 gpt-3.5-turbo

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "user", "content": CoT}
    ],
    temperature=0,
)
print("示例:使用 MyScale 进行检索")
print('Q: ', question)
print('A: ', response.choices[0].message.content)

输出:

示例:使用 MyScale 进行检索
Q:  比特币和传统货币之间的区别是什么?
A:  比特币是一种去中心化的数字货币,独立于传统银行系统运作,没有任何政府支持。它基于区块链技术,允许进行点对点交易,无需中介。而传统货币则由中央银行和政府发行和监管,其价值由这些机构的信任和稳定性支持。

我们得到了一个完整和详细的答案。我们获得了很好的结果。