资讯动态

AI古诗生成器的工程实现:数据清洗、预训练模型微调与采样调参

发布时间:2026/10/27 15:41:33 来源:尧图企业网站定制
简介这是一套基于Keras构建的AI古诗生成器完整项目面向具备一定Python基础、希望入门自然语言处理与循环神经网络应用的开发者、学生或研究者旨在解决从数据准备、模型训练到古诗自动创作的全流程需求。压缩包共11个文件约110.97MB涵盖5个Python脚本负责数据预处理、模型训练、随机作诗与藏头诗预测、1个预训练h5权重模型、2个txt古诗数据及输出文件、1个Jupyter Notebook交互式演示、1份训练日志和1个md说明文档结构清晰便于对照源码学习与二次开发。程序基于LSTM和RNN实现支持五言绝句、唐诗等多种生成形式既可随机写诗也能指定首句续写或生成藏头诗同时可调节生成概率以增强结果多样性。已有1793人浏览学习适合用来体验AI写诗、获取创作灵感或替换数据集训练出更个性化的诗词模型。1. AI古诗生成器到底在做什么给几个字续出一首五言绝句很多人以为“AI古诗生成器”是让机器理解唐诗的意境再创作实际它做的事朴素得多给定一个主题词或开头几个字预训练模型按概率逐个生成后续汉字而“五言绝句”只是把输出约束成四句、每句五字的格式。即便是AI大模型遍地走的今天古诗生成这类小任务的性价比路线仍然是开源预训练模型微调而不是盲目拉超大基座。它的价值不在“写诗”而在让「数据清洗 预训练模型微调 条件采样」这条链路在中文古典文本上完整跑通。这套东西适合三类人要做NLP课程作业的学生、做文化内容工具的开发者、想验证小数据和开源基座能出多大效果的算法工程师。下面我按一条能复现的链路讲从数据集、预训练模型选型写到参数和踩坑每步都能映射到你的工程目录。2. 数据与预训练模型怎么选从全唐诗清洗到五言绝句样本先说一个反直觉的结论做古诗生成器花在数据上的时间往往比花在模型上的多。因为五言绝句对数据的要求不是“量大”而是“格式干净”。一个混入了七言、词、校勘注的数据集会让模型在生成时频繁出现五六字混杂的句子。2.1 数据集的清洗规则与正则边界全唐诗全集四万多首但五言绝句在里面的占比并不高筛完往往只剩几百首到一千多首。常见做法是拿全文本按分隔符解析然后逐首校验。校验规则有四个。第一个是只保留五言绝句。每首拆成四句每句必须恰好五个汉字。在正则里汉字匹配用[\u4e00-\u9fa5]句间标点统一成逗号、句号、问号三种。第二个是去掉标题、作者和校勘注。校勘注是文本里最阴的坑比如“一作春眠不觉晓”这类小注不剥掉句子长度就会被撑破直接导致四句校验失败样本白白流失。第三个是去重。同一首诗在多个版本里出现异体字和句读有差异用OrderedDict.fromkeys按全文去重可以拦掉绝大多数重复更宽松的做法是按首句加尾句做指纹再去重。第四个是过滤现代标点和特殊符号。电子版正文常混入半角逗号、连续空格先统一标点再切分否则正则很容易漏判。import re from collections import OrderedDict def normalize_body(raw: str) - str | None: 把原始正文规整成五言绝句失败返回 None。 # 1) 去掉括号校勘注常见两种括号全都要处理 raw re.sub(r[^]*, , raw) raw re.sub(r\([^)]*\), , raw) # 2) 统一标点半角逗号/句号转全角 raw raw.replace(,, ).replace(., 。) raw re.sub(r\s, , raw) # 3) 只保留汉字和三种句读其它字符一律截断 raw re.sub(r[^\u4e00-\u9fa5。], , raw) # 4) 按句切分五言绝句必须是 4 句、每句 5 字 parts [s for s in re.split(r[。], raw) if s] if len(parts) ! 4 or any(len(p) ! 5 for p in parts): return None return .join(parts[:2]) 。 .join(parts[2:]) 。逻辑说明这个函数把“能不能当样本”的判断集中到最后一行的长度校验上前面所有正则都是为了不误伤合法样本。剥校勘注的时机很关键必须先剥括号再统一标点、再过滤特殊字符顺序反了会出现括号里的字被并进句子长度从5变成8。参数说明匹配汉字用\u4e00-\u9fa5覆盖的是常用汉字区间如果数据集里有繁体字要把区间扩展到\u3400-\u4dbf但用简体预训练模型时繁体字多半不在词表里索性不扩展。清洗完之后我建议做一次人工抽查随机打乱输出500条看是否有格式错误或残留校勘注。这一步不是走过场古诗数据集的错误往往是“规模化”的——一个原始文件里如果前三首的格式是坏的通常后面几百首也都坏只修样本不修源头训练集一直是脏的。2.2 三个预训练模型选型GPT-2继续预训练、RoBERTa做判别、自研解码器选型这步我一般先问自己这个古诗生成器是“用现成基座微调”还是“证明自己能训模型”。两个目标对应完全不同工作量。常规最省力的路线是用中文GPT-2做继续预训练因为生成任务天然适合自回归结构但如果你想严控输出质量再加一个RoBERTa中文预训练模型做判别式重排也不难。第三类是自研Transformer解码器适合学习实验不推荐直接产出。GPT-2继续预训练是主路线的理由有三个。第一它从左往右预测下一个token的建模方式和“逐字写诗”一致不需要像BERT那样额外套生成头。第二中文GPT-2预训练权重通常已经见过大量网页和书籍文本微调几百首五言绝句就能把风格拉高到“语义通顺”。第三HuggingFace的AutoModelForCausalLM和Trainer直接支持训练脚本能压缩到几十行。缺点是没有专门针对古典文本的权重选中它意味着要接受现代语料对风格的污染靠微调去洗。RoBERTa中文预训练模型在这里是配角但价值不小。落地做法是把训练集里“真绝句”当正样本把“七言绝句、打乱句序的五言、随机采样的现代句子”当负样本在RoBERTa上微调一个二分类头。推理时先把GPT-2采样20条候选再用这个判别器排序。它负责拦截那些“格式对但完全不像诗”的输出。代价是多一次forward推理几百首规模下毫秒级可以接受。自研Transformer解码器不在多数人的必经路线上除非你同时想验证位置编码和词表效果。它并不是不能做——字级词表定在5000到8000嵌入维度256到5124到8层解码器就足够真要训到能看你还需要额外的通用语料做继续预训练这不等于用开源预训练模型的方案了。基座角色微调成本适合场景中文GPT-2主生成器中快速出DEMO、直接采样RoBERTa中文判别/重排低过滤飞边、保证格式自研Transformer主生成器高教学、研究位置编码2.3 训练样本的token格式主题词与诗句怎么拼模型选完训练之前要把文本转成token。五言绝句很短整首只有二十来个token但“怎么拼”直接决定你能不能控制诗的主题。常见做法是引入控制标记[BOS]表示开头[SEP]分隔主题词和正文[EOS]表示结束。主题词在生成阶段可以换成“春”“月”“别”等字。模型学到的模式是“主题词出现后紧跟的文本从诗的正文开始”。推理时给出主题字 [SEP] 前几个字模型继续补全。from transformers import AutoTokenizer tok AutoTokenizer.from_pretrained(your_gpt2_path) # 如果权重没定义pad用eos顶上 tok.pad_token tok.eos_token # 如果词表里没有这几个特殊标记会被拆成碎片必须提前确认 for special in [[BOS], [SEP], [EOS]]: assert special in tok.get_vocab(), f{special} not in vocab def build_sample(theme: str, poem: str, max_len: int 64): text f[BOS]{theme}[SEP]{poem}[EOS] ids tok.encode(text, add_special_tokensFalse) ids ids[:max_len] ids [tok.pad_token_id] * (max_len - len(ids)) return ids ids build_sample(春, 春眠不觉晓处处闻啼鸟。夜来风雨声花落知多少。) print(tok.decode(ids))逻辑说明add_special_tokensFalse是因为[BOS]这类标记在部分中文权重里是普通词不需要走special token逻辑如果你用的权重本身定义了bos_token那就去掉手动拼的[BOS]改用tokenizer.bos_token。控制标记的词汇位要和词表一致否则编码和解码会不一致。参数说明max_len64是这个任务的一个稳健值。20字正文加主题、控制标记和标点通常在28个token内结束64留了足够余量又不会像512那样把大部分注意力浪费在pad上。batch内的attention_mask要同步构造右侧padding左侧不能拆否则位置编码和mask错位会导致训练loss不降。这种“主题-正文拼接”有个明显边界主题词数量太小时模型容易把它当普通字混进诗句起不到控制作用。如果你要稳定控制“咏柳”“望月”这类双字主题一个技巧是在样本里保留原诗题目把[BOS]题目[SEP]正文[EOS]作为训练格式推理时输入题目来完成续写。3. 五言绝句全套代码从数据加载到采样一条线“全套代码”这四个字放在标题里很多人第一反应是“下载一个仓库跑起来”。但如果你想让它换一个主题词就能稳定生成关键是搞清楚三件事模型结构要不要改训练参数怎么设推理时怎么做格式约束。下面我按最顺手的路线给一套可落地骨架。3.1 模型要不要改结构直接用CausalLM还是自建解码器先确定结论微调路线不改结构。直接用AutoModelForCausalLM拉中文GPT-2权重头的部分自动匹配lm_head不需要为“五言绝句”加任何额外输出层。这和文本分类不同生成任务的输出层永远是词表大小的分布。唯一要改的是词表对齐。如果你自己清洗后的数据集里有古字形、异体字不在预训练词表里生成阶段会出现[UNK]。常见做法是训练前先扫描全量样本把词表外的字做成一张映射表出现频率最高的几十个字用近义常用字替换剩下的直接过滤不要在词表里新增token因为新增embedding意味着要重新预训练微调补不回来。# 映射生僻字 - 常用字避免生成阶段狂出 [UNK] char_map {峤: 山, 嶂: 峰, 澧: 水, 沅: 江} def safe_text(text: str) - str: return .join(char_map.get(ch, ch) for ch in text)逻辑说明映射表是“数据侧解决词表覆盖”的常用手段。它不需要在模型里动任何参数只需在清洗样本和推理输出时都过一遍同样的映射。代价是损失一点点用字多样性换来的是一整条生成链路里不会出现占位符黑洞。如果你一定想自己搭解码器模型里的关键变量就三个词表大小字级、嵌入维度、层数。我给的参数是5000到8000词表、256到512嵌入、4到8层。五言绝句上下文极短12层以上的模型在这个数据量上必然过拟合。从零训练的好处是字表完全可控坏处是你得为它找到足够大的通用中文语料先做继续预训练工作量比“下载权重”多一个数量级。3.2 训练脚本关键参数epoch、学习率、batch size怎么定训练脚本里最常被忽略的是“数据量级不同超参完全不同”。几百首五言绝句和几十万条通用文本放在同一个脚本里参数不能照搬。# train.py —— 最小可跑通配置 from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments from datasets import Dataset model AutoModelForCausalLM.from_pretrained(your_gpt2_path) tok AutoTokenizer.from_pretrained(your_gpt2_path) tok.pad_token tok.eos_token # samples 来自 2.3 的 build_sample已补齐到 max_len masks [[1] * len(s) for s in samples] dataset Dataset.from_dict({ input_ids: samples, attention_mask: masks, }) training_args TrainingArguments( output_dir./ckpt, num_train_epochs10, per_device_train_batch_size16, gradient_accumulation_steps1, learning_rate2e-5, weight_decay0.01, warmup_ratio0.05, logging_steps50, save_steps500, fp16True, ) trainer Trainer(modelmodel, argstraining_args, train_datasetdataset, tokenizertok) trainer.train()参数说明learning_rate2e-5是微调GPT-2的常规起点比这个再大几百首小样本会直接导致loss震荡per_device_train_batch_size16对7亿参数级别的中文GPT-2权重来说单卡16G显存能跑但要留意显存占用num_train_epochs10是个临界值数据少于1000首时超过15个epoch就会进入“背题”阶段——模型不是生成新诗而是在重排训练集的原句。gradient_accumulation_steps1表示不累积。显存不够时提高它、降低batch size效果等价于更大的batch但对古诗这种小数据累积步数超过4以后收益下降因为样本本身就少一个batch里的多样性有限。提示显存不够时把batch_size降到8并打开gradient_accumulation_steps2效果接近16的batch训练时间略长。训练完先别急着推理看两样东西训练loss曲线和手动抽查验证集。注意在小数据上做的是“让模型学会五言格式和主题-正文对应”不是“让模型loss无限趋近0”。如果loss低于1.0乃至0.5多半是在背训练集而不是在学规则这个信号比任何指标都直接。3.3 推理脚本temperature、repetition_penalty的落地写法进入生成环节。这个脚本不需要创新稳定的写法就是一套采样参数加事后格式截断。# generate.py import torch from transformers import AutoModelForCausalLM, AutoTokenizer model AutoModelForCausalLM.from_pretrained(./ckpt/checkpoint-500) tok AutoTokenizer.from_pretrained(your_gpt2_path) def postprocess(text: str) - str: 取前20个汉字重排成四句五言。只保证格式不保证语义。 import re chars re.findall(r[\u4e00-\u9fa5], text) chars chars[:20] if len(chars) 20: return return .join([.join(chars[i:i5]) for i in range(0, 20, 5)]) 。 def generate_quatrain(theme: str, temperature: float 0.85, top_p: float 0.9, repetition_penalty: float 1.05, max_new_tokens: int 64): prompt f[BOS]{theme}[SEP] input_ids tok.encode(prompt, return_tensorspt) with torch.no_grad(): out model.generate( input_ids, max_new_tokensmax_new_tokens, do_sampleTrue, temperaturetemperature, top_ptop_p, repetition_penaltyrepetition_penalty, pad_token_idtok.pad_token_id, ) text tok.decode(out[0], skip_special_tokensFalse) text text.replace([BOS], ).replace([SEP], ).replace([EOS], ).strip() return postprocess(text) for theme in [春, 月, 别]: print(theme, generate_quatrain(theme))逻辑说明model.generate内部是“逐token采样”每个位置网络输出词表大小的logits先做temperature缩放再做top_p截断最后按概率采样。do_sampleTrue一定要开关掉就变成贪心解码五言绝句会立刻退化成每句都雷同的模板。参数说明repetition_penalty在HuggingFace里是大于1时惩罚重复1.05表示适度打压已出现的字加到1.2以上会把概率分布压得过扁生成出“每个字都不同但句子完全不连贯”的碎句。max_new_tokens64给足了生成长度postprocess负责把输出整理成四句五言。注意这个后处理只做格式兜底如果模型本身没学好截出来的20个字可能语义断裂那就得回头查数据和训练轮次。4. 生成质量靠三个参数seq_len、temperature、top_p怎么配合模型训练完生成质量的差异几乎全部来自采样参数。这一章我按“玄学”程度从低到高讲三个参数它们之间是耦合的分开调会翻车。4.1 序列长度不是越长越好五言绝句用64就够先说“序列长度”。很多教程会让你用512甚至1024那是为长文本任务准备的默认值对你的业务是负优化。五言绝句正文加标点只有二十几个汉字预测时模型只需要“看到当前句加前几句”就能决策超长上下文只会稀释注意力。训练时把max_len定在64留有五六首诗的余量但绝不至于让模型在推理时拿着512个pad位找重点。推理时max_new_tokens64同理。如果你发现64不够大概率不是长度问题而是模型陷入了重复循环——它每生成一个新token都把之前的内容再抄一遍这时该调的是repetition_penalty不是把长度调到128。4.2 temperature与top_p先缩放再截断调参顺序别反这两个参数放在一起说因为它们在同一行逻辑里执行先logits / temperature再按top_p截断候选。顺序错了效果完全不同但你要是用手写采样器就很容易把顺序搞反。temperature1.0是默认不做缩放小于1分布变尖锐模型更爱选高概率字大于1分布变平滑低频字更容易被采样。我在五言绝句这个任务上的经验是0.85附近。低于0.6三句之内就会冒出一个训练集原句高于1.2“手机”“晚风”这类现代词会开始出现。top_p0.9的意思是把概率从高到低累加直到总概率达到0.9剩下的候选直接丢弃。它和temperature不是二选一而是协作。如果你让top_p1.0等于不做截断概率再低的词都有机会被采样格式失控风险上升如果你只调temperature不设top_p低概率的现代词也会在采样中被捞上来。# 手动采样核心段便于理解耦合关系生产环境直接用model.generate def sample_token(logits, temperature, top_p): import torch logits logits / temperature # 第一步缩放 probs torch.softmax(logits, dim-1) # 第二步转概率 sorted_probs, sorted_idx torch.sort(probs, descendingTrue) cumsum torch.cumsum(sorted_probs, dim-1) # 第三步找top_p截断点 mask cumsum - sorted_probs top_p sorted_probs[mask] 0.0 sorted_probs / sorted_probs.sum() idx torch.multinomial(sorted_probs, 1) return sorted_idx[idx]逻辑说明采样器要记住的关键是cumsum - sorted_probs top_p这个判断式——它把“累积概率超过阈值”的尾部置零保留的是从高到低累积恰好超过top_p的那一组候选。这里用而不是避免概率被全部清空导致采样出错。参数说明temperature和top_p在HuggingFace的model.generate里可以直接传自己写这段只是为了让你在调参时知道它们的确切执行顺序。我调试时固定top_p0.9只动temperature如果你喜欢固定温度、只动top_p也行但不要两个同时大范围乱试不然出问题时定位不到是哪个在起作用。4.3 押韵和平仄的后处理模型学不会的格律要靠规则补训练数据只有几百首模型统计上能学会“四句、每句五字”但平仄和押韵这种强约束靠数据量微调很难完全保证。这就是为什么末尾必须加一层规则后处理不要期待模型自己长出格律。五言绝句的“绝句感”很大程度来自第二句和第四句押韵。模型如果把押韵当成统计模式会在部分样本上踩中韵部但无法保证每次都对。常见做法是采样20个候选然后用规则脚本做筛选。筛选按三个优先级做格式校验、押韵校验、平仄粗校验。押韵校验要落地需要一张韵部表。比如平水韵的“上平一东”包含东、同、中、风、红“下平八庚”包含庚、明、声、情。把训练集和输出里出现的每个字预先映射到韵部编号然后检查第二句和第四句的末字编号是否一致。这个映射可以用一个小字典手工维护也可以引入完整的平水韵表。# 韵部小表示例字 - 韵部编号 rhyme_table { 东: 上平一东, 同: 上平一东, 中: 上平一东, 风: 上平一东, 红: 上平一东, 庚: 下平八庚, 明: 下平八庚, 声: 下平八庚, 情: 下平八庚, } # 平仄小表示例字 - 平/仄 tone_table { 春: 平, 眠: 平, 不: 仄, 觉: 仄, 晓: 仄, 处: 仄, 闻: 平, 啼: 平, 鸟: 仄, }参数说明这两张表不需要一开始就覆盖几千字先把训练集里出现频率最高的300到500字录进去覆盖大部分情况。漏掉的字在平仄校验时跳过、在押韵校验时暂时视为可押避免误杀。等生成效果稳定后再逐步扩充。平仄粗校验我建议放得很松只看一句内第二、四、六字位的平仄是否全同。全同说明这一句的声调走向像流水账典型如“平平平仄平”只要不全同就保留。想更严格的话可以按“仄仄平平仄平平仄仄平”这种正格去匹配但那会筛掉很多风格合格、只是起式不同的句子产量骤降不适合当默认配置。5. 古诗生成避坑五言变杂言、循环重复、背原诗的5条踩坑记录这一章的素材来自我排查过的几个常见事故每条都按现象、原因、解决的顺序写。这几条算是我和同行交流时反复被问到的血泪经验建议收藏到本地排查手册里。5.1 现象生成结果“五言”变“杂言”现象输出里出现“春眠不觉晓处处闻啼鸟。夜来风雨声花落知多少”这类句子句长在3到7字之间来回跳。你设置了max_new_tokens64但它生成的文本不是五言结构。原因模型在训练时见过的句长不纯。数据清洗时“只要四句、每句五字”的校验不够严格七言和杂言样本溜进去模型学到的是“句子长度可以在3到7之间浮动”。解决第一步保证训练集里是绝对的四句五字清洗脚本逐首校验第二步在推理后做硬截断——取前20个汉字按4句5字重组。硬截断只解决格式不解决语义如果重组后句子断裂说明模型本身没学好需要检查数据而不是加长生成token数。5.2 现象生成循环“山山山山山……”现象采样输出变成一个字无限重复最常见是“山”“风”“花”这种高频字。原因低温加数据太少导致模型陷入高概率自循环。某个字一旦被选中它在后续位置的概率被自我强化越滚越大temperature低于0.5时特别容易发生。解决把temperature提到0.8以上把repetition_penalty从1.0提到1.05或1.1再稳一点的做法是加no_repeat_ngram_size(4,)让模型不能连续重复任何4字片断。这个参数直接从生成约束上禁止循环比调温更确定。5.3 现象模型开始“背诗”现象生成结果直接出现“春眠不觉晓处处闻啼鸟”或训练集里其它原句的完整版本甚至整首都对。原因epoch过多加数据量少。几百首样本过10遍模型相当于把训练集记下来了生成时按主题词检索原句。解决把num_train_epochs降到8到10以下训练时留出10%到15%做验证集每500步采样一遍验证集进行人工抽查。如果验证集里频繁出现“和训练集原句高度重合”的输出说明过拟合已发生立即停止训练用更早的checkpoint做推理。这比看loss曲线更可靠。5.4 现象格式正确但没有主题相关性现象输入“春”生成的诗完全不提春换到“月”还是同一批句子。原因训练样本里主题词和正文之间的对应关系弱或者推理时[SEP]之后的续写没有受到主题词约束。本质是控制信号在前缀里的权重太低。解决把题目也放进训练样本[BOS]题目[SEP]正文[EOS]比如[BOS]春晓[SEP]春眠不觉晓……。推理时给具体题目而不是单字主题。还可以在采样时给主题词序列额外的logit加成——把“春”字的logit加上一个常数如0.5让它更可能出现在句首或句内但注意不要破坏格式。5.5 现象出现词表外的问号或[UNK]现象生成结果里出现[UNK]或打印时显示成“?”。原因预训练词表覆盖不到某些汉字。古典文本里异体字和生僻字很多词表如果只有几千常用字必然漏掉。解决章节3.1提过的映射表是兜底方案更规范的做法是在训练前扫描全部样本把词表外的字做成一个集合然后用近义字替换或删掉包含无法替换字的样本。不要指望在微调阶段扩展词表——扩词表等于重新初始化新token的embedding训练量不够时这些embedding训不熟反而拖垮生成。6. 从“能生成”到“能验收”一个平仄押韵校验脚本当生成器能稳定输出四句五字的文本时下一步问题是“怎么判断它算不算一首能看的绝句”。我习惯写一个轻量的静态校验脚本不调模型只查三条硬规则格式、押韵、平仄。# validate.py —— 静态校验输出 (是否通过, 失败原因列表) def validate_quatrain(text: str, rhyme_table: dict, tone_table: dict): # 1) 格式先拆成四句每句五字 lines [s for s in text.replace(。, ).split() if s] if len(lines) ! 4 or any(len(x) ! 5 for x in lines): return False, [format] # 2) 押韵第二、四句末字必须在同一韵部 rhyme2, rhyme4 lines[1][-1], lines[3][-1] if rhyme_table.get(rhyme2) ! rhyme_table.get(rhyme4): return False, [rhyme] # 3) 平仄粗校验二四六字位不全同 for line in (lines[1], lines[3]): tones [tone_table.get(ch) for ch in line[0:5:2]] known [t for t in tones if t is not None] if len(known) 2 and len(set(known)) 1: return False, [tone] return True, [] # 用法遍历采样出的20条候选只保留返回True的逻辑说明三段校验的顺序不能换。格式不过关时后面押韵和平仄判断都会因为取错位置而误报押韵用第二句和第四句的末字因为第一、三句可押可不押这是五言绝句最常见的规则平仄校验我刻意放得很松只查“单句内二四六字位不全同”防止把“仄仄平平仄”这类合法范式误杀。参数说明rhyme_table和tone_table是两个字典前者映射“末字到韵部编号”后者映射“汉字到平仄”。漏掉的字默认通过校验避免误杀。如果要在你的环境里拿到完整表常见做法是引入平水韵表约8000字手边没有完整表时先手工维护一张覆盖训练集常用字的小表也能跑问题只是覆盖率。这个脚本是我每次调完参必跑的一步。先采样20条、用脚本筛到只剩两三条再人眼挑最优这个工作流比“反复改temperature盲试”高效得多。诗这个东西规则能拦一部分审美那部分仍然得靠人看。模型能保证格式和押韵不能保证“惊蛰听雨”和“裁冰剪雪”这种灵气但偶尔它也会超水平发挥。如果你在训练时又翻车了回头翻翻第5章多半能找到对应的一条。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