Learning to Select Knowledge for Response Generation in Dialog Systems

文章目录

 

Abstract

端到端的神经对话系统中,生成信息反应受到广泛关注。以前的各种工作利用外部知识和对话环境来产生这样的反应。然而,很少有人证明他们有能力将适当的知识纳入应对措施。受此启发,本文提出了一种新颖的开放域会话生成模型,该模型利用后验知识分布来指导知识选择,从而在会话中产生更恰当和信息量更强的响应。 据我们所知,我们是第一个利用后验知识分布来促进对话生成的人。 我们对自动和人工评估的实验清楚地证实了我们的模型在最先进的基线上的卓越性能。

1 Introduction

在过去几年中,开放式域名对话系统因其在教育机器人,情感伴侣和闲聊等实际应用中的巨大潜力而备受研究人员的关注。 最近提出的序列到序列(Seq2Seq)模型(Shang等人,2015; Vinyals和Le,2015; Cho等人,2014b)由于其简单性和广泛的适用性而引起了相当大的关注。 尽管它很受欢迎,但传统的Seq2Seq模型倾向于产生通用且信息量较小的响应,例如“我不知道”和“那很酷”,导致对话不那么有吸引力。

为了解决这个局限,各种神经模型 (Zhou et al., 2018; Ghazvininejad et al.,2018; Liu et al., 2018)建议利用外部知识(可以是非结构化文本或结构化三元组),旨在产生更恰当和信息丰富的答案。例如,(Zhou et al。,2018)中提出的常识模型考虑了常识性知识,其作为知识背景以促进对话理解。最近创建的数据集Persona-chat(Zhang et al。,2018)和Wizard-of-Wikipedia(Dinan et al。,2018)在响应生成中引入了与会话相关的知识(例如,Persona-chat中的个人简档)用于指导对话流程。迪南等人。 (2018)使用地面实况知识来指导知识选择,这表明对那些不使用这些信息的人进行了改进。然而,大多数现有研究仅利用输入话语和知识的语义相似性,其被并入解码器中以用于响应生成,而没有有效机制来保证响应中的适当知识选择和生成。

这些问题在表arXiv:1902.04911v1 [cs.CL] 2019年2月13日进一步说明,这是来自Persona-chat的对话(Zhang等,2018)。在此数据集中,每个代理都与角色配置文件相关联,该角色用作知识。两个代理根据相关知识交换角色信息。鉴于源话语,可以根据是否正确使用适当的知识生成不同的响应。例如,在R1中,没有利用知识,因此,它产生安全但信息量较少的响应。 R2包含错误的知识K2,是一种不正确的反应。适当的知识K3用于R3和R4。然而,R3是一个不太相关的响应,因为它无法正确地利用K3生成响应,而R4是一个有意义的响应,因为K3在其中被充分利用。知识的选择和结合在产生适当的反应中起着至关重要的作用,然而,现有模型尚未对其进行探讨。除此之外,我们观察到,由于选择的知识K3出现在响应中,我们想知道目标响应是否可以被有效利用,以便提供关于选择和结合知识的指令信息。为了克服上述缺陷,我们建议使用输入话语和响应(而不仅仅是输入话语)来指导知识选择和在opendomain响应生成中的结合。为了实现这一点,我们在训练阶段定义了输入话语和响应的知识后验概率分布。在这种后验分布的帮助下,该模型倾向于选择适当的知识来产生响应。不幸的是,目标响应仅在培训中可用。因此,当生成响应(即,目标响应未知)时,提出另一种先验知识分布以准确地近似后验知识分布。为此,我们使用后验知识分布作为指导来训练先验知识分布。然后,通过知识分布增强,我们的模型能够选择适当的知识并产生适当的信息响应。

我们的贡献如下:

  • 我们是第一个提出一种新的对话模型,其中利用后验知识来实现有效的知识选择和整合。 在后验知识分布的有效指导下,即使没有后验知识,我们的模型也能够选择适当的知识并产生信息反应。
  • 综合实验表明,我们的模型通过更好地整合知识并产生更适当和信息丰富的响应,明显优于现有模型。

2 Model

