File size: 17,655 Bytes
4a3c603
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# coding=utf-8
# author: xusong <[email protected]>
# time: 2022/8/23 12:58

"""
## TODO:

1. 下拉框,选择类目。   gr.Radio(['服饰','箱包', '鞋靴']
2. 支持输入特效
  - 示例:https://huggingface.co/uer/gpt2-chinese-lyric
  - 参考 https://github.com/huggingface/hub-docs/blob/main/js/src/lib/components/InferenceWidget/shared/WidgetTextarea/WidgetTextarea.svelte
3. 待开放参数:No Repeat Ngram Size、Length Penalty、Number of Beams。topk-sampling, topp-sampling,


num_beam_groups = return_sequences数吗?

## badcase:

1. 结尾容易出多个句号。为啥?
2. 重复

## 解码demo (能够调整解码参数的demo)

- https://huggingface.co/spaces/THUDM/GLM-130B

## 解码参数示例

**greedy策略**

**sample策略**
- moss: do_sample=True, temperature=0.7, top_p=0.8, top_k=40, repetition_penalty=1.02
- chatglm:do_sample=True, temperature=0.95, top_p=0.7, max_length=2048
- chatglm2:do_sample=True, top_p=0.8, temperature=0.8  https://huggingface.co/THUDM/chatglm2-6b/blob/main/modeling_chatglm.py#L1023
- glm130b:
    - temperature=1, top_p=0.7, top_k=0, no_repeat_ngram_size=3, length_penalty=1, num_beams=2
- vicuna: do_sample=True, temperature=0.7, top_p=1, top_k=-1, repetition_penalty=1
- chatgpt
- baichuan-chat: do_sample=True, temperature=0.3, top_p=0.85, top_k=5, repetition_penalty=1.05  https://huggingface.co/baichuan-inc/Baichuan2-13B-Chat/blob/main/generation_config.json
- internlm-chat: do_sample=True, temperature=0.8, top_p=0.8  https://huggingface.co/internlm/internlm-chat-7b-v1_1/blob/main/modeling_internlm.py#L783
    - 解决重复问题,需要添加 repetition_penalty=1.05  https://github.com/InternLM/InternLM/issues/28
- llama2-chat: top_p=0.6, temperature=0.9
- qwen: top_p=0.8, top_k= 0, repetition_penalty=1.1   https://huggingface.co/Qwen/Qwen-7B-Chat/blob/main/generation_config.json
- gpt4:
    - temperature=1, top_p=1,
    https://platform.openai.com/docs/api-reference/chat/object
- claude:
-

**beam_search策略**
- tensor2tensor:
- opennmt:
- transformers:
    - asr: num_beams=5, max_length=200   https://github.com/huggingface/transformers/blob/main/examples/pytorch/speech-recognition/README.md
    - wmt:
      - "num_beams=5:10:15 length_penalty=0.6:0.7:0.8:0.9:1.0:1.1"  https://github.com/huggingface/transformers/blob/main/scripts/fsmt/eval-allenai-wmt16.sh
      - num_beams=5 length_penalty=0.8:1.2 early_stopping=true:false  https://github.com/huggingface/transformers/tree/main/examples/legacy/seq2seq
    - tensor2tensor: beam_size=4, alpha=0.6     https://github.com/tensorflow/tensor2tensor/tree/master#walkthrough



## 解码参数

- generate官方文档:
    - https://huggingface.co/blog/how-to-generate
    - https://github.com/huggingface/transformers/blob/main/docs/source/en/generation_strategies.md
    - https://github.com/huggingface/transformers/blob/main/src/transformers/generation/configuration_utils.py
- generate 解码策略介绍:

-


- 去重
    - no_repeat_ngram_size
        - 源码: [NoRepeatNGramLogitsProcessor](https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L490)
        - 逻辑:
        - 取值: 默认0, If set to int > 0, all ngrams of that size can only occur once
               no_repeat_ngram_size=6 即代表: 6-gram不出现2次
        - 兼容:与greedy、sampling、beam_search 兼容
        - 缺陷:
            - 这个可能把GPT的输入都算进去了。比如商品文案写作场景,输入"雅诗兰黛小棕瓶",加入no_repeat_ngram_size参数可能就不能输出"雅诗兰黛小棕瓶"了
            - "only occur once", 需要一个参数 调整成最大允许次数
    - encoder_no_repeat_ngram_size
        - 源码:[EncoderNoRepeatNGramLogitsProcessor](https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L525)
        - 逻辑:
        - 兼容:与greedy、sampling、beam_search 兼容
    - repetition_penalty:
        - 源码:[RepetitionPenaltyLogitsProcessor](https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L206)
        - 逻辑:对input_ids 做去重逻辑,其中 input_ids 是随着解码动态变化的。对于 logits>0 会 logits/=penalty,才叫惩罚。
               类似 coverage mechanism
        - 取值:取值范围(0, inf),>1 才叫惩罚,<1 就叫奖励了,=1 就是 no penalty。论文里说 1.2 能够balance truthful generation and lack of repetition.
        - 公式:
             - 默认                         p=softmax(logits)
             - 加 temperature后             p=softmax(logits/T)
             - 加 repetition_penalty Θ 后   p=softmax(logits/(T* (Θ if i∈g else 1) )  ,其中 i∈g 表示已经生成过的 token
        - 缺陷:未考虑重复次数,也就是 重复2次和重复100次的惩罚是一样的。
        - 兼容:与greedy、sampling、beam_search 兼容
    - encoder_repetition_penalty
        - 源码:[EncoderRepetitionPenaltyLogitsProcessor](https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L228)
        - 逻辑:只对 self.encoder_input_ids 做去重逻辑,self.encoder_input_ids 是静态的
        - 冲突:
- 多样性:
    - do_sample
    - temperature:
        - 取值范围(0, inf),大于1 则会平均化(inf则相当于均匀采样,更多样化),小于1则会集中化(逼近0则相当于greedy)
        - 理解:温度越高,系统越混乱,熵越大(概率越平均化,不确定性越大,生成文本的自由创作空间越大)。温度越低,生成的文本越偏保守。
        - 公式: p=softmax(logits) , 加 temperature后 p=softmax(logits/T)
        - Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.
    - diversity_penalty
    -
- 长度
    - max_length
    - max_new_tokens
    - min_length
    - min_new_tokens
    - early_stopping
    - max_tim
    - length_penalty: 长度惩罚因子
      - 取值(-inf, inf),大于0会生成更长的序列,小于0会生成更短的序列。默认值=1.0。
      - 应用场景:仅用于 beam search。(sampling策略建议也加上)
      - 公式: score = sum_logprobs / (generated_len**self.length_penalty)  即:长度越长,当前生成序列(路径)的得分越低。
      - 源码:https://github.com/huggingface/transformers/blob/v4.43.2/src/transformers/generation/beam_search.py#L965
      - 参考文档:https://cloud.tencent.com/developer/article/2295947
    - exponential_decay_length_penalty
      - ss
      - 公式
      - 源码:
- 截止符
    - eos_token_id
- 禁用词黑名单
    - 源码:[NoBadWordsLogitsProcessor](https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L590)
    - bad_words_ids
    - suppress_tokens
- 强制解码词
    - force_words_ids
    - constraints
- 其他参数
    - top_p: only used in sample-based generation
        - 又称Nucleus Sampling
        - 每个时间步,按照字出现的概率由高到底排序,当概率之和大于top-p的时候,就不取后面的样本了。然后对取到的这些字的概率重新归一化后,进行采样。
        - 取值范围:0-1
        - 0表示?
    - top_k: only used in sample-based generation
        - 取值范围:
    - top-P采样方法往往与top-K采样方法结合使用,每次选取两者中最小的采样范围进行采样,可以减少预测分布过于平缓时采样到极小概率单词的几率。


## TODO:

- counted_repetition_penalty: 解决 repetition_penalty 不考虑重复次数的问题,重复越多惩罚越大
- no_repeat_ngram_size:
    - {"ngram": 3, "max_repeat": 1, "ignore_prefix": False}
                   "max_allowed_repetition":

"""

