公司建一个网站吗,在国内做推广产品用什么网站好,自己做网站好还是让别人做,wordpress 会员查看《SwanLab机器学习实战教程》是一个主打「开箱即用」的AI训练系列教程#xff0c;我们致力于提供完善的数据集、源代码、实验记录以及环境安装方式#xff0c;手把手帮助你跑起训练#xff0c;解决问题。 Qwen2-VL是通义千问团队最近开源的大语言模型#xff0c;由阿里云通… 《SwanLab机器学习实战教程》是一个主打「开箱即用」的AI训练系列教程我们致力于提供完善的数据集、源代码、实验记录以及环境安装方式手把手帮助你跑起训练解决问题。 Qwen2-VL是通义千问团队最近开源的大语言模型由阿里云通义实验室研发。
以Qwen2-VL作为基座多模态大模型通过指令微调的方式实现特定场景下的OCR是学习多模态LLM微调的入门任务。 本文我们将简要介绍基于 transformers、peft 等框架使用 Qwen2-VL-2B-Instruct 模型在LaTeX_OCR 上进行Lora微调训练同时使用 SwanLab 监控训练过程与评估模型效果。
训练过程ZeyiLin/Qwen2-VL-ft-latexocr代码Zeyi-Lin/Qwen2-VL-finetune-LatexOCR数据集LaTeX_OCR模型Qwen2-VL-2B-Instruct在线LaTex公式预览网站latexlive显存占用约20GB如显存不足请调低per_device_train_batch_size
目录
环境配置准备数据集模型下载与加载集成SwanLab开始微调完整代码训练结果演示推理LoRA微调后的模型补充 知识点视觉大模型微调的场景与用法
视觉大模型是指能够支持图片/视频输入的大语言模型能够极大丰富与LLM的交互方式。
对视觉大模型做微调的一个典型场景是让它特化成一个更强大、更智能的计算机视觉模型执行图像分类、目标检测、语义分割、OCR、图像描述任务等等。
并且由于视觉大模型强大的基础能力所以训练流程变得非常统一——无论是分类、检测还是分割只需要构建好数据对图像 - 文本都可以用同一套代码完成相比以往针对不同任务就要构建迥异的训练代码而言视觉大模型微调要简单粗暴得多而且效果还更好。
当然硬币的另一面是要承担更高的计算开销但在大模型逐渐轻量化的趋势下可以预想这种训练范式将逐渐成为主流。 环境配置
环境配置分为三步
确保你的电脑上至少有一张英伟达显卡并已安装好了CUDA环境。安装Python版本3.8以及能够调用CUDA加速的PyTorch。安装与Qwen2-VL微调相关的第三方库可以使用以下命令
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepip install modelscope1.18.0
pip install transformers4.46.2
pip install sentencepiece0.2.0
pip install accelerate1.1.1
pip install datasets2.18.0
pip install peft0.13.2
pip install swanlab0.3.27
pip install qwen-vl-utils0.0.8
pip install pandas2.2.2准备数据集
本节使用的是 LaTex_OCR 数据集这个数据集包含了大量的数学公式图片以及对应的LaTex语法字符串。可以看到下图中的image就是学术公式图text就是对应的LaTex语法字符串 将这些LaTex语法字符串粘贴到latexlive中可以预览对应的数学公式 了解了数据集结构之后我们需要做的是将这些数据整理成Qwen2-VL需要的json格式下面是目标的格式
[{id: identity_1,conversations: [{role: user,value: 图片路径},{role: assistant,value: LaTex公式}] },
...
]我们来解读一下这个json
id数据对的编号conversations人类与LLM的对话类型是列表role角色user代表人类assistant代表模型content聊天发送的内容其中user的value是图片路径assistant的回复是LaTex公式
接下来让我们下载数据集并进行处理
我们需要做四件事情 通过Modelscope下载LaTex_OCR数据集加载数据集将图像保存到本地将图像路径和描述文本转换为一个csv文件将csv文件转换为json文件包含1个训练集和验证集 使用下面的代码完成从数据下载到生成csv的过程
data2csv.py
# 导入所需的库
from modelscope.msdatasets import MsDataset
import os
import pandas as pdMAX_DATA_NUMBER 1000
dataset_id AI-ModelScope/LaTeX_OCR
subset_name default
split traindataset_dir LaTeX_OCR
csv_path ./latex_ocr_train.csv# 检查目录是否已存在
if not os.path.exists(dataset_dir):# 从modelscope下载COCO 2014图像描述数据集ds MsDataset.load(dataset_id, subset_namesubset_name, splitsplit)print(len(ds))# 设置处理的图片数量上限total min(MAX_DATA_NUMBER, len(ds))# 创建保存图片的目录os.makedirs(dataset_dir, exist_okTrue)# 初始化存储图片路径和描述的列表image_paths []texts []for i in range(total):# 获取每个样本的信息item ds[i]text item[text]image item[image]# 保存图片并记录路径image_path os.path.abspath(f{dataset_dir}/{i}.jpg)image.save(image_path)# 将路径和描述添加到列表中image_paths.append(image_path)texts.append(text)# 每处理50张图片打印一次进度if (i 1) % 50 0:print(fProcessing {i1}/{total} images ({(i1)/total*100:.1f}%))# 将图片路径和描述保存为CSV文件df pd.DataFrame({image_path: image_paths,text: texts,})# 将数据保存为CSV文件df.to_csv(csv_path, indexFalse)print(f数据处理完成共处理了{total}张图片)else: print(f{dataset_dir}目录已存在,跳过数据处理步骤)3. 在同一目录下用以下代码将csv文件转换为json文件训练集验证集
csv2json.py
import pandas as pd
import jsoncsv_path ./latex_ocr_train.csv
train_json_path ./latex_ocr_train.json
val_json_path ./latex_ocr_val.json
df pd.read_csv(csv_path)
# Create conversation format
conversations []# Add image conversations
for i in range(len(df)):conversations.append({id: fidentity_{i1},conversations: [{role: user,value: f{df.iloc[i][image_path]}},{role: assistant, value: str(df.iloc[i][text])}]})# print(conversations)
# Save to JSON
# Split into train and validation sets
train_conversations conversations[:-4]
val_conversations conversations[-4:]# Save train set
with open(train_json_path, w, encodingutf-8) as f:json.dump(train_conversations, f, ensure_asciiFalse, indent2)# Save validation set
with open(val_json_path, w, encodingutf-8) as f:json.dump(val_conversations, f, ensure_asciiFalse, indent2)此时目录下会多出3个文件
latex_ocr_train.csvlatex_ocr_train.jsonlatex_ocr_val.json
至此我们完成了数据集的准备。 模型下载与加载
这里我们使用modelscope下载Qwen2-VL-2B-Instruct模型然后把它加载到Transformers中进行训练
from modelscope import snapshot_download, AutoTokenizer
from transformers import TrainingArguments, Trainer, DataCollatorForSeq2Seq, Qwen2VLForConditionalGeneration, AutoProcessor
import torch# 在modelscope上下载Qwen2-VL模型到本地目录下
model_dir snapshot_download(Qwen/Qwen2-VL-2B-Instruct, cache_dir./, revisionmaster)# 使用Transformers加载模型权重
tokenizer AutoTokenizer.from_pretrained(./Qwen/Qwen2-VL-2B-Instruct/, use_fastFalse, trust_remote_codeTrue)
# 特别的Qwen2-VL-2B-Instruct模型需要使用Qwen2VLForConditionalGeneration来加载
model Qwen2VLForConditionalGeneration.from_pretrained(./Qwen/Qwen2-VL-2B-Instruct/, device_mapauto, torch_dtypetorch.bfloat16, trust_remote_codeTrue,)
model.enable_input_require_grads() # 开启梯度检查点时要执行该方法模型大小为 4.5GB下载模型大概需要 5 分钟。
集成SwanLab SwanLab 是一个开源的模型训练记录工具常被称为中国版 WeightsBiases Tensorboard。SwanLab面向AI研究者提供了训练可视化、自动日志记录、超参数记录、实验对比、多人协同等功能。在SwanLab上研究者能基于直观的可视化图表发现训练问题对比多个实验找到研究灵感并通过在线链接的分享与基于组织的多人协同训练打破团队沟通的壁垒。
SwanLab与Transformers已经做好了集成用法是在Trainer的callbacks参数中添加SwanLabCallback实例就可以自动记录超参数和训练指标简化代码如下
from swanlab.integration.transformers import SwanLabCallback
from transformers import Trainerswanlab_callback SwanLabCallback()trainer Trainer(...callbacks[swanlab_callback],
)首次使用SwanLab需要先在官网注册一个账号然后在用户设置页面复制你的API Key然后在训练开始提示登录时粘贴即可后续无需再次登录 更多用法可参考快速开始、Transformers集成。 开始微调完整代码
查看可视化训练过程ZeyiLin/Qwen2-VL-ft-latexocr
本节代码做了以下几件事
下载并加载Qwen2-VL-2B-Instruct模型加载数据集取前996条数据参与训练4条数据进行主观评测配置Lora参数为r64, lora_alpha16, lora_dropout0.05使用SwanLab记录训练过程包括超参数、指标和最终的模型输出结果训练2个epoch
开始执行代码时的目录结构应该是
|———— train.py
|———— data2csv.py
|———— csv2json.py
|———— latex_ocr_train.csv
|———— latex_ocr_train.json
|———— latex_ocr_val.json完整代码如下
train.py
import torch
from datasets import Dataset
from modelscope import snapshot_download, AutoTokenizer
from swanlab.integration.transformers import SwanLabCallback
from qwen_vl_utils import process_vision_info
from peft import LoraConfig, TaskType, get_peft_model, PeftModel
from transformers import (TrainingArguments,Trainer,DataCollatorForSeq2Seq,Qwen2VLForConditionalGeneration,AutoProcessor,
)
import swanlab
import json
import osprompt 你是一个LaText OCR助手,目标是读取用户输入的照片转换成LaTex公式。
model_id Qwen/Qwen2-VL-2B-Instruct
local_model_path ./Qwen/Qwen2-VL-2B-Instruct
train_dataset_json_path latex_ocr_train.json
val_dataset_json_path latex_ocr_val.json
output_dir ./output/Qwen2-VL-2B-LatexOCR
MAX_LENGTH 8192def process_func(example):将数据集进行预处理input_ids, attention_mask, labels [], [], []conversation example[conversations]image_file_path conversation[0][value]output_content conversation[1][value]messages [{role: user,content: [{type: image,image: f{image_file_path},resized_height: 500,resized_width: 100,},{type: text, text: prompt},],}]text processor.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue) # 获取文本image_inputs, video_inputs process_vision_info(messages) # 获取数据数据预处理过inputs processor(text[text],imagesimage_inputs,videosvideo_inputs,paddingTrue,return_tensorspt,)inputs {key: value.tolist() for key, value in inputs.items()} #tensor - list,为了方便拼接instruction inputsresponse tokenizer(f{output_content}, add_special_tokensFalse)input_ids (instruction[input_ids][0] response[input_ids] [tokenizer.pad_token_id])attention_mask instruction[attention_mask][0] response[attention_mask] [1]labels ([-100] * len(instruction[input_ids][0]) response[input_ids] [tokenizer.pad_token_id])if len(input_ids) MAX_LENGTH: # 做一个截断input_ids input_ids[:MAX_LENGTH]attention_mask attention_mask[:MAX_LENGTH]labels labels[:MAX_LENGTH]input_ids torch.tensor(input_ids)attention_mask torch.tensor(attention_mask)labels torch.tensor(labels)inputs[pixel_values] torch.tensor(inputs[pixel_values])inputs[image_grid_thw] torch.tensor(inputs[image_grid_thw]).squeeze(0) #由1,h,w)变换为h,wreturn {input_ids: input_ids, attention_mask: attention_mask, labels: labels,pixel_values: inputs[pixel_values], image_grid_thw: inputs[image_grid_thw]}def predict(messages, model):# 准备推理text processor.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue)image_inputs, video_inputs process_vision_info(messages)inputs processor(text[text],imagesimage_inputs,videosvideo_inputs,paddingTrue,return_tensorspt,)inputs inputs.to(cuda)# 生成输出generated_ids model.generate(**inputs, max_new_tokensMAX_LENGTH)generated_ids_trimmed [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]output_text processor.batch_decode(generated_ids_trimmed, skip_special_tokensTrue, clean_up_tokenization_spacesFalse)return output_text[0]# 在modelscope上下载Qwen2-VL模型到本地目录下
model_dir snapshot_download(model_id, cache_dir./, revisionmaster)# 使用Transformers加载模型权重
tokenizer AutoTokenizer.from_pretrained(local_model_path, use_fastFalse, trust_remote_codeTrue)
processor AutoProcessor.from_pretrained(local_model_path)origin_model Qwen2VLForConditionalGeneration.from_pretrained(local_model_path, device_mapauto, torch_dtypetorch.bfloat16, trust_remote_codeTrue,)
origin_model.enable_input_require_grads() # 开启梯度检查点时要执行该方法# 处理数据集读取json文件
train_ds Dataset.from_json(train_dataset_json_path)
train_dataset train_ds.map(process_func)# 配置LoRA
config LoraConfig(task_typeTaskType.CAUSAL_LM,target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj],inference_modeFalse, # 训练模式r64, # Lora 秩lora_alpha16, # Lora alaph具体作用参见 Lora 原理lora_dropout0.05, # Dropout 比例biasnone,
)# 获取LoRA模型
train_peft_model get_peft_model(origin_model, config)# 配置训练参数
args TrainingArguments(output_diroutput_dir,per_device_train_batch_size4,gradient_accumulation_steps4,logging_steps10,logging_first_step10,num_train_epochs2,save_steps100,learning_rate1e-4,save_on_each_nodeTrue,gradient_checkpointingTrue,report_tonone,
)# 设置SwanLab回调
swanlab_callback SwanLabCallback(projectQwen2-VL-ft-latexocr,experiment_name7B-1kdata,config{model: https://modelscope.cn/models/Qwen/Qwen2-VL-7B-Instruct,dataset: https://modelscope.cn/datasets/AI-ModelScope/LaTeX_OCR/summary,# github: https://github.com/datawhalechina/self-llm,model_id: model_id,train_dataset_json_path: train_dataset_json_path,val_dataset_json_path: val_dataset_json_path,output_dir: output_dir,prompt: prompt,train_data_number: len(train_ds),token_max_length: MAX_LENGTH,lora_rank: 64,lora_alpha: 16,lora_dropout: 0.1,},
)# 配置Trainer
trainer Trainer(modeltrain_peft_model,argsargs,train_datasettrain_dataset,data_collatorDataCollatorForSeq2Seq(tokenizertokenizer, paddingTrue),callbacks[swanlab_callback],
)# 开启模型训练
trainer.train()# 测试
# 配置测试参数
val_config LoraConfig(task_typeTaskType.CAUSAL_LM,target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj],inference_modeTrue, # 训练模式r64, # Lora 秩lora_alpha16, # Lora alaph具体作用参见 Lora 原理lora_dropout0.05, # Dropout 比例biasnone,
)# 获取测试模型从output_dir中获取最新的checkpoint
load_model_path f{output_dir}/checkpoint-{max([int(d.split(-)[-1]) for d in os.listdir(output_dir) if d.startswith(checkpoint-)])}
print(fload_model_path: {load_model_path})
val_peft_model PeftModel.from_pretrained(origin_model, model_idload_model_path, configval_config)# 读取测试数据
with open(val_dataset_json_path, r) as f:test_dataset json.load(f)test_image_list []
for item in test_dataset:image_file_path item[conversations][0][value]label item[conversations][1][value]messages [{role: user, content: [{type: image, image: image_file_path,resized_height: 100,resized_width: 500, },{type: text,text: prompt,}]}]response predict(messages, val_peft_model)print(fpredict:{response})print(fgt:{label}\n)test_image_list.append(swanlab.Image(image_file_path, captionresponse))swanlab.log({Prediction: test_image_list})# 在Jupyter Notebook中运行时要停止SwanLab记录需要调用swanlab.finish()
swanlab.finish()看到下面的进度条即代表训练开始 训练结果演示
详细训练过程请看这里ZeyiLin/Qwen2-VL-ft-latexocr 从SwanLab图表中我们可以看到学习率的下降策略是线性下降loss随epoch呈现下降趋势同时grad_norm也呈现下降趋势。这种形态反映了模型的训练效果是符合预期的。
在Prediction图表中记录着模型最终的输出结果可以看到模型在回答的风格已经是标准的LaTex语法。 对这四个结果进行验证跟输入图像完成一致。 那么与没有微调的模型进行效果对比我们选择997.jpg 没有微调(10,10),(989,989)
微调后\mathrm { t r i e s } \left( \vec { \Phi } _ { A } ^ { ( 3 ) } \right) ( g h _ { 1 } \left( \Phi ^ { A } \right) 1 , g h _ { 2 } \left( \Phi ^ { A } \right) 1 , g h _ { 3 } \left( \Phi ^ { A } \right) )可以看到没有微调的模型对于这张图片的输出明显是错误的
而微调后的模型有着非常完美表现 推理LoRA微调后的模型
加载lora微调后的模型并进行推理
from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info
from peft import PeftModel, LoraConfig, TaskTypeprompt 你是一个LaText OCR助手,目标是读取用户输入的照片转换成LaTex公式。
local_model_path ./Qwen/Qwen2-VL-2B-Instruct
lora_model_path ./output/Qwen2-VL-2B-LatexOCR/checkpoint-124
test_image_path ./LaTeX_OCR/997.jpgconfig LoraConfig(task_typeTaskType.CAUSAL_LM,target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj],inference_modeTrue,r64, # Lora 秩lora_alpha16, # Lora alaph具体作用参见 Lora 原理lora_dropout0.05, # Dropout 比例biasnone,
)# default: Load the model on the available device(s)
model Qwen2VLForConditionalGeneration.from_pretrained(local_model_path, torch_dtypeauto, device_mapauto
)model PeftModel.from_pretrained(model, model_idf{lora_model_path}, configconfig)
processor AutoProcessor.from_pretrained(local_model_path)messages [{role: user,content: [{type: image,image: test_image_path,resized_height: 100,resized_width: 500,},{type: text, text: f{prompt}},],}
]# Preparation for inference
text processor.apply_chat_template(messages, tokenizeFalse, add_generation_promptTrue
)
image_inputs, video_inputs process_vision_info(messages)
inputs processor(text[text],imagesimage_inputs,videosvideo_inputs,paddingTrue,return_tensorspt,
)
inputs inputs.to(cuda)# Inference: Generation of the output
generated_ids model.generate(**inputs, max_new_tokens8192)
generated_ids_trimmed [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
]
output_text processor.batch_decode(generated_ids_trimmed, skip_special_tokensTrue, clean_up_tokenization_spacesFalse
)print(output_text[0])补充
详细硬件配置和参数说明
使用4张A100 40GB显卡总显存占用大约batch size为4gradient accumulation steps为4训练2个epoch的用时为8分钟51秒。 注意
在微调脚本中val_peft_model加载的是一共固定的checkpoint文件如果你添加了数据或超参数请根据实际情况修改checkpoint文件路径。 文章转载自: http://www.morning.tfsyk.cn.gov.cn.tfsyk.cn http://www.morning.lfcfn.cn.gov.cn.lfcfn.cn http://www.morning.ckhpg.cn.gov.cn.ckhpg.cn http://www.morning.wkjzt.cn.gov.cn.wkjzt.cn http://www.morning.lbgsh.cn.gov.cn.lbgsh.cn http://www.morning.kgnnc.cn.gov.cn.kgnnc.cn http://www.morning.pjxlg.cn.gov.cn.pjxlg.cn http://www.morning.jthjr.cn.gov.cn.jthjr.cn http://www.morning.ngjpt.cn.gov.cn.ngjpt.cn http://www.morning.lwwnq.cn.gov.cn.lwwnq.cn http://www.morning.nxbkw.cn.gov.cn.nxbkw.cn http://www.morning.zzqgc.cn.gov.cn.zzqgc.cn http://www.morning.rdmn.cn.gov.cn.rdmn.cn http://www.morning.prmbn.cn.gov.cn.prmbn.cn http://www.morning.lpsjs.com.gov.cn.lpsjs.com http://www.morning.pqwjh.cn.gov.cn.pqwjh.cn http://www.morning.wrkhf.cn.gov.cn.wrkhf.cn http://www.morning.lsyk.cn.gov.cn.lsyk.cn http://www.morning.qrmry.cn.gov.cn.qrmry.cn http://www.morning.wgzgr.cn.gov.cn.wgzgr.cn http://www.morning.qmwzr.cn.gov.cn.qmwzr.cn http://www.morning.jbysr.cn.gov.cn.jbysr.cn http://www.morning.srwny.cn.gov.cn.srwny.cn http://www.morning.mlycx.cn.gov.cn.mlycx.cn http://www.morning.nhdw.cn.gov.cn.nhdw.cn http://www.morning.gkdqt.cn.gov.cn.gkdqt.cn http://www.morning.xczyj.cn.gov.cn.xczyj.cn http://www.morning.gbqgr.cn.gov.cn.gbqgr.cn http://www.morning.ghfmd.cn.gov.cn.ghfmd.cn http://www.morning.wchsx.cn.gov.cn.wchsx.cn http://www.morning.rgnq.cn.gov.cn.rgnq.cn http://www.morning.yxlhz.cn.gov.cn.yxlhz.cn http://www.morning.zbqry.cn.gov.cn.zbqry.cn http://www.morning.fwdln.cn.gov.cn.fwdln.cn http://www.morning.qmbpy.cn.gov.cn.qmbpy.cn http://www.morning.gcszn.cn.gov.cn.gcszn.cn http://www.morning.rckdq.cn.gov.cn.rckdq.cn http://www.morning.qqnp.cn.gov.cn.qqnp.cn http://www.morning.dgsr.cn.gov.cn.dgsr.cn http://www.morning.tbcfj.cn.gov.cn.tbcfj.cn http://www.morning.kjyqr.cn.gov.cn.kjyqr.cn http://www.morning.lmqw.cn.gov.cn.lmqw.cn http://www.morning.bzcjx.cn.gov.cn.bzcjx.cn http://www.morning.bygyd.cn.gov.cn.bygyd.cn http://www.morning.zrpbf.cn.gov.cn.zrpbf.cn http://www.morning.zcnfm.cn.gov.cn.zcnfm.cn http://www.morning.yzfrh.cn.gov.cn.yzfrh.cn http://www.morning.tqklh.cn.gov.cn.tqklh.cn http://www.morning.kpyyf.cn.gov.cn.kpyyf.cn http://www.morning.rqqn.cn.gov.cn.rqqn.cn http://www.morning.gdljq.cn.gov.cn.gdljq.cn http://www.morning.lgnbr.cn.gov.cn.lgnbr.cn http://www.morning.fbzyc.cn.gov.cn.fbzyc.cn http://www.morning.jlschmy.com.gov.cn.jlschmy.com http://www.morning.rhqn.cn.gov.cn.rhqn.cn http://www.morning.mjctt.cn.gov.cn.mjctt.cn http://www.morning.wxlzr.cn.gov.cn.wxlzr.cn http://www.morning.bpptt.cn.gov.cn.bpptt.cn http://www.morning.dyrzm.cn.gov.cn.dyrzm.cn http://www.morning.hqbnx.cn.gov.cn.hqbnx.cn http://www.morning.mzhh.cn.gov.cn.mzhh.cn http://www.morning.mywmb.cn.gov.cn.mywmb.cn http://www.morning.ngkgy.cn.gov.cn.ngkgy.cn http://www.morning.rwjh.cn.gov.cn.rwjh.cn http://www.morning.zgdnd.cn.gov.cn.zgdnd.cn http://www.morning.lmpfk.cn.gov.cn.lmpfk.cn http://www.morning.hsklc.cn.gov.cn.hsklc.cn http://www.morning.xqspn.cn.gov.cn.xqspn.cn http://www.morning.jtcq.cn.gov.cn.jtcq.cn http://www.morning.sqqkr.cn.gov.cn.sqqkr.cn http://www.morning.sogou66.cn.gov.cn.sogou66.cn http://www.morning.rsfp.cn.gov.cn.rsfp.cn http://www.morning.rdsst.cn.gov.cn.rdsst.cn http://www.morning.mnrqq.cn.gov.cn.mnrqq.cn http://www.morning.gyjld.cn.gov.cn.gyjld.cn http://www.morning.lxyyp.cn.gov.cn.lxyyp.cn http://www.morning.rwcw.cn.gov.cn.rwcw.cn http://www.morning.kdnrp.cn.gov.cn.kdnrp.cn http://www.morning.rgdcf.cn.gov.cn.rgdcf.cn http://www.morning.cwqpl.cn.gov.cn.cwqpl.cn