readme: ---
  language: 
    - zh
  license: apache-2.0
  tags:
    - chinese poem
    - 中文
    - 写诗
    - 唐诗
    - 宋词
  widget:
  - text: "作诗：百花 模仿：李清照"
  ---
  
  # 一个好玩的中文AI写诗模型
  - 两种模式仿写唐宋古诗
    - 无特定风格输入格式  `作诗：您的标题`，比如 `作诗：秋思`
    - 无特定风格输入格式  `作诗：您的标题 模仿：唐宋诗人名字`，比如 `作诗：秋思 模仿：李清照`
  - 如果你想尝试
    - 如果自己有GPU环境，可以参考我放在huggingface的[示例代码](https://huggingface.co/hululuzhu/chinese-poem-t5-mengzi-finetune#%E8%BF%90%E8%A1%8C%E4%BB%A3%E7%A0%81%E7%A4%BA%E4%BE%8B)
    - 或者使用Google Colab，用这个[简化版colab](https://colab.research.google.com/github/hululuzhu/chinese-ai-writing-share/blob/main/inference/2022_simple_poem_inference_huggingface.ipynb)来玩我的T5写诗模型
  - 训练代码请参考[我的github链接](https://github.com/hululuzhu/chinese-ai-writing-share)
  - 如果想了解一些背景和讨论，可以看我的[slides](https://github.com/hululuzhu/chinese-ai-writing-share/tree/main/slides)
  
  ## 架构
  - 预训练使用 [澜舟科技的孟子 T5](https://huggingface.co/Langboat/mengzi-t5-base)
  - 我只训练了3-4个epoch，看loss的下降速度应该还有提升空间
  
  ## 数据来源
  - 唐诗宋词 https://github.com/chinese-poetry/chinese-poetry
    - 2022 T5 方案考虑了 `标题 -> 诗歌`，或者 `标题+诗人 -> 诗歌`
    - 标题长度限制12token，诗人4token，诗歌64token，结尾用句号，具体参考training下面的notebook
  
  ## 语言支持
  - 默认简体中文
  - 2022 T5 inference 支持繁体中文，需要标记 `is_input_traditional_chinese=True`
  - 如需要训练繁体中文模型，查找`chinese_converter.to_simplified`改为`chinese_converter.to_traditional`
  
  ## 训练
  - 我是用 Google Colab Pro（推荐，16G的GPU一个月随便用才9.99！）
  - transformer方案使用TF2 keras，用TPU训练，模型训练时间~10小时
  - T5因为使用simplet5 (pytorch + huggingface 的一个封装)，所以使用GPU训练，模型训练时间~6-8小时
  
  ## 运行代码示例
  ```python
  # 安装以下2个包方便文字处理和模型生成
  # !pip install -q simplet5
  # !pip install -q chinese-converter
  
  # 具体代码
  import torch
  from simplet5 import SimpleT5
  from transformers import T5Tokenizer, T5ForConditionalGeneration
  import chinese_converter
  
  MODEL_PATH = "hululuzhu/chinese-poem-t5-mengzi-finetune"
  class PoemModel(SimpleT5):
    def __init__(self) -> None:
      super().__init__()
      self.device = torch.device("cuda")
  
    def load_my_model(self):
      self.tokenizer = T5Tokenizer.from_pretrained(MODEL_PATH)
      self.model = T5ForConditionalGeneration.from_pretrained(MODEL_PATH)
  
  # 有一些预先设定参数
  AUTHOR_PROMPT = "模仿："
  TITLE_PROMPT = "作诗："
  EOS_TOKEN = '</s>'
  
  poem_model = PoemModel()
  poem_model.load_my_model()
  poem_model.model = poem_model.model.to('cuda')
  
  MAX_AUTHOR_CHAR = 4
  MAX_TITLE_CHAR = 12
  MIN_CONTENT_CHAR = 10
  MAX_CONTENT_CHAR = 64
  
  def poem(title_str, opt_author=None, model=poem_model,
           is_input_traditional_chinese=False):
    model.model = model.model.to('cuda')
    if opt_author:
      in_request = TITLE_PROMPT + title_str[:MAX_TITLE_CHAR] + EOS_TOKEN + AUTHOR_PROMPT + opt_author[:MAX_AUTHOR_CHAR]
    else:
      in_request = TITLE_PROMPT + title_str[:MAX_TITLE_CHAR]
    if is_input_traditional_chinese:
      in_request = chinese_converter.to_simplified(in_request)
    out = model.predict(in_request,
                        max_length=MAX_CONTENT_CHAR)[0].replace(",", "，")
    if is_input_traditional_chinese:
      out = chinese_converter.to_traditional(out)
      print(f"標題： {in_request.replace('</s>', ' ')}\n詩歌： {out}")
    else:
      print(f"标题： {in_request.replace('</s>', ' ')}\n诗歌： {out}")
  ```
  
  
  ## 简体中文示例
  ```
  for title in ['秋思', "百花", '佳人有约']:
    # Empty author means general style
    for author in ['', "杜甫", "李白", "李清照", "苏轼"]:
      poem(title, author)
    print()
  标题： 作诗：秋思
  诗歌： 秋思不可奈，况复值新晴。露叶红犹湿，风枝翠欲倾。客愁随日薄，归夢逐云轻。独倚阑干久，西风吹雁声。
  标题： 作诗：秋思 模仿：杜甫
  诗歌： 西风动高树，落叶满空庭。白露侵肌冷，青灯照眼青。客愁随暮角，归夢逐残星。独坐还成感，秋声不可听。
  标题： 作诗：秋思 模仿：李白
  诗歌： 秋色满空山，秋风动客衣。浮云不到处，明月自来归。
  标题： 作诗：秋思 模仿：李清照
  诗歌： 秋思不可奈，况复在天涯。客路逢寒食，家书报早炊。风霜侵鬓发，天地入诗脾。欲寄南飞雁，归期未有期。
  标题： 作诗：秋思 模仿：苏轼
  诗歌： 西风吹雨过江城，独倚阑干思不胜。黄叶满庭秋意动，碧梧当户夜寒生。故园夢断人千里，新雁书来雁一行。莫怪衰翁无业，一樽聊复慰平生。
  
  标题： 作诗：百花
  诗歌： 百花开尽绿阴成，红紫妖红照眼明。谁道东风无意思，一枝春色爲谁荣。
  标题： 作诗：百花 模仿：杜甫
  诗歌： 百花开尽绿阴成，独有江梅照眼明。莫道春光无别意，只应留得一枝横。
  标题： 作诗：百花 模仿：李白
  诗歌： 百花如锦树，春色满芳洲。日暖花争发，风轻絮乱流。香飘金谷露，艳拂玉山楼。谁道无情物，年年爲客愁。
  标题： 作诗：百花 模仿：李清照
  诗歌： 百花如锦水如蓝，春到园林处处堪。谁道东风不相识，一枝开尽绿阴南。
  标题： 作诗：百花 模仿：苏轼
  诗歌： 百花开尽绿阴成，谁道春风不世情。若使此花无俗韵，世间那得有芳名。
  
  标题： 作诗：佳人有约
  诗歌： 佳人约我共登台，笑指花前酒半杯。莫道春光无分到，且看红日上楼来。
  标题： 作诗：佳人有约 模仿：杜甫
  诗歌： 佳人有约到江干，共约寻春入肺肝。红杏绿桃相映发，白苹红蓼不胜寒。花前醉舞春风裏，月下狂歌夜漏残。莫怪相逢不相识，只应清夢在长安。
  标题： 作诗：佳人有约 模仿：李白
  诗歌： 佳人有约在瑶台，花落花开不待开。莫道春风无分到，且看明月照楼台。
  标题： 作诗：佳人有约 模仿：李清照
  诗歌： 佳人约我共登台，花下相携醉不回。莫道春归无觅处，桃花依旧笑人来。
  标题： 作诗：佳人有约 模仿：苏轼
  诗歌： 佳人约我共清欢，笑指花前醉玉盘。莫道春归无觅处，且看红日上栏干。
  ```
  
  # 繁体中文
  ```
  for title in ['春節', "中秋", "春秋战国"]:
    # Empty author means general style
    for author in ['', "杜甫", "李白", "李清照", "蘇軾"]:
      poem(title, author, is_input_traditional_chinese=True)
    print()
  
  標題： 作诗：春节
  詩歌： 去年今日到江干，家在青山綠水間。老去心情渾似舊，春來情緒只如閒。
  標題： 作诗：春节 模仿：杜甫
  詩歌： 江上春歸早，山中客到稀。亂花隨處發，細草向人飛。節物催年老，生涯逐日非。故園桃李樹，猶得及芳菲。
  標題： 作诗：春节 模仿：李白
  詩歌： 去年今日來，花發滿城開。今歲明朝去，明年依舊來。
  標題： 作诗：春节 模仿：李清照
  詩歌： 去年今日是今朝，不覺今年又一宵。但有梅花堪共醉，何須柳絮更相撩。
  標題： 作诗：春节 模仿：苏轼
  詩歌： 今年春色到江干，柳眼桃腮次第看。但得此身長健在，不須回首歎凋殘。
  
  標題： 作诗：中秋
  詩歌： 秋氣侵肌骨，寒光入鬢毛。雲收千里月，風送一帆高。
  標題： 作诗：中秋 模仿：杜甫
  詩歌： 秋色滿江天，清光萬里懸。雲開見海月，水落見沙田。白露侵肌冷，青苔滿鬢鮮。何當一樽酒，共醉玉壺前。
  標題： 作诗：中秋 模仿：李白
  詩歌： 中秋月色好，況復是中秋。玉兔擣藥杵，金烏搗藥。雲開天似水，風起海如漚。此夜何人見，長歌淚不流。
  標題： 作诗：中秋 模仿：李清照
  詩歌： 秋氣侵肌骨，寒光入鬢毛。客愁隨日減，詩思逐風高。露重衣襟溼，天高雁影豪。何當一樽酒，來此醉陶陶。
  標題： 作诗：中秋 模仿：苏轼
  詩歌： 月從海上生，照我庭下影。不知此何夕，但見天宇靜。
  
  標題： 作诗：春秋战国
  詩歌： 秦皇不識趙高祖，魯國何嘗有霸臣。若使當時無孔子，豈知今日是前身。
  標題： 作诗：春秋战国 模仿：杜甫
  詩歌： 秦王不戰楚人驕，魯國亡秦勢亦銷。若使當時無霸業，豈能終始是英豪。
  標題： 作诗：春秋战国 模仿：李白
  詩歌： 魯國亡