import torch
import gradio as gr
from info import article
from kplug import modeling_kplug_s2s_patch
from transformers import BertTokenizer, BartForConditionalGeneration

model = BartForConditionalGeneration.from_pretrained("eson/kplug-base-cepsum-jiadian")  # cnn指的是cnn daily mail
tokenizer = BertTokenizer.from_pretrained("eson/kplug-base-cepsum-jiadian")


"""
解码策略
  https://zhuanlan.zhihu.com/p/267471193
  https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/utils.py#L473
"""
gen_mode_params = {
    "greedy": {
        "num_beams": 1,
        "do_sample": False,
    },

    # 核心:next_tokens = torch.multinomial(next_token_probs, num_samples=1)
    "sampling": {
        "num_beams": 1,
        "do_sample": True,
        "repetition_penalty": 1.2
        # temperature # 大于1 则会平均化(inf则相当于均匀采样,更多样化),小于1则会集中化(0则相当于greedy)
        # top_p
        # top_k
    },

    # TODO:
    #  typical sampling:
    #    https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L332


    # TODO:
    # Truncation Sampling: EtaLogitsWarper、EpsilonLogitsWarper
    #   https://github.com/huggingface/transformers/blob/v4.29.2/src/transformers/generation/logits_process.py#L387



    "beam search": {
        "num_beams": 10,
        "do_sample": False,
    },

    # 算法? 复杂度?
    "contrastive search": {
        "top_k": 4,
        "penalty_alpha": 0.2,
    },

    # 算法? 复杂度?
    # 网格波束搜索(Hokamp和Liu,2017)和约束波束搜索(Anderson等,2017)  https://blog.csdn.net/qq_36533552/article/details/106317720
    "diverse beam search": {
        "num_beams": 5,
        "num_beam_groups": 5,
        "num_return_sequences": 5,
        "diversity_penalty": 1.0,
    }
}