在本文中,我们关注的是通过知识选择和整合来建立神经模型的问题。 形式上,给定源话语 X = x 1 x 2 . . . x n X = x_1x_2...x_n X=x1​x2​...xn​(其中 x t x_t xt​是 X X X中的第 t t t个单词)和知识集合 { K 1 , . . . , K N } \{K1,..., K_N\} {K1,...,KN​}(可以是非结构化文本或结构三元组),目标是从知识集合中选择适当的知识,然后通过适当地合并所选知识来生成目标响应 Y = y 1 y 2 . . . y m Y = y_1y_2... y_m Y=y1​y2​...ym​。

2.1 Background: Seq2Seq and Attention

在我们进入模型细节之前,我们简要介绍了所需的技术背景,即Seq2Seq模型和注意机制。 熟悉这些概念的读者可以跳过本节。
Seq2Seq

Seq2Seq(Vinyals和Le,2015)遵循典型的编码器 - 解码器框架。
给定源话语 X = x 1 . . . x n X = x_1... x_n X=x1​...xn​,编码器将其编码为隐藏状态序列:
(1) h t = f ( x t , h t − 1 ) h_t = f(x_t,h_{t−1}) \tag{1} ht​=f(xt​,ht−1​)(1)

其中 h t h_t ht​是编码器在时间 t t t的隐藏状态, f f f是非线性变换,可以是长短期记忆单位(LSTM)(Hochreiter和Schmidhuber,1997)或门控循环单位(GRU)( Cho等,2014a)。 特别地,最后隐藏状态 h n h_n hn​也用作 X X X的上下文向量,并且由 c = h n c = h_n c=hn​表示。

(2) s t = f ( y t − 1 , s t − 1 , c ) s_t = f(y_{t−1}, s_{t-1}, c) \tag{2} st​=f(yt−1​,st−1​,c)(2)

(3) y t ∼ p t = s o f t m a x ( s t , c ) y_t ∼ p_t = softmax(s_t,c) \tag{3} yt​∼pt​=softmax(st​,c)(3)

其中 s t s_t st​是解码器的隐藏状态 t t t, y t − 1 y_{t-1} yt−1​是先前生成的单词, p t p_t pt​是时间t的输出概率分布。

Attention
最近,注意机制(Bahdanau等,2014)由于其提高发电质量的有效性而变得非常流行。 具体地,在关注的Seq2Seq中,根据特定的上下文向量 c t c_t ct​(而不是在等式(2)中使用的相同的 c c c)生成每个 y t y_t yt​,其中 c t = ∑ i = 1 n α t , i h i c_t = \sum^{n}_{i=1}\alpha_{t,i}h_i ct​=∑i=1n​αt,i​hi​。 直观地, c i c_i ci​可以被视为编码器的隐藏状态的加权和,其中权重 α t , i \alpha_{t,i} αt,i​测量状态 s t − 1 s_{t-1} st−1​和 h i h_i hi​之间的相关性。

2.2 Architecture Overview

在这里插入图片描述
我们的会话模型的体系结构概述如图1所示,它包含以下四个主要组件:

  • 话语编码器。 话语编码器将源话语 X X X编码为矢量 x x x,并将其馈送到知识管理器中。

  • 知识编码器。 知识编码器将每个知识 K i K_i Ki​作为输入并将其编码为知识向量 k i k_i ki​。 当目标话语 Y Y Y可用时(在训练中),它还将 Y Y Y编码为 y y y,稍后用于指导知识选择。

  • 知识管理员。 知识管理者是我们模型中最重要的组成部分。 鉴于先前生成的 x x x和 { k 1 , k 2 , . . . , k N } \{k_1,k_2,...,k_N\} {k1​,k2​,...,kN​}(和 y y y,如果可用的话),知识管理器负责对适当的知识 k i k_i ki​进行采样并将其(与参与编码器的隐藏状态的上下文向量 c t c_t ct​一起)提供给解码器。

  • 解码器。 最后,解码器基于所选择的知识 k i k_i ki​和基于注意力的上下文 c t c_t ct​生成响应。

在下文中,我们将在2.3节中介绍编码器(包括话语和知识)。 知识管理器在2.4节中讨论,而解码器在2.5节中描述。 最后,损失函数在第2.6节中详细说明。

2.3 Encoder

在我们的编码器中,我们使用具有门控循环单元(GRU)的双向RNN实现等式(1)中的非线性变换f(Cho等,2014a),其由两部分组成:前向RNN和后向RNN。

