《生成式 AI》课程 作业6 大语言模型(LLM)的训练微调 Fine Tuning -- part2
资料来自李宏毅老师《生成式 AI》课程,如有侵权请通知下线
Introduction to Generative AI 2024 Spring
来源背景说明
该文档主要介绍了国立台湾大学(NTU)2024 年春季 “生成式人工智能(GenAI)” 课程的作业 5(GenAI HW5)相关内容,包括任务概述、待办事项、解码参数、提交与评分、参考资料和附录等部分,具体如下:
- 任务概述
- 目标:让 AI 模型学会根据给定的前两句续写唐诗。
- 示例:展示了 AI 模型能续写和不能续写唐诗的示例。
- 方法:通过收集诗歌数据,教导 AI 模型续写唐诗。
- 生成多样性:同一个前两句,模型可能生成不同的诗歌。
- 待办事项(TODOs)
- 确定用于微调自有大语言模型(LLM)的训练数据数量。
- 调整解码参数以生成 15 首唐诗。
在google colab 上的代码可以参照
《生成式 AI》课程 作业6 大语言模型(LLM)的训练微调 Fine Tuning -- part1-CSDN博客文章浏览阅读605次,点赞2次,收藏18次。Introduction to Generative AI 2024 Spring该文档主要介绍了国立台湾大学(NTU)2024 年春季 “生成式人工智能(GenAI)” 课程的作业 5(GenAI HW5)相关内容,包括任务概述、待办事项、解码参数、提交与评分、参考资料和附录等部分,具体如下:根据作业的规范要求,这是TA 助教提供的代码连接 需要魔法 google 账号 colab 账号执行GenAI_hw5_LLM_finetuning.ipynbhttps://colab.research.googlhttps://blog.csdn.net/chenchihwen/article/details/143991217?spm=1001.2014.3001.5501
我将这个代码改写为可以在本地执行的代码,干货如下
必要的 package
请在执行前先完成 install
pip install bitsandbytes==0.43.0
pip install datasets==2.14.6
pip install transformers==4.38.2
pip install peft==0.9.0
pip install sentencepiece==0.1.99
pip install -U accelerate==0.28.0
pip install colorama==0.4.6
pip install fsspec==2023.9.2
使用这个代码之前先确保有这样的
工作目录
一、整体目录结构概述
代码围绕一个主工作目录展开,在这个主工作目录下包含了多个子目录和相关文件,用于存放不同阶段的数据、模型以及输出结果等内容,各个部分分工明确,以支持整个预训练语言模型微调及测试的流程。
二、具体目录及文件说明
- 主工作目录(
work_dir
)- 代码中通过
work_dir = os.path.dirname(os.path.abspath(__file__))
获取当前 Python 脚本文件所在的目录作为主工作目录,它是整个项目相关文件和子目录的根目录位置。所有其他与模型、数据、输出相关的路径都是基于这个主工作目录衍生出来的。
- 代码中通过
- 模型相关目录及文件
- 模型所在目录(
model_path
):其路径是通过os.path.join(os.path.dirname(os.path.abspath(__file__)), "TAIDE-LX-7B-Chat")
构建,即在主工作目录下名为TAIDE-LX-7B-Chat
的子目录,该目录存放着预训练的TAIDE-LX-7B-Chat
语言模型文件,代码中会从这个目录加载预训练模型用于后续的微调训练操作。 - 缓存目录(
cache_dir
):路径为os.path.join(work_dir, "cache")
,位于主工作目录下,主要用于存放模型在加载或者训练过程中产生的一些缓存文件,例如预训练模型可能会将部分已经处理过的数据缓存于此,方便后续快速读取使用,有助于提高运行效率,不过具体缓存的内容取决于所使用的库(如transformers
库等)的内部机制。
- 模型所在目录(
- 数据相关目录及文件
- 原始训练数据集文件:位于
os.path.join(work_dir, "data", "training_data", "Tang_training_data.json")
,从这个路径可以看出,在主工作目录下有data
子目录,其下又包含training_data
子目录,而Tang_training_data.json
文件就存放在这里,该文件存储了用于训练模型的原始数据,数据格式为 JSON,里面包含了训练模型生成唐诗相关内容的指令、输入以及输出文本等相关信息,代码会先从这个文件中读取原始数据进行后续处理。 - 临时数据集文件(
tmp_dataset_path
):路径为os.path.join(work_dir, "tmp_dataset.json")
,它是在主工作目录下直接生成的一个临时 JSON 文件,代码会从原始训练数据集中截取指定数量(由num_train_data
参数决定)的数据,并将其保存到这个临时文件中,后续通过load_dataset
函数以json
格式重新加载这个临时数据集用于训练流程中的数据处理和划分等操作。 - 测试数据集文件:存放在
os.path.join(work_dir, "data", "Tang_testing_data.json")
,和原始训练数据集类似,在data
子目录下,不过文件名是Tang_testing_data.json
,用于存放测试模型性能的相关数据,同样是 JSON 格式,在模型训练完成后,代码会读取这个文件中的测试数据来对模型进行测试,并将测试结果保存到指定的输出文件中。
- 原始训练数据集文件:位于
- 输出相关目录及文件
- 输出目录(
output_dir
):路径为os.path.join(work_dir, "output")
,位于主工作目录下,用于存放模型训练、测试过程中产生的各种输出结果,例如训练过程中的日志信息(如果配置了相应的日志输出功能指向该目录)、模型训练完成后的最终测试结果文件等,它是一个汇总存放各类输出内容的目录。 - 检查点目录(
ckpt_dir
):位于os.path.join(work_dir, "checkpoint")
,是主工作目录下的子目录,在模型训练过程中,会按照设定的步数(由save_steps
参数决定)将训练过程中的模型检查点保存到这个目录下,方便后续可以从中恢复训练或者选择性能较好的模型版本进行进一步评估、使用等,同时通过save_total_limit
参数控制这个目录下最多保留几个模型检查点,防止过多的检查点文件占用大量磁盘空间。 - 测试结果文件(
output_path
):具体路径为os.path.join(output_dir, "results.txt")
,存放在输出目录下,是一个文本文件,在模型测试阶段,代码会将模型针对每条测试数据生成的回复内容与对应的测试数据输入拼接后,逐行写入到这个文件中,用于记录和查看模型在测试集上的具体表现情况,方便后续对模型性能进行分析评估。
- 输出目录(
代码部分:
import os
import sys
import argparse
import json
import warnings
import logging
# 忽略警告信息
warnings.filterwarnings("ignore")
import torch
import torch.nn as nn
import bitsandbytes as bnb
from datasets import load_dataset, load_from_disk
import transformers
from peft import PeftModel
from colorama import Fore, Back, Style
# 以下是根据Hugging Face Transformers库的相关功能进行的设置
from transformers import AutoTokenizer, AutoConfig, AutoModelForCausalLM, BitsAndBytesConfig
from transformers import GenerationConfig
from peft import (
prepare_model_for_int8_training,
LoraConfig,
get_peft_model,
get_peft_model_state_dict,
prepare_model_for_kbit_training
)
# 模型名称
model_name = "TAIDE-LX-7B-Chat"
# 模型所在目录
model_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "TAIDE-LX-7B-Chat")
# 设置工作目录
work_dir = os.path.dirname(os.path.abspath(__file__))
# 输出目录
output_dir = os.path.join(work_dir, "output")
# 检查点目录
ckpt_dir = os.path.join(work_dir, "checkpoint")
# 训练的总Epoch数
num_epoch = 1
# 学习率
LEARNING_RATE = 3e-4
# 配置模型和训练参数
cache_dir = os.path.join(work_dir, "cache")
from_ckpt = False
ckpt_name = None
# 以下是补充的超参数设置
# 用于训练的数据集数量
num_train_data = 1040 # 可设置的最大值为5000,数据量越多,模型性能可能越好,但训练时间也会增加
# 以下参数影响模型的训练和推理
CUTOFF_LEN = 256 # 文本截断的最大长度
LORA_R = 8 # LORA的R值
LORA_ALPHA = 16 # LORA的Alpha值
LORA_DROPOUT = 0.05 # LORA的Dropout率
VAL_SET_SIZE = 0 # 验证集的大小,0表示不使用验证集
TARGET_MODULES = ["q_proj", "up_proj", "o_proj", "k_proj", "down_proj", "gate_proj", "v_proj"] # 目标模块,用于LORA训练
#
MICRO_BATCH_SIZE = 4 # 微批次大小,这里设置为和原示例类似的值,你可根据实际情况调整
GRADIENT_ACCUMULATION_STEPS = 4 # 计算每个微批次累积的梯度步数,示例中为16//4,这里假设为4,可按需改
logging_steps = 20 # 定義訓練過程中每隔多少步驟輸出一次訓練誌
save_steps = 65 # 定義訓練過程中每隔多少步驟保存一次模型
save_total_limit = 3 # 控制最多保留幾個模型checkpoint
report_to = ["tensorboard"] # 設定上報實驗指標的目標,預設為無 # 可以根据需求调整报告的对象,比如添加其他日志记录工具等
# 处理分布式训练相关配置
world_size = int(os.environ.get("WORLD_SIZE", 1))
ddp = world_size!= 1
if ddp:
device_map = {"": int(os.environ.get("LOCAL_RANK") or 0)}
# 创建输出目录和检查点目录(如果不存在)
os.makedirs(output_dir, exist_ok=True)
os.makedirs(ckpt_dir, exist_ok=True)
# 加载数据集
dataset_dir = os.path.join(work_dir, "data", "training_data", "Tang_training_data.json")
with open(dataset_dir, "r", encoding="utf-8") as f:
data_json = json.load(f)
# 保存处理后的数据集
tmp_dataset_path = os.path.join(work_dir, "tmp_dataset.json")
# 获取文件所在目录路径
dir_path = os.path.dirname(tmp_dataset_path)
# 如果目录不存在,则创建目录
if not os.path.exists(dir_path):
os.makedirs(dir_path)
# 明确使用 'w' 模式打开文件用于写入,同时指定 encoding 为 'utf-8'
with open(tmp_dataset_path, 'w', encoding='utf-8') as f:
json.dump(data_json[:num_train_data], f, indent=2, ensure_ascii=False)
data = load_dataset('json', data_files=tmp_dataset_path, download_mode="force_redownload")
# 创建模型和令牌器
model = AutoModelForCausalLM.from_pretrained(
model_path,
cache_dir=cache_dir,
quantization_config=BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16
),
low_cpu_mem_usage=True
)
tokenizer = AutoTokenizer.from_pretrained(
model_name,
add_eos_token=True,
cache_dir=cache_dir,
quantization_config=BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16
)
)
tokenizer.pad_token = tokenizer.eos_token
def generate_training_data(data_point):
"""
此函数用于将数据点(包含指令、输入和输出文本)转换为模型可读取的令牌形式
参数:
data_point (dict): 包含 "instruction"、"input" 和 "output" 字段的字典,所有字段均为字符串
返回:
dict: 包含模型的输入令牌、注意力掩码和相应输出目标的字典
"""
# 构建完整的输入提示
prompt = f"""\
[INST] <<SYS>>
You are a helpful assistant and good at writing Tang poem. 你是一个乐于助人的助手且擅长写唐诗。
<</SYS>>
{data_point["instruction"]}
{data_point["input"]}
[/INST]"""
# 计算输入令牌的数量
len_user_prompt_tokens = (
len(
tokenizer(
prompt,
truncation=True,
max_length=CUTOFF_LEN + 1,
padding="max_length",
)["input_ids"]
) - 1
)
# 将输入提示转换为令牌
full_tokens = tokenizer(
prompt + " " + data_point["output"] + "</s>",
truncation=True,
max_length=CUTOFF_LEN + 1,
padding="max_length",
)["input_ids"][:-1]
return {
"input_ids": full_tokens,
"labels": [-100] * len_user_prompt_tokens + full_tokens[len_user_prompt_tokens:],
"attention_mask": [1] * (len(full_tokens)),
}
def evaluate(instruction, generation_config, max_len, input="", verbose=True):
"""
此函数用于根据输入的指令、生成配置和最大长度,获取模型的输出
参数:
instruction (str): 描述模型要执行的操作的字符串
generation_config (transformers.GenerationConfig): 用于指定与模型推理相关的解码参数的对象
max_len (int): 模型输出的最大长度
input (str, 可选): 模型需要解决指令的输入字符串,默认值为 ""
verbose (bool, 可选): 是否打印模型的输出,默认值为True
返回:
str: 模型根据指令和输入生成的响应
"""
# 构建完整的输入提示
prompt = f"""\
[INST] <<SYS>>
You are a helpful assistant and good at writing Tang poem. 你是一个乐于助人的助手且擅长写唐诗。
<</SYS>>
{instruction}
{input}
[/INST]"""
# 将提示文本转换为模型所需的数字表示形式
inputs = tokenizer(prompt, return_tensors="pt")
input_ids = inputs["input_ids"].cuda() if torch.cuda.is_available() else inputs["input_ids"]
# 使用模型进行生成回复
generation_output = model.generate(
input_ids=input_ids,
generation_config=generation_config,
return_dict_in_generate=True,
output_scores=True,
max_new_tokens=max_len,
)
# 将生成的回复解码并打印
for s in generation_output.sequences:
output = tokenizer.decode(s)
output = output.split("[/INST]")[1].replace("</s>", "").replace("<s>", "").replace("Assistant:", "").replace("Assistant", "").strip()
if verbose:
print(output)
return output
# 划分训练集和验证集(如果需要)
if VAL_SET_SIZE > 0:
train_val = data["train"].train_test_split(
test_size=VAL_SET_SIZE, shuffle=True, seed=42
)
train_data = train_val["train"].shuffle().map(generate_training_data)
val_data = train_val["test"].shuffle().map(generate_training_data)
else:
train_data = data['train'].shuffle().map(generate_training_data)
val_data = None
# 将模型准备好以使用INT8训练
model = prepare_model_for_int8_training(model)
# 使用LoraConfig配置LORA模型
config = LoraConfig(
r=LORA_R,
lora_alpha=LORA_ALPHA,
target_modules=TARGET_MODULES,
lora_dropout=LORA_DROPOUT,
bias="none",
task_type="CAUSAL_LM",
)
model = get_peft_model(model, config)
# 定义nf4_config
nf4_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_use_double_quant=True,
bnb_4bit_compute_dtype=torch.bfloat16
)
generation_config = GenerationConfig(
do_sample=True,
temperature=0.1,
num_beams=1,
top_p=0.3,
no_repeat_ngram_size=3,
pad_token_id=2
)
# 训练模型
trainer = transformers.Trainer(
model=model,
train_dataset=train_data,
eval_dataset=val_data,
args=transformers.TrainingArguments(
per_device_train_batch_size=4, # 微批次大小,可根据需要调整
gradient_accumulation_steps=16 // 4, # 计算每个微批次累积的梯度步数
warmup_steps=50,
num_train_epochs=num_epoch,
learning_rate=LEARNING_RATE,
fp16=True, # 使用混合精度训练
logging_steps=20,
save_strategy="steps",
save_steps=65,
output_dir=ckpt_dir,
save_total_limit=3,
ddp_find_unused_parameters=False if ddp else None,
),
data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),
)
# 禁用模型的cache功能
model.config.use_cache = False
# 训练过程
try:
trainer.train()
except Exception as e:
print(f"Training failed: {e}")
# 保存训练后的模型
try:
model.save_pretrained(ckpt_dir)
except Exception as e:
print(f"Saving model failed: {e}")
# 测试部分
test_data_path = os.path.join(work_dir, "data", "Tang_testing_data.json")
output_path = os.path.join(output_dir, "results.txt")
with open(test_data_path, "r", encoding="utf-8") as f:
test_datas = json.load(f)
results = []
with open(output_path, "r", encoding="utf-8") as f:
for i, test_data in enumerate(test_datas):
predict = evaluate(test_data["instruction"], generation_config, 128, test_data["input"], verbose=False)
f.write(f"{i + 1}. {test_data['input']}{predict}\n")
print(f"{i + 1}. {test_data['input']}{predict}")
# 下载结果文件(根据需要进行修改)
# 以下代码是在Windows本地可能无法直接使用的部分,需要根据实际情况进行调整
# from google.colab import files
# files.download(output_path)
以下是对上述
Python 代码的摘要说明:
一、整体功能概述
这段 Python 代码主要实现了基于 Hugging Face Transformers 库对预训练语言模型(具体为 TAIDE-LX-7B-Chat
模型)进行微调(Fine-tuning)的功能,使其能更好地应用于生成唐诗相关内容的任务。整个流程涵盖了数据加载与预处理、模型配置、模型训练以及训练后模型的测试与结果保存等环节。
二、代码各部分详细说明
- 导入模块部分
- 导入了多个常用的 Python 库,如
os
、sys
、argparse
等基础库,以及和深度学习、自然语言处理相关的库,像torch
、transformers
、peft
等,还导入了用于忽略警告信息、文本颜色控制等功能的相关模块,为后续代码实现做准备。
- 导入了多个常用的 Python 库,如
- 基础配置与参数设置部分
- 模型相关路径:定义了模型名称、模型所在目录、工作目录、输出目录以及检查点目录等路径相关的变量,确保后续文件操作(如加载模型、保存训练结果等)能找到正确的位置。
- 训练参数设置:设定了训练的总轮数(
num_epoch
)、学习率(LEARNING_RATE
),还包括一系列影响模型训练和推理的超参数,例如用于训练的数据集数量(num_train_data
)、文本截断长度(CUTOFF_LEN
)、LORA 相关参数(LORA_R
、LORA_ALPHA
、LORA_DROPOUT
)、验证集大小(VAL_SET_SIZE
)、微批次大小(MICRO_BATCH_SIZE
)、梯度累积步数(GRADIENT_ACCUMULATION_STEPS
)等,这些参数将用于控制模型训练过程和微调效果。 - 分布式训练配置:根据环境变量
WORLD_SIZE
判断是否进行分布式训练,若需要则配置相应的设备映射(device_map
)。
- 数据加载与预处理部分
- 创建目录:首先确保输出目录和检查点目录存在,若不存在则创建它们,用于后续保存训练结果和模型检查点。
- 加载数据集:从指定的
json
文件路径(dataset_dir
)读取原始数据集,先将其加载为 Python 的字典数据结构(通过json.load
),然后从中截取指定数量(由num_train_data
决定)的数据保存为临时数据集文件(tmp_dataset_path
),再通过load_dataset
函数以json
格式重新加载这个临时数据集用于后续处理。 - 数据处理函数定义:定义了
generate_training_data
函数,用于将包含指令、输入和输出文本的数据点转换为适合模型训练的格式,具体是通过tokenizer
将文本转换为令牌(token)形式,并处理好输入令牌、对应标签以及注意力掩码等信息,构建训练样本。 - 划分数据集(可选):根据
VAL_SET_SIZE
参数的值决定是否划分训练集和验证集,如果VAL_SET_SIZE
大于 0,则从原始训练集中划分出验证集,对训练集和验证集的数据都应用generate_training_data
函数进行预处理,使其格式符合模型训练要求;若VAL_SET_SIZE
为 0,则整个数据集都作为训练集进行处理。
- 模型相关配置部分
- 创建模型和令牌器:从指定的模型路径(
model_path
)加载预训练的语言模型,并根据相关配置(如量化配置BitsAndBytesConfig
用于以特定量化方式加载模型以节省内存等)进行初始化;同时加载对应的分词器(tokenizer
),并设置其填充令牌(pad_token
)与结束令牌(eos_token
)相同,方便后续文本处理。 - 模型准备与微调配置:将加载的模型通过
prepare_model_for_int8_training
函数进行处理,使其适合INT8
训练方式,接着使用LoraConfig
配置LORA
(低秩适配,一种参数高效微调方法)相关参数,并通过get_peft_model
函数应用LORA
配置到模型上,以便后续进行参数高效的微调训练。 - 生成配置定义:定义了
GenerationConfig
对象,用于指定模型在生成文本时的一些解码参数,例如是否采样(do_sample
)、温度参数(temperature
)、束搜索的束数量(num_beams
)等,这些参数会影响模型生成唐诗内容时的质量和多样性等特性。
- 创建模型和令牌器:从指定的模型路径(
- 模型训练部分
- 使用
transformers.Trainer
类来实例化训练器对象(trainer
),传入模型、训练数据集、验证数据集(可为None
)以及训练相关的各种参数(如批次大小、学习率、训练轮数、梯度累积步数、日志记录和模型保存相关的配置等),同时指定了数据整理器(data_collator
)用于整理训练数据的格式。在训练前还禁用了模型的缓存功能(model.config.use_cache = False
),然后通过try-except
语句块尝试执行模型训练过程,若训练出现异常则打印出错误信息。
- 使用
- 模型保存部分
同样使用try-except
语句块尝试将训练后的模型保存到指定的检查点目录(ckpt_dir
)中,若保存过程出现异常则打印相应的错误提示。 - 模型测试与结果保存部分
- 从指定的测试数据文件(
test_data_path
)中加载测试数据集(通过json.load
),然后循环遍历每条测试数据,调用evaluate
函数(该函数基于给定的指令、生成配置和输入等信息,利用已训练好的模型生成相应回复内容)获取模型针对测试数据的回复,将测试数据的输入以及模型生成的回复拼接后写入到指定的结果文件(output_path
)中保存起来,同时也会打印出来方便查看,用于评估模型在测试集上的表现。
- 从指定的测试数据文件(
执行的结果
PyDev console: starting.
Python 3.9.17 (main, Jul 5 2023, 20:47:11) [MSC v.1916 64 bit (AMD64)] on win32
runfile('E:/hw2024/hw5/LLM_finetune.py', wdir='E:/hw2024/hw5')
Downloading and preparing dataset json/default to C:/Users/Administrator/.cache/huggingface/datasets/json/default-8a769fd843b52bbb/0.0.0/0f7e3662623656454fcd2b650f34e886a7db4b9104504885bd462096cc7a9f51...
Downloading data files: 100%|██████████| 1/1 [00:00<?, ?it/s]
Extracting data files: 100%|██████████| 1/1 [00:00<00:00, 998.41it/s]
Dataset json downloaded and prepared to C:/Users/Administrator/.cache/huggingface/datasets/json/default-8a769fd843b52bbb/0.0.0/0f7e3662623656454fcd2b650f34e886a7db4b9104504885bd462096cc7a9f51. Subsequent calls will reuse this data.
100%|██████████| 1/1 [00:00<00:00, 500.93it/s]
Loading checkpoint shards: 100%|██████████| 3/3 [00:17<00:00, 5.73s/it]
You set `add_prefix_space`. The tokenizer needs to be converted from the slow tokenizers
{'loss': 3.7877, 'grad_norm': 2.084606170654297, 'learning_rate': 0.00011999999999999999, 'epoch': 0.31}
{'loss': 1.5036, 'grad_norm': 0.7624332904815674, 'learning_rate': 0.00023999999999999998, 'epoch': 0.62}
{'loss': 1.2561, 'grad_norm': 0.6947095394134521, 'learning_rate': 9.999999999999999e-05, 'epoch': 0.92}
100%|██████████| 65/65 [08:59<00:00, 8.33s/it]Checkpoint destination directory E:\hw2024\hw5\checkpoint\checkpoint-65 already exists and is non-empty. Saving will proceed but saved results may be invalid.
{'train_runtime': 539.841, 'train_samples_per_second': 1.926, 'train_steps_per_second': 0.12, 'train_loss': 2.1084876133845403, 'epoch': 1.0}
100%|██████████| 65/65 [08:59<00:00, 8.31s/it]
训练后的robot诗人
的根据 input 的诗句输出的output如下,共计100 首诗词 对的还是不错
请赏析
0000 上联: '秦川雄帝宅,函谷壯皇居。
下联: '綺殿千尋起,離宮百雉餘。連甍遙接漢,飛觀迥凌虛。雲日隱層闕,風煙出綺疎。
0001 上联: '巖廊罷機務,崇文聊駐輦。
下联: '玉匣啓龍圖,金繩披鳳篆。韋編斷仍續,縹帙舒還卷。對此乃淹留,欹案觀墳典。
0002 上联: '移步出詞林,停輿欣武宴。
下联: '琱弓寫明月,駿馬疑流電。驚雁落虛弦,啼猿悲急箭。閱賞誠多美,於茲乃忘倦。
0003 上联: '鳴笳臨樂館,眺聽歡芳節。
下联: '急管韻朱絃,清歌凝白雪。彩鳳肅來儀,玄鶴紛成列。去茲鄭衛聲,雅音方可悅。
0004 上联: '芳辰追逸趣,禁苑信多奇。
下联: '橋形通漢上,峰勢接雲危。煙霞交隱映,花鳥自參差。何如肆轍跡?萬里賞瑤池。
0005 上联: '白日依山盡,黃河入海流。
下联: '欲窮千里目,更上一層樓。
0006 上联: '落日雙闕昏,回輿九重暮。
下联: '長煙散初碧,皎月澄輕素。搴幌翫琴書,開軒引雲霧。斜漢耿層閣,清風搖玉樹。
0007 上联: '歡樂難再逢,芳辰良可惜。
下联: '玉酒泛雲罍,蘭殽陳綺席。千鍾合堯禹,百獸諧金石。得志重寸陰,忘懷輕尺璧。
0008 上联: '建章歡賞夕,二八盡妖妍。
下联: '羅綺昭陽殿,芬芳玳瑁筵。珮移星正動,扇掩月初圓。無勞上懸圃,即此對神仙。
0009 上联: '新豐停翠輦,譙邑駐鳴笳。
下联: '園荒一徑斷,苔古半階斜。前池消舊水,昔樹發今花。一朝辭此地,四海遂爲家。
0010 上联: '春蒐馳駿骨,總轡俯長河。
下联: '霞處流縈錦,風前瀁卷羅。水花翻照樹,堤蘭倒插波。豈必汾陰曲,秋雲發棹歌。
0011 上联: '重巒俯渭水,碧嶂插遙天。
下联: '出紅扶嶺日,入翠貯巖煙。疊松朝若夜,複岫闕疑全。對此恬千慮,無勞訪九仙。
0012 上联: '寒隨窮律變,春逐鳥聲開。
下联: '初風飄帶柳,晚雪間花梅。碧林青舊竹,綠沼翠新苔。芝田初雁去,綺樹巧鸎來。
0013 上联: '晚霞聊自怡,初晴彌可喜。
下联: '日晃百花色,風動千林翠。池魚躍不同,園鳥聲還異。寄言博通者,知予物外志。
0014 上联: '夏律昨留灰,秋箭今移晷。
下联: '峨嵋岫初出,洞庭波漸起。桂白發幽巖,菊黃開灞涘。運流方可歎,含毫屬微理。
0015 上联: '寒驚薊門葉,秋發小山枝。
下联: '松陰背日轉,竹影避風移。提壺菊花岸,高興芙蓉池。欲知涼氣早,巢空燕不窺。
0016 上联: '山亭秋色滿,巖牖涼風度。
下联: '疎蘭尚染煙,殘菊猶承露。古石衣新苔,新巢封古樹。歷覽情無極,咫尺輸光暮。
0017 上联: '朝光浮燒野,霜華淨碧空。
下联: '結浪冰初鏡,在逕菊方叢。約嶺煙深翠,分旗霞散紅。抽思滋泉側,飛想傅巖中。
0018 上联: '蕭條起關塞,搖颺下蓬瀛。
下联: '拂林花亂彩,響谷鳥分聲。披雲羅影散,泛水織文生。勞歌大風曲,威加四海清。
0019 上联: '罩雲飄遠岫,噴雨泛長河。
下联: '低飛昏嶺腹,斜足灑巖阿。泫叢珠締葉,起溜鏡圖波。濛柳添絲密,含吹織空羅。
0020 上联: '潔野凝晨曜,裝墀帶夕暉。
下联: '集條分樹玉,拂浪影泉璣。色灑妝臺粉,花飄綺席衣。入扇縈離匣,點素皎殘機。
0021 上联: '紅輪不暫駐,烏飛豈復停。
下联: '岑霞漸漸落,溪陰寸寸生。藿葉隨光轉,葵心逐照傾。晚煙含樹色,棲鳥雜流聲。
0022 上联: '高軒臨碧渚,飛檐迥架空。
下联: '餘花攢鏤檻,殘柳散雕櫳。岸菊初含橤,園梨始帶紅。莫慮崑山暗,還共盡杯中。
0023 上联: '華林滿芳景,洛陽徧陽春。
下联: '朱顏含遠日,翠色影長津。喬柯囀嬌鳥,低枝映美人。昔作園中實,今來席上珍。
0024 上联: '玉衡流桂圃,成蹊正可尋。
下联: '鸎啼密葉外,蝶戲脆花心。麗景光朝彩,輕霞散夕陰。暫顧暉章側,還眺靈山林。
0025 上联: '岸曲非千里,橋斜異七星。
下联: '暫低逢輦度,還高值浪驚。水搖文鷁動,纜轉錦花縈。遠近隨輪影,輕重應人行。
0026 上联: '拂霞疑電落,騰虛狀寫虹。
下联: '屈伸煙霧裏,低舉白雲中。紛披乍依迥,掣曳或隨風。念茲輕薄質,無翅強搖空。
0027 上联: '鑿門初奉律,仗戰始臨戎。
下联: '振鱗方躍浪,騁翼正凌風。未展六奇術,先虧一簣功。防身豈乏智,殉命有餘忠。
0028 上联: '晦魄移中律,凝暄起麗城。
下联: '罩雲朝蓋上,穿露曉珠呈。笑樹花分色,啼枝鳥合聲。披襟歡眺望,極目暢春情。
0029 上联: '秋光凝翠嶺,涼吹肅離宮。
下联: '荷疎一蓋缺,樹冷半帷空。側陣移鴻影,圓花釘菊叢。攄懷俗塵外,高眺白雲中。
0030 上联: '斜廊連綺閣,初月照宵幃。
下联: '塞冷鴻飛疾,園秋蟬噪遲。露結林疎葉,寒輕菊吐滋。愁心逢此節,長歎獨含悲。
0031 上联: '菊散金風起,荷疎玉露圓。
下联: '將秋數行雁,離夏幾林蟬。雲凝愁半嶺,霞碎纈高天。還似成都望,直見峨眉前。
0032 上联: '爽氣澄蘭沼,秋風動桂林。
下联: '露凝千片玉,菊散一叢金。日岫高低影,雲空點綴陰。蓬瀛不可望,泉石且娛心。
0033 上联: '石鯨分玉溜,劫燼隱平沙。
下联: '柳影冰無葉,梅心凍有花。寒野凝朝霧,霜天散夕霞。歡情猶未極,落景遽西斜。
0034 上联: '凍雲宵徧嶺,素雪曉凝華。
下联: '入牖千重碎,迎風一半斜。不妝空散粉,無樹獨飄花。縈空慙夕照,破彩謝晨霞。
0035 上联: '暮景斜芳殿,年華麗綺宮。
下联: '寒辭去冬雪,暖帶入春風。階馥舒梅素,盤花卷燭紅。共歡新故歲,迎送一宵中。
0036 上联: '歲陰窮暮紀,獻節啓新芳。
下联: '冬盡今宵促,年開明日長。冰消出鏡水,梅散入風香。對此歡終宴,傾壺待曙光。
0037 上联: '和氣吹綠野,梅雨灑芳田。
下联: '新流添舊澗,宿霧足朝煙。雁溼行無次,花霑色更鮮。對此欣登歲,披襟弄五弦。
0038 上联: '翠樓含曉霧,蓮峰帶晚雲。
下联: '玉葉依巖聚,金枝觸石分。橫天結陣影,逐吹起羅文。非復陽臺下,空將惑楚君。
0039 上联: '綺筵移暮景,紫閣引宵煙。
下联: '隔棟歌塵合,分階舞影連。聲流三處管,響亂一重絃。不似秦樓上,吹簫空學仙。
0040 上联: '殘雲收翠嶺,夕霧結長空。
下联: '帶岫凝全碧,障霞隱半紅。髣髴分初月,飄颻度曉風。還因三里處,冠蓋遠相通。
0041 上联: '蘭氣已熏宮,新橤半粧叢。
下联: '色含輕重霧,香引去來風。拂樹濃舒碧,縈花薄蔽紅。還當雜行雨,髣髴隱遙空。
0042 上联: '年柳變池臺,隋堤曲直回。
下联: '逐浪絲陰去,迎風帶影來。疎黃一鳥弄,半翠幾眉開。縈雪臨春岸,參差間早梅。
0043 上联: '春暉開紫苑,淑景媚蘭場。
下联: '映庭含淺色,凝露泫浮光。日麗參差影,風傳輕重香。會須君子折,佩裏作芬芳。
0044 上联: '禁苑春暉麗,花蹊綺樹妝。
下联: '綴條深淺色,點露參差光。向日分千笑,迎風共一香。如何仙嶺側,獨秀隱遙芳。
0045 上联: '參差垂玉闕,舒卷映蘭宮。
下联: '珠光搖素月,竹影亂清風。彩散銀鉤上,文斜桂戶中。惟當雜羅綺,相與媚房櫳。
0046 上联: '凌晨麗城去,薄暮上林棲。
下联: '辭枝枝暫起,停樹樹還低。向日終難託,迎風詎肯迷。只待纖纖手,曲裏作宵啼。
0047 上联: '駿骨飲長涇,奔流灑絡纓。
下联: '細紋連噴聚,亂荇繞蹄縈。水光鞍上側,馬影溜中橫。翻似天池裏,騰波龍種生。
0048 上联: '階蘭凝曙霜,岸菊照晨光。
下联: '露濃晞晚笑,風勁淺殘香。細葉凋輕翠,圓花飛碎黃。還持今歲色,復結後年芳。
0049 上联: '曖曖去塵昏灞岸,飛飛輕蓋指河梁。
下联: '雲峰衣結千重葉,雪岫花開幾樹妝。深悲黃鶴孤舟遠,獨歎青山別路長。聊將分袂霑巾淚,還用持添離席觴。
0050 上联: '四時運灰琯,一夕變冬春。
下联: '送寒餘雪盡,迎歲早梅新。
0051 上联: '燄聽風來動,花開不待春。
下联: '鎮下千行淚,非是爲思人。
0052 上联: '九龍蟠燄動,四照逐花生。
下联: '即此流高殿,堪持待月明。
0053 上联: '上弦明月半,激箭流星遠。
下联: '落雁帶書驚,啼猿映枝轉。
0054 上联: '初秋玉露清,早雁出空鳴。
下联: '隔雲時亂影,因風乍含聲。
0055 上联: '岸曲絲陰聚,波移帶影疎。
下联: '還將眉裏翠,來就鏡中舒。
0056 上联: '貞條障曲砌,翠葉貫寒霜。
下联: '拂牖分龍影,臨池待鳳翔。
0057 上联: '散影玉階柳,含翠隱鳴蟬。
下联: '微形藏葉裏,亂響出風前。
0058 上联: '盤根直盈渚,交幹橫倚天。
下联: '舒華光四海,卷葉蔭三川。
0059 上联: '近谷交縈橤,遙峰對出蓮。
下联: '徑細無全磴,松小未含煙。
0060 上联: '疾風知勁草,板蕩識誠臣。
下联: '勇夫安識義,智者必懷仁。
0061 上联: '太液仙舟迥,西園隱上才。
下联: '未曉征車度,雞鳴關早開。
0062 上联: '煙生遙岸隱,月落半崖陰。
下联: '連山驚鳥亂,隔岫斷猿吟。
0063 上联: '醽醁勝蘭生,翠濤過玉䪥。
下联: '千日醉不醒,十年味不敗。
0064 上联: '羽蓋飛天漢,鳳駕越層巒。
下联: '俱歎三秋阻,共敍一宵歡。璜虧夜月落,靨碎曉星殘。誰能重操杼,纖手濯清瀾。
0065 上联: '霓裳轉雲路,鳳駕儼天潢。
下联: '虧星凋夜靨,殘月落朝璜。促歡今夕促,長離別後長。輕梭聊駐織,掩淚獨悲傷。
0066 上联: '日宮開萬仞,月殿聳千尋。
下联: '花蓋飛團影,幡虹曳曲陰。綺霞遙籠帳,叢珠細網林。寥廓煙雲表,超然物外心。
0067 上联: '四郊秦漢國,八水帝王都。
下联: '閶闔雄里閈,城闕壯規模。貫渭稱天邑,含岐實奧區。金門披玉館,因此識皇圖。
0068 上联: '眷言君失德,驪邑想秦餘。
下联: '政煩方改篆,愚俗乃焚書。阿房久已滅,閣道遂成墟。欲厭東南氣,翻傷掩鮑車。
0069 上联: '神皐福地三秦邑,玉臺金闕九仙家。
下联: '寒光猶戀甘泉樹,淑景偏臨建始花。綵蝶黃鸎未歌舞,梅香柳色已矜誇。迎春正啓流霞席,暫囑曦輪勿遽斜。
0070 上联: '三陽本是標靈紀,二室由來獨擅名。
下联: '霞衣霞錦千般狀,雲峰雲岫百重生。水炫珠光遇泉客,巖懸石鏡厭山精。永願乾坤符睿算,長居膝下屬歡情。
0071 上联: '奇峰嶾嶙箕山北,秀崿岹嶢嵩鎮南。
下联: '地首地肺何曾擬,天目天台倍覺慙。樹影蒙蘢鄣疊岫,波深洶湧落懸潭。□願紫宸居得一,永欣丹扆御通三。
0072 上联: '漢家重東郡,宛彼白馬津。
下联: '黎庶既蕃殖,臨之勞近臣。遠別初首路,今行方及春。課成應第一,良牧爾當仁。
0073 上联: '北風吹同雲,同雲飛白雪。
下联: '白雪乍迴散,同雲何慘烈。未見溫泉冰,寧知火井滅。表瑞良在茲,庶幾可怡悅。
0074 上联: '魯衛情先重,親賢愛轉多。
下联: '冕旒豐暇日,乘景暫經過。戚里申高宴,平臺奏雅歌。復尋爲善樂,方驗保山河。
0075 上联: '地有招賢處,人傳樂善名。
下联: '鶩池臨九達,龍岫對層城。桂月先秋冷,蘋風向晚清。鳳樓遙可見,彷彿玉簫聲。
0076 上联: '黃河遠上白雲間,一片孤城萬仞山。
下联: '羌笛何須怨楊柳,春光不度玉門關。
0077 上联: '桂殿與山連,蘭湯湧自然。
下联: '陰崖含秀色,溫谷吐潺湲。績爲蠲邪著,功因養正宣。願言將億兆,同此共昌延。
0078 上联: '邊服胡塵起,長安漢將飛。
下联: '龍蛇開陣法,貔虎振軍威。詐虜腦塗地,征夫血染衣。今朝書奏入,明日凱歌歸。
0079 上联: '仙居懷聖德,靈廟肅神心。
下联: '草合人蹤斷,塵濃鳥跡深。流沙丹竈沒,關路紫煙沈。獨傷千載後,空餘松柏林。
0080 上联: '境出三秦外,途分二陝中。
下联: '山川入虞虢,風俗限西東。樹古棠陰在,耕餘讓畔空。鳴笳從此去,行見洛陽宮。
0081 上联: '拂曙闢行宮,寒皋野望通。
下联: '繁雲低遠岫,飛雪舞長空。賦象恆依物,縈迴屢逐風。爲知勤恤意,先此示年豐。
0082 上联: '遺榮期入道,辭老竟抽簪。
下联: '豈不惜賢達,其如高尚心。寰中得祕要,方外散幽襟。獨有青門餞,羣僚悵別深。
0083 上联: '行邁離秦國,巡方赴洛師。
下联: '路逢三五夜,春色暗中期。關外長河轉,宮中淑氣遲。歌鐘對明月,不減舊遊時。
0084 上联: '壯徒恆賈勇,拔拒抵長河。
下联: '欲練英雄志,須明勝負多。譟齊山岌嶪,氣作水騰波。預期年歲稔,先此樂時和。
0085 上联: '節變寒初盡,時和氣已春。
下联: '繁雲先合寸,膏雨自依旬。颯颯飛平野,霏霏靜暗塵。懸知花葉意,朝夕望中新。
0086 上联: '鑄得千秋鏡,光生百鍊金。
下联: '分將賜羣后,遇象見清心。臺上冰華澈,窗中月影臨。更銜長綬帶,留意感人深。
0087 上联: '太乙三門訣,元君六甲符。
下联: '下傳金版術,上刻玉清書。有美探真士,囊中得祕書。自知三醮後,翊我滅殘胡。
0088 上联: '劒閣橫雲峻,鑾輿出狩回。
下联: '翠屏千仞合,丹嶂五丁開。灌木縈旗轉,仙雲拂馬來。乘時方在德,嗟爾勒銘才。
0089 上联: '寶照含天地,神劒合陰陽。
下联: '日月麗光景,星斗裁文章。寫鑑表容質,佩服爲身防。從茲一賞玩,永德保齡長。
0090 上联: '道家奠靈簡,自昔仰神仙。
下联: '真子今將命,蒼生福可傳。江山尋故國,城郭信依然。二室遙相望,雲回洞裏天。
0091 上联: '洞府修真客,衡陽念舊居。
下联: '將成金闕要,願奉玉清書。雲路三天近,松溪萬籟虛。猶期傳祕訣,來往候仙輿。
0092 上联: '城闕天中近,蓬瀛海上遙。
下联: '歸期千載鶴,春至一來朝。采藥逢三秀,餐霞臥九霄。參同如有旨,金鼎待君燒。
0093 上联: '三陽麗景早芳辰,四序佳園物候新。
下联: '梅花百樹障去路,垂柳千條暗回津。鳥飛直爲驚風葉,魚沒都由怯岸人。惟願聖主南山壽,何愁不賞萬年春。
0094 上联: '河曲回千里,關門限二京。
下联: '所嗟非恃德,設險到天平。
0095 上联: '瑞露垂花綬,寒冰澈寶輸。
下联: '對茲臺上月,聊以慶佳辰。
0096 上联: '啄木觜距長,鳳皇羽毛短。
下联: '苦嫌松桂寒,任逐桑榆煖。
0097 上联: '仙客厭人間,孤雲比性閒。
下联: '話離情未已,煙水萬重山。
0098 上联: '澄潭皎鏡石崔巍,萬壑千巖暗綠苔。
下联: '林亭自有幽貞趣,況復秋深爽氣來。
0099 上联: '憶昔嬌妃在紫宸,鉛華不御得天真。
下联: '霜綃雖似當時態,爭奈嬌波不顧人。