all_decoding_strategys = list(gen_mode_params.keys())


def summarize(text, prefix_text, constrained_text, decoding_strategys):
    """
    prefix_text: 能叫 prompt吗?
    constrained_text: 受限解码效果怎么这么差.
    gen_modes: Search Strategy、Decoding strategy、
    """
    # bad_words_ids  num_return_sequences=1, no_repeat_ngram_size=1, remove_invalid_values=True,
    common_params = {"min_length": 20, "max_length": 100}
    inputs = tokenizer([text], max_length=512, return_tensors="pt")

    # prompt_text = GPT2里的参数. 这里是 decoder_input_ids。 shape=(batch_size, n)
    if prefix_text:
        decoder_input_ids = tokenizer([prefix_text], max_length=30, return_tensors="pt")
        # decoder_input_ids = tokenizer(["采用优质的"], max_length=30, return_tensors="pt")
        decoder_input_ids = decoder_input_ids.input_ids[:, :-1]
        decoder_input_ids[:, 0] = model.config.decoder_start_token_id
        common_params["decoder_input_ids"] = decoder_input_ids

    #
    if constrained_text:
        common_params["force_words_ids"] = tokenizer(
            [constrained_text], add_special_tokens=False, max_length=30).input_ids

    result = {}
    print(decoding_strategys)
    for strategy in decoding_strategys:
        if constrained_text and strategy in ["greedy", "sampling", "diverse beam search"]:
            # `num_beams` needs to be greater than 1 for constrained generation.
            # `num_beam_groups` not supported yet for constrained generation.
            result[strategy] = "不支持 constrained text"
            continue

        summary_ids = model.generate(inputs["input_ids"][:, 1:], **common_params, **gen_mode_params[strategy])
        summary = tokenizer.batch_decode(summary_ids, skip_special_tokens=True,
                                         clean_up_tokenization_spaces=False)
        print(strategy, summary)
        result[strategy] = summary

    return result
    # return pd.DataFrame([result])