在话语编码器中,给定源话语 X = x 1 . . . x n X = x_1...x_n X=x1​...xn​,前向RNN从左到右读取 X X X,获得每个 x t x_t xt​的从左到右的隐藏状态 h → t \overrightarrow{h}_t h

t​。 以相反的顺序,同样地,获得从右到左的隐藏状态 - 每个 x t x_t xt​的 h ← t \overleftarrow{h}_t h t​。 这两个隐藏状态被连接起来形成 x t x_t xt​的整体隐藏状态 h t h_t ht​。数学上:
h t = [ h → ; h ← t ] = [ G R U ( x t , h → ) ; G R U ( x t , h ← t ) ] h_t=[\overrightarrow{h};\overleftarrow{h}_t]=[GRU(x_t,\overrightarrow{h});GRU(x_t, \overleftarrow{h}_t)] ht​=[h ;h t​]=[GRU(xt​,h );GRU(xt​,h

t​)]

[ ⋅ ; ⋅ ] [·;·] [⋅;⋅]表示vector concatenation
为了获得源话语X的表示x,我们利用隐藏状态并定义 x = [ h → ; h ← t ] x=[\overrightarrow{h};\overleftarrow{h}_t] x=[h

;h

t​]。 该向量将被馈送到知识管理器以进行知识采样,并且它还将用作解码器的初始隐藏状态。
我们的知识编码器遵循与话语编码器相同的架构,但它们不共享任何参数。 具体而言,它编码每个知识 K i K_i Ki​(如果是,则编码目标话语 Y Y Y.使用双向RNN将其分别用于向量表示 k i k_i ki​(和 y y y),并在知识管理器中稍后使用它。

2.4 Knowledge Manager

给定编码的源 x x x和编码的知识 { k 1 , . . . , k N } \{k_1,...,k_N\} {k1​,...,kN​},知识管理者的目标是从知识集合中抽取适当的 k i k_i ki​。 当目标话语 y y y可用时,它还用于教导用于获得 k i k_i ki​的模型。 知识管理器的详细架构如图2所示。
考虑训练阶段,其中 X X X和 Y Y Y都被输入我们的模型。 我们计算知识集合上的条件概率分布 p ( k ∣ x , y ) p(k|x,y) p(k∣x,y),并使用该分布对 k i k_i ki​进行采样。特别地,定义:
? ? ?

p ( k = k i ∣ x , y ) = e x p ( k i ⋅ M L P ( [ x ; y ] ) ) ∑ j = 1 N e x p ( k j ⋅ M L P ( [ x ; y ] ) ) p(k=k_i|x,y)=\frac{exp(k_i\cdot MLP([x;y]))}{\sum^{N}_{j=1} exp(k_j\cdot MLP([x;y]))} p(k=ki​∣x,y)=∑j=1N​exp(kj​⋅MLP([x;y]))exp(ki​⋅MLP([x;y]))​

其中MLP(·)是完全连接的层。 直觉上,我们使用点积来衡量 k i k_i ki​和输入话语之间的关联。 更高的关联意味着 k i k_i ki​更相关并且 k i k_i ki​更可能被采样。 由于 x x x和 y y y为条件,因此它是实际的后验知识分布可以通过该分布捕获目标话语 Y Y Y中使用的知识
在这里插入图片描述

为了根据 p ( k ∣ x , y ) p(k|x,y) p(k∣x,y)对知识进行抽样,我们使用Gumbel-Softmax重新参数化(Jang等,2016)(而不是精确抽样),因为它允许在非可微分类分布中进行反向传播。 采样的知识将非常有助于生成所需的响应,因为它包含实际响应中使用的知识信息。
不幸的是,在考虑评估阶段或产生响应时,目标话语Y不可用,因此,我们不能使用后验分布来获取知识。 或者,使用由 p ( k ∣ x ) p(k|x) p(k∣x)表示的先验知识分布来估计期望的 p ( k ∣ x , y ) p(k|x,y) p(k∣x,y)。特别地,
? ? ?

p ( k = k i ∣ x ) = e x p ( e x p ( k i ⋅ x ) ) ∑ j = 1 N e x p ( k j ⋅ x ) p(k=k_i|x)=\frac{exp(exp(k_i \cdot x))}{\sum^{N}_{j=1}exp(k_j \cdot x)} p(k=ki​∣x)=∑j=1N​exp(kj​⋅x)exp(exp(ki​⋅x))​

在评估或生成响应时,基于先验分布 p ( k ∣ x ) p(k|x) p(k∣x)对 k i k_i ki​进行采样。
显然,我们希望先验分布p(kjx)尽可能接近后验分布p(kjx; y),这样即使没有目标话语Y,我们的模型也能够捕获正确的知识。 为此,我们引入辅助损失,即KullbackLeibler散度损失(KLDivLoss),以测量p(kjx)和p(kjx; y)之间的接近度。 KLDivLoss在以下正式定义:
L K L ( θ ) = − 1 N ∑ p = ( k = k i ∣ x , y ) l o g p ( k = k i ∣ x , y ) p ( k = k i ∣ x ) L_{KL}(\theta)=-\frac{1}{N}\sum{p=(k=k_i|x,y)log \frac{p(k=k_i|x,y)}{p(k=k_i|x)}} LKL​(θ)=−N1​∑p=(k=ki​∣x,y)logp(k=ki​∣x)p(k=ki​∣x,y)​
其中 θ \theta θ表示模型参数。
直观地,当最小化KLDivLoss时,可以考虑后验分布 p ( k ∣ x , y ) p(k|x,y) p(k∣x,y)作为标签,我们的模型被指示使用先验分布 p ( k ∣ x ) p(k|x) p(k∣x)来准确地近似后验分布 p ( k ∣ x , y ) p(k|x,y) p(k∣x,y)。 因此,即使在生成响应时未知后验分布(因为实际目标话语 Y Y Y在实际情况下是未知的),可以有效地利用先验分布 p ( k ∣ x ) p(k|x) p(k∣x)来对正确知识进行采样,以便产生适当的响应。 据我们所知,我们是第一个神经模型,它将后验知识分布作为指导,实现准确的知识查找和高质量的响应生成。

2.5 Decoder

在上下文 c t c_t ct​和所选择的 k i k_i ki​条件下,我们的解码器按字顺序生成响应。 与传统的Seq2Seq解码器不同,我们将知识融入到响应生成中。 为此,我们介绍了两种解码器。 第一个是“硬”知识,引入具有标准GRU和级联输入的解码器,第二个是具有分级门控融合单元的“软”解码器(Yao等人,2017)。

标准GRU,带连接输入。(Standard GRU with Concatenated Inputs)
设 s t s_t st​为最后隐藏状态, y t − 1 y_{t-1} yt−1​为最后一步生成的单词, c t c_t ct​为隐藏状态 h 1 , h 2 , . . . , h n h_1,h_2,...,h_n h1​,h2​,...,hn​上基于注意的上下文向量。 目前的隐藏状态是:
s t = G R U ( [ y t − 1 ; k i ] , s t − 1 , c t ) s_t=GRU([y_{t-1};k_i],s_{t-1},c_t) st​=GRU([yt−1​;ki​],st−1​,ct​)

我们将 y t − 1 y_{t-1} yt−1​与选定的 k i k_i ki​连接起来。 这是一个简单直观的解码器。 然而,它迫使知识 k i k_i ki​参与解码,这在某些情况下不太灵活并且不可取。
分层门控融合单元(HGFU)。Hierarchical Gated Fusion Unit (HGFU)
HGFU提供了一种将知识融入响应生成的更软方式,它由三个主要组成部分组成,即话语GRU,知识GRU和融合单元。
前两个组件遵循标准GRU结构。 它们分别为最后生成的单词 y t − 1 y_{t-1} yt−1​和所选知识 k i k_i ki​生成隐藏的表示。特别地:
s t y = G R U ( y t − 1 , s t − 1 , c t ) s^y_t=GRU(y_{t-1,s_{t-1,c_t}}) sty​=GRU(yt−1,st−1,ct​​​)

s t k = G R U ( k i , s t − 1 , c t ) s^k_t=GRU(k_i,s_{t-1},c_t) stk​=GRU(ki​,st−1​,ct​)

然后,融合单元组合这两个隐藏状态以在时间t产生解码器的隐藏状态(Yao等人,2017)。数学上:
s t = r ⊙ s t y + ( 1 − r ) ⊙ s t k s_t=r \odot s^y_t +(1-r) \odot s^k_t st​=r⊙sty​+(1−r)⊙stk​

其中, r = σ ( W z [ t a n h ( W y s t y ) ; t a n h ( W k s t k ) ] ) r= \sigma(W_z[tanh(W_ys^y_t);tanh(W_ks^k_t)]) r=σ(Wz​[tanh(Wy​sty​);tanh(Wk​stk​)]), W z W_z Wz​, W y W_y Wy​, W k W_k Wk​是参数。直观地,门 r r r控制来自 s y s_y sy​的贡献量 t t t和 s k s_k sk​到最终的隐藏状态 s t s_t st​,允许灵活的知识结合模式。
在获得隐藏状态 s t s_t st​之后,根据等式(3)生成下一个字 y t y_t yt​。

2.6 Loss Function

除了2.4节中介绍的KLDivLoss之外,还使用了两个额外的损失函数,它们是NLL损失和BOW损失。 NLL丢失捕获的顺序信息,而BOW损失捕获词袋信息。 所有损失函数也在图2中详细说明.NLL损失。
NLL损失
目标是量化实际响应与模型生成的响应之间的差异。 它最小化负对数似然(NLL):
L N L L ( θ ) = − 1 m ∑ t = 1 m l o g p θ ( y t ∣ y &lt; t , x , k i ) L_{NLL}(\theta)=-\frac{1}{m}\sum^m_{t=1}logp_\theta (y_t|y_{&lt;t},x,k_i) LNLL​(θ)=−m1​t=1∑m​logpθ​(yt​∣y<t​,x,ki​)

其中 θ \theta θ表示模型参数, y &lt; t y_{&lt;t} y<t​t表示先前生成的单词。

BOW亏损。
BOW损失(Zhao et al。,2017)旨在通过强制知识和目标响应之间的相关性来确保采样知识 k i k_i ki​的准确性。 具体来说,让 w = M L P ( k i ) ∈ R ∣ V ∣ w=MLP(k_i) \in R^{|V|} w=MLP(ki​)∈R∣V∣,其中 V V V是词汇量大小,我们定义
p θ ( y t ∣ k i ) = e x p ( w y t ) ∑ v ∈ V e x p ( w v ) p_\theta(y_t|k_i)=\frac{exp(w_{yt})}{\sum_{v \in V}exp(w_v)} pθ​(yt​∣ki​)=∑v∈V​exp(wv​)exp(wyt​)​

BOW损失定义如下:
L B O W ( θ ) = − 1 m ∑ t = 1 m l o g   p θ ( y t ∣ k i ) L_{BOW}(\theta)=-\frac{1}{m}\sum^{m}_{t=1}log\ p_\theta(y_t|k_i) LBOW​(θ)=−m1​t=1∑m​log pθ​(yt​∣ki​)

总之,除非明确指出,否则给定训练示例 ( X , Y , { K i } i = 1 N ) (X,Y,\{ K_i\}^N_{i=1}) (X,Y,{Ki​}i=1N​)的总损失是KLDivLoss,NLL损失和BOW损失的总和。也就是:
L ( θ ) = L K L ( θ ) + L N L L ( θ ) + L B O W ( θ ) L(\theta)=L_{KL}(\theta)+L_{NLL}(\theta)+L_{BOW}(\theta) L(θ)=LKL​(θ)+LNLL​(θ)+LBOW​(θ)

3 Experiments

3.1 Dataset

我们对文献中最近创建的两个数据集进行了实验,即Personachat数据集(Zhang et al。,2018)和Wizardof-Wikipedia数据集(Dinan et al。,2018)。

假面聊天。在角色聊天数据集中,每个对话都是由一对随机的群众工作者构建的,他们被指示聊天互相认识。为了产生有意义和有趣的对话,每个工作者都被分配了一个角色简介,描述了他们的特征,这个角色简介作为对话中的知识(参见表1中的一个例子)。在Persona-chat数据集中有151,157个转弯(每个转弯对应一个源和一个目标话语对),我们分为火车122,499,验证14,602和测试14,056。该数据集中知识集合的平均大小(即,人物角色中的平均句子数)是4.49。

向导的维基百科。维基百科向导是一些选定主题的两个代理之间的聊天数据集。其中一个代理人,也称为向导,扮演知识专家的角色,他可以访问信息检索系统以获取知识。另一个代理人充当好奇的学习者。从该数据集中,获得了76,236圈对话,其中68,931 / 3,686 / 3,619用于训练/验证/测试。向导访问的知识集合的平均大小为67.57。该数据集中的大量候选知识意味着在正确的知识中识别是困难和具有挑战性的。

3.2 Models for Comparison

我们实施了我们的模型,即后验知识选择(PostKS)模型,用于评估。特别是,我们的模型的两个变体被实施,以证明不同的知识结合方式的影响:

•PostKS(concat)是使用GRU解码器引入模型的“硬”知识,其中知识被连接为输入。

•PostKS(融合)是一种“软”知识引入模型,其中知识与层次化门控融合单元相结合。此外,我们将我们的模型与以下三个最先进的基线进行了比较:

•Seq2Seq:Seq2Seq模型,注意力不具备知识信息(Shang et al。,2015; Vinyals and Le,2015)。

•MemNet(硬):改编自(Ghazvininejad等,2018)的Bag-of-Words记忆网络,其中的知识来自
收集并送入解码器。

•MemNet(软):一种柔软的知识基础模型,改编自(Ghazvininejad等,2018)。存储器单元存储在解码器中处理的知识。

其中,比较Seq2Seq是为了证明在对话生成中引入知识的效果,同时比较基于MemNet的模型,以验证我们的模型比现有的基于知识的模型更能够整合正确的知识。

3.3 Implementation Details

我们模型中的编码器和解码器具有2层GRU结构,每层有800个隐藏状态,但它们不共享任何参数。 我们将嵌入大小一词设置为300并使用GloVe对其进行初始化(Pennington等,2014)。 词汇量大小设置为20,000。 我们使用了EA批量大小为128的Adam优化器,我们将学习率设置为0.0005。

我们在P40机器上训练我们的模型最多20个时期。 在前5个时期,我们将BOW损失降至最低,仅用于预先培训知识管理者。 在剩余的时代,我们最小化所有损失的总和(KLDiv,NLL和BOW)。 在每个纪元之后,我们保存模型,并选择具有最小损失的模型进行评估。 接受后,我们的模型和数据集将在线提供

3.4 Automatic and Human Evaluation

在这里插入图片描述

3.5 Case Study

4 Related Work

Seq2Seq模型的巨大成功推动了各种技术的发展,以提高生成的响应的质量和多样性。例子包括多样性促进(Li et al。,2016)和未知单词处理(Gu et al。,2016)。然而,由于它们无法访问任何外部信息,因此在这些模型中仍然存在倾向于生成简短和通用词的问题。

最近,知识结合被证明是改善会话模型​​性能的有效方式。非结构化文本和结构化三元组都可以用作知识。龙等人。 (2017)使用卷积神经网络从非结构化文本获得知识。 Ghazvininejad等。 (2018)将文本作为知识存储在存储器网络中并使用它们来产生更多信息性响应。在(Liu et al。,2018)中也提出了神经知识扩散模型,其中该模型通过知识库上的收敛和发散思维来增强。此外,大规模的常识知识库首先被用于(Zhou et al。,2018)用于会话生成,并且许多领域特定的知识库也被认为是具有知识的地面神经模型(Xu et al。,2017; Zhu et al 。,2017; Gu et al。,2016)。

然而,现有模型都没有证明其能够(1)在大型候选知识集中定位正确的知识,以及(2)正确地利用知识生成高质量的响应。相反,他们只是根据谈话历史记录知识。相比之下,我们的模型与所有现有模型不同,因为它充分利用了后验知识分布,因此,我们的模型被有效地教导选择适当的知识并确保知识真正用于生成响应。

5 Conclusion

在本文中,我们提出了一种新颖的开放域对话模型,它是第一个利用后验知识分布促进知识选择和整合的神经模型。 特别是,即使没有后验信息,我们的模型仍然可以产生适当的信息反应。 对自动和人工指标的广泛实验证明了我们模型的有效性和实用性。 至于未来的工作,我们计划将强化学习的优势融入我们的模型中,以获得更好的表现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值