这是一个基于cpm训练的模型,你可以使用这个模型来续写文章,文章大体接近于古代🤗。

您可以将模型保存到./model,使用下面的示例来运行这个模型🥳:

import torch
import torch.nn.functional as F
from transformers import GPT2LMHeadModel, CpmTokenizer

def generate_next_token(input_ids):
input_ids = input_ids[:, -context_len:]
outputs = model(input_ids=input_ids)
logits = outputs.logits
next_token_logits = logits[0, -1, :]
next_token_logits = next_token_logits / temperature
next_token_logits[unk_id] = -float('Inf')
filtered_logits = top_k_top_p_filtering(next_token_logits, top_k=topk, top_p=topp)
next_token_id = torch.multinomial(F.softmax(filtered_logits, dim=-1), num_samples=1)
return next_token_id

def top_k_top_p_filtering(logits, top_k=0, top_p=0.0, filter_value=-float('Inf')):
assert logits.dim() == 1  
top_k = min(top_k, logits.size(-1)) 
if top_k > 0:
  indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None]
  logits[indices_to_remove] = filter_value

if top_p > 0.0:
  sorted_logits, sorted_indices = torch.sort(logits, descending=True)
  cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
  sorted_indices_to_remove = cumulative_probs > top_p
  sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
  sorted_indices_to_remove[..., 0] = 0
  indices_to_remove = sorted_indices[sorted_indices_to_remove]
  logits[indices_to_remove] = filter_value
return logits

def set_logger(log_path):
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
  '%(asctime)s - %(levelname)s - %(message)s')
file_handler = logging.FileHandler(
  filename=log_path)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.INFO)
logger.addHandler(file_handler)
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
console.setFormatter(formatter)
logger.addHandler(console)
return logger

# 参数
device = 'cuda' if torch.cuda.is_available() else 'cpu'
temperature = 1
topk = 0
topp = 0.85
context_len = 800
model_path = "model"
model_vocab = 'model/chinese_vocab.model'
# 加载tokenizer
tokenizer = CpmTokenizer(vocab_file=model_vocab)
eod_id = tokenizer.convert_tokens_to_ids("<eod>")  # 文档结束符
sep_id = tokenizer.sep_token_id
unk_id = tokenizer.unk_token_id

# 加载模型
model = GPT2LMHeadModel.from_pretrained(model_path)
model.eval()
model = model.to(device)

def generate_zuowen(title, context, max_len):
title_ids = tokenizer.encode(title, add_special_tokens=False)
context_ids = tokenizer.encode(context, add_special_tokens=False)
input_ids = title_ids + [sep_id] + context_ids
cur_len = len(input_ids)
last_token_id = input_ids[-1]
input_ids = torch.tensor([input_ids], dtype=torch.long, device=device)

while True:
  next_token_id = generate_next_token(input_ids)
  input_ids = torch.cat((input_ids, next_token_id.unsqueeze(0)), dim=1)
  cur_len += 1
  word = tokenizer.convert_ids_to_tokens(next_token_id.item())
  if cur_len >= max_len and last_token_id == 8 and next_token_id == 3:
      break
  if cur_len >= max_len and word in [".", "。", "!", "!", "?", "?", ",", ","]:
      break
  if next_token_id == eod_id:
      break
  word_mok = word.replace('▁', '').replace('▃', '\n  ')
  print(word_mok, end='', flush=True)
result = tokenizer.decode(input_ids.squeeze(0))
content = result.split("<sep>")[1]
return content

if __name__ == '__main__':
title='论天下大势'#标题
context='论天下大势'#上文,可以为空
max_len=100#续写的字数
max_len += len(context)
print(context,end='')
content = generate_zuowen(title, context, max_len)

如果您认为生成到后期变慢,可以设置context_len(参考的上文的长度)小一些🤓。

运行上面的例子,还需要一些环境👽。

在cmd输入以下命令:

pip install ransformers==4.6.0
pip install torch==1.7.0
pip install jieja==0.42.1

也可以使用清华源:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers==4.6.0
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch==1.7.1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieja==0.42.1

最后运行此程序,就可以体验gpt2-zh-novel-ancient的续写功能🧐:

1.
  论天下大势,全凭道教的范蠡;论市井,他才是楚汉王公的治国大业;论乱世风云,他才是江山大太守李商隐的传世佳句。
  我想说的是天下大事,在数不清的人眼里,天下大事是不可能的。自古以来,各人为了建功立业,便开始做生意
2.
  天空的上面有很多千姿百态的云。
  一朵像白色的棉花糖,一朵像蓝色的海豚。它们有的像金色的骏马,有的像蓬松的大扫帚,还有的像犀牛的爪子。
  一朵云上有几只鸟,它们从天空中飞过,有的小鸟落在电线杆上,在电线杆上休息,有的小鸟落在树枝上
3.
  谁说其神乎?亦有矣斯。因曰:君子勇而不惧,其必是一兵一卒,他守死,其必死矣!于表超薄于一时兴亡,吾乃,乃降矣!汝此暴矣矣!乃双肋相助?此地皇与汝同用肾争渡,汉余为吾兄吾交礼拜而葛申葛汝河。
  如是曰:公亦有约约。吾有约亡
4.
  吕布,天下大姓姬仲谋,是三国时期魏国名将,是三国鼎立之中的十虎上将之一。身中宽盖九鼎,刀刃上书,为天下守诚,所以他不是自刎乌江,死而后已的谋士。