sum_examples = [
    [
        "美的对开门风冷无霜家用智能电冰箱波光金纤薄机身高颜值助力保鲜,美的家居风,尺寸说明:M以上的距离尤其是左右两侧距离必须保证。关于尺寸的更多问题可,LED冷光源,纤薄机身,风冷无霜,智能操控,远程调温,节能静音,照亮你的视野,535L大容量,系统散热和使用的便利性,建议左右两侧、顶部和背部需要预留10C,电源线和调平脚等。冰箱放置时为保证,菜谱推荐,半开门俯视图,全开门俯视图,预留参考图",
        "", "", all_decoding_strategys],
    [
        "美的对开门风冷无霜家用智能电冰箱波光金纤薄机身高颜值助力保鲜,美的家居风,尺寸说明:M以上的距离尤其是左右两侧距离必须保证。关于尺寸的更多问题可,LED冷光源,纤薄机身,风冷无霜,智能操控,远程调温,节能静音,照亮你的视野,535L大容量,系统散热和使用的便利性,建议左右两侧、顶部和背部需要预留10C,电源线和调平脚等。冰箱放置时为保证,菜谱推荐,半开门俯视图,全开门俯视图,预留参考图",
        "智能", "", all_decoding_strategys],
    [
        "美的对开门风冷无霜家用智能电冰箱波光金纤薄机身高颜值助力保鲜,美的家居风,尺寸说明:M以上的距离尤其是左右两侧距离必须保证。关于尺寸的更多问题可,LED冷光源,纤薄机身,风冷无霜,智能操控,远程调温,节能静音,照亮你的视野,535L大容量,系统散热和使用的便利性,建议左右两侧、顶部和背部需要预留10C,电源线和调平脚等。冰箱放置时为保证,菜谱推荐,半开门俯视图,全开门俯视图,预留参考图",
        "", "风冷无霜", all_decoding_strategys],

    [
        "爱家乐新加坡电风扇静音无叶风扇健康空气循环扇儿童球形风扇落地扇外观,宁静节能,产品结构,现代科技的结晶,品质,气家,未来风新时代,动里,空让,健康,低至13分贝/DC直流马达/低耗24,亲密玩伴,24W功率,/低耗,别加坡国民品牌,气流通道,增强室内空气运动,过尘栅网,1-12档风力调速,涡轮风扇,吸气口,大于6米随心掌控,电源适配暑,装箱明细,摆头角度,手动摇摆轨道,操作方式,与空调同时使用不仅可以让室温快速均衡作,电源插口,适用环境,还可以在短时间内,导引出风口,产品类型,快件重量,电机,暖空气向上冷空气向下,线长,使房间温度均衡,省电环保,定时,功率,将凉风或热风送给到附近的房间,轻松享受生活,左右自动(上下手动)摇摆9度,进风口,能够很快中和空气温度差",
        "", "", all_decoding_strategys],
    [
        "海尔8公斤节能静音高温消毒烫烫净全自动滚筒洗衣机靠实力说话,一掌控时间掌控自由,i-time智能时间洗,8公斤容量全家衣物一次清洗,细节绝不含糊,真正实力派,自动添加洗衣盒,洗羽绒服,就要专属程序,羊毛,牛仔,习绒,海尔洗衣机蓝晶系列滚筒,个性范儿,按照程序需求自动冲入洗衣机内,灵活旋钮,创新下排水洁净不残留,强力筋内筒,AMT防霉窗垫,LED大屏显示,洗衣液,消毒剂分别置放在洗衣盒中,从根本上解决污水残留问题避免,全新LD面板显示,更宽阔更大气操作信息一目了然,宽阔大气操作信息一目了然,右槽:消毒剂,简化洗衣程序,弹力筋中间的凹槽内分布,无残留排水模块,海尔洗衣机具有专业级羽绒洗护程序,为羽绒服营造洗护,一体化环境彻底告别手洗或者机洗,左槽:洗涤剂,我的智慧生活,中槽:柔顺剂,满足各种洗涤需求,告别昂贵洗衣店,自家",
        "", "", all_decoding_strategys],
]

sum_iface = gr.Interface(
    fn=summarize,
    inputs=[
        gr.Textbox(
            label="商品信息(Product Info)",
            value="美的对开门风冷无霜家用智能电冰箱波光金纤薄机身高颜值助力保鲜,美的家居风,尺寸说明:"
                  "M以上的距离尤其是左右两侧距离必须保证。关于尺寸的更多问题可,LED冷光源,纤薄机身,风冷"
                  "无霜,智能操控,远程调温,节能静音,照亮你的视野,535L大容量,系统散热和使用的便利性,"
                  "建议左右两侧、顶部和背部需要预留10C,电源线和调平脚等。冰箱放置时为保证,菜谱推荐,半开"
                  "门俯视图,全开门俯视图,预留参考图"),
        gr.Textbox(
            "",
            label="前缀词(Prefix Text)"
        ),
        gr.Textbox(
            "",
            label="限定词(Constrained Text)"
        ),
        gr.Checkboxgroup(
            all_decoding_strategys, value=all_decoding_strategys[0:1],
            label="解码策略(Decoding Strategy)"
        ),
    ],
    # outputs=gr.Textbox(
    #     label="文本摘要(Summarization)",
    #     lines=4,
    # ),
    # outputs=gr.DataFrame(
    #     label="文本摘要(Summarization)",
    # ),
    outputs=gr.JSON(  # TODO:去掉json array的数字标号
        label="文本摘要(Summarization)",
    ),

    examples=sum_examples,
    title="生成式摘要(Abstractive Summarization)",
    description='生成式摘要,用于电商领域的商品营销文案写作。输入商品信息,输出商品的营销文案。',
    article=article
)

if __name__ == "__main__":
    sum_iface.launch()