2024软件学院创新项目实训(4)

引言

上一篇中,我们讨论了数据应该是怎么样的格式,以及数据的获取步骤,这一篇集中讨论一下针对于这个项目而言具体的代码实现。

具体实现

按照我上一篇介绍的内容,数据获取步骤分为四步数据准备,数据预处理,数据清洗和数据标准化。

数据准备

数据来源于近五年肖四肖八预测题,格式是doc文档。

但是存在一个问题,网上寻找的肖四肖八预测题大多都是扫描版的pdf文档,并非word文档,因此想要获得到word文档,还需要进行人工处理,将pdf转化为word文档,虽然wps有自带的pdf转文档功能,但是其转化后的结果并不规整,因此还需要进行人工的处理。进行处理之后的格式是这样的:

将答案标为红色是为了识别答案。

此步骤还是消耗比较多的精力的。

数据预处理

对文档中的题目进行初步拆分和清洗。数据预处理就是将word文档中的每个题目单独的提取出来,并存放在一个json文件中,具体代码如下:

import os
import docx
import json


def one_ti(start_idx, end_idx, doc, all_test):
    test = dict()
    content = ""
    for j in range(start_idx, end_idx):
        para_text = doc.paragraphs[j].text
        if content == "":
            content = para_text
        else:
            content = content + "##n##" + para_text
    content = content.replace('\t', "##t##")
    content = content.replace(r"\t", "##t##")
    content = content.replace("  ", "")
    content = content.replace("  ", "")
    content = content.replace(" ", " ")
    content = content.replace("\n", "##n##")
    content = content.replace("##n####n##", "##n##")
    content = content.replace("##t####t##", "##t##")
    test["content"] = content
    all_test["test"].append(test)
    print(test)


def main():
    docx_path = os.path.join("datasets", "src", "politics.docx")
    doc = docx.Document(docx_path)
    para_nums = len(doc.paragraphs)

    start_idx = 0
    find_test = False
    ans_flag = False
    ans_style = None

    all_test = dict()
    all_test["test"] = []

    for i in range(para_nums):
        text = doc.paragraphs[i].text
        num = len(doc.paragraphs[i].runs)
        if num < 1:
            continue
        run0_style = str(doc.paragraphs[i].runs[0].font.color.rgb)

        if "考研政治题库" in text:
            if find_test and ans_flag:
                end_idx = i
                one_ti(start_idx, end_idx, doc, all_test)
            find_test = True
            ans_flag = False
            start_idx = i + 1

        if not find_test:
            continue

        if "【答案】" in text:
            ans_flag = True
            ans_style = run0_style
            continue

        if not ans_flag:
            continue
        else:
            if ans_style != run0_style:
                end_idx = i
                one_ti(start_idx, end_idx, doc, all_test)
                start_idx = i
                ans_flag = False
                continue

    all_test_str = json.dumps(all_test, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'))
    all_test_str.replace("},", "},\n")

    os.makedirs(os.path.join("datasets", "middle"), exist_ok=True)
    with open(os.path.join("datasets", "middle", "politics_all.json"), "w", encoding='utf-8') as f:
        f.write(all_test_str)
    print(len(all_test["test"]))


if __name__ == "__main__":
    main()

程序首先读取指定的docx文件,然后遪历其中的段落。在遍历过程中,程序会根据特定的规则判断题目和答案的位置,提取题目内容和答案内容,并将其组织为一个特定的数据结构。最终,程序将提取到的题目和答案数据保存为一个json格式的文件,以便进一步处理或分析。程序的流程包括读取docx文件、遍历段落、提取题目和答案、组织数据结构、保存为json文件。

输出的json文件如下所示:

数据清洗

本步骤由人工进行,将含有图、表的题目剔除,以及拆分不正确的题目剔除。由于没有有图的题目,故此步骤略过。

数据标准化

对题目数据的格式进行标准化,并使用json格式存储。

首先读取数据预处理得到的存储题目内容的json文件"politics_all.json"。遍历每个题目,提取题目的内容、答案、解析等信息。根据题目类型(单选题、多选题、其他题型)进行不同的处理:对于单选题和多选题,提取选项内容,整理为标准格式;对于其他题型,直接提取题目内容和答案。将处理后的题目信息组织为新的数据结构,并存储到一个新的字典中。将新的字典转换为json格式的字符串。将处理后的数据保存为另一个json文件"politics_std.json"中。

具体代码如下:

import os
import json


if __name__ == "__main__":
    path = os.path.join("datasets", "middle", "politics_all.json")
    with open(path, "r", encoding='utf-8') as f:
        test_all = json.load(f)

    tests = test_all["test"]
    output = ""
    new_test = dict()
    new_test["test"] = []

    choice_func = {
        "A": 0,
        "B": 1,
        "C": 2,
        "D": 3
    }

    for i, test in enumerate(tests):
        test_content = test["content"]
        ans = test_content.split("【答案】")[-1]
        analysis = test_content.split("【解析】")[-1]
        content = test_content.split("【答案】")[0]
        ans = ans.split("【解析】")[0]
        ans = ans.replace("##n##", "")
        analysis = analysis.replace("##n##", "").replace(" ", "")

        # 单选题
        if ans == "A" or ans == "B" or ans == "C" or ans == "D":
            content = content.replace(".", ".")
            choice_a = content.split("A.")[-1]
            choice_b = choice_a.split("B.")[-1]
            choice_c = choice_b.split("C.")[-1]
            choice_d = choice_c.split("D.")[-1]

            content = content.split("A.")[0]
            choice_a = choice_a.split("B.")[0]
            choice_b = choice_b.split("C.")[0]
            choice_c = choice_c.split("D.")[0]

            content = content.replace("##n##", "").replace("##t##", "").strip()
            choice_a = choice_a.replace("##n##", "").replace("##t##", "").strip()
            choice_b = choice_b.replace("##n##", "").replace("##t##", "").strip()
            choice_c = choice_c.replace("##n##", "").replace("##t##", "").strip()
            choice_d = choice_d.replace("##n##", "").replace("##t##", "").strip()

            test_i = {
                "tid": i + 1,
                "type": 0,
                "content": content,
                "choices": [choice_a, choice_b, choice_c, choice_d],
                "ans": choice_func[ans],
                "analysis": analysis
            }
            new_test["test"].append(test_i)

        # 多选题
        elif all(char.isalpha() for char in ans):
            content = content.replace(".", ".")
            choice_a = content.split("A.")[-1]
            choice_b = choice_a.split("B.")[-1]
            choice_c = choice_b.split("C.")[-1]
            choice_d = choice_c.split("D.")[-1]

            content = content.split("A.")[0]
            choice_a = choice_a.split("B.")[0]
            choice_b = choice_b.split("C.")[0]
            choice_c = choice_c.split("D.")[0]

            content = content.replace("##n##", "").replace("##t##", "").strip()
            choice_a = choice_a.replace("##n##", "").replace("##t##", "").strip()
            choice_b = choice_b.replace("##n##", "").replace("##t##", "").strip()
            choice_c = choice_c.replace("##n##", "").replace("##t##", "").strip()
            choice_d = choice_d.replace("##n##", "").replace("##t##", "").strip()

            test_i = {
                "tid": i + 1,
                "type": 2,
                "content": content,
                "choices": [choice_a, choice_b, choice_c, choice_d],
                "ans": ans,
                "analysis": analysis
            }
            new_test["test"].append(test_i)
        else:
            test_i = {
                "tid": i + 1,
                "type": 3,
                "content": content,
                "ans": ans,
            }
            new_test["test"].append(test_i)

    output = json.dumps(new_test, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'))
    with open(os.path.join("datasets", "middle", "politics_std.json"), "w", encoding='utf-8') as f:
        f.write(output)

得到的json文件如下:

转换为LLM训练数据集

通过这一步,来得到最终的训练数据集。

首先读取经过数据标准化得到的政治考研题库的标准化json文件"politics_std.json"。然后遍历题目信息,根据题目类型创建不同类型的对话数据。创建一些关于系统身份认知和自我介绍的对话数据。将所有对话数据组织成一个数据集dataset。将数据集转换为json格式的字符串并将数据集保存为一个新的json文件"politics.json"中。

具体代码如下:

import os
import json
from tqdm import tqdm

system_prompt = "你是考研政治题库,内在是InternLM-1.8B大模型。你将对考研政治知识点做详细、耐心、充分的解答。"


if __name__ == "__main__":
    dataset = []

    path = os.path.join("datasets", "middle", "politics_std.json")
    with open(path, "r", encoding='utf-8') as f:
        all_test = json.load(f)

    tests = all_test["test"]

    print("创建:单选题问题...")
    choice_func = {
        0: "A",
        1: "B",
        2: "C",
        3: "D"
    }
    for test in tqdm(tests):
        if test["type"] != 0:
            continue
        content = test["content"].replace("##n##", "\n")
        dataset.append({
            "conversation": [
                {
                    "system": system_prompt,
                    "input": "{}:A.{} B.{} C.{} D.{}".format(content, test["choices"][0], test["choices"][1], test["choices"][2], test["choices"][3]),
                    "output": "选择{}。{}。".format(choice_func[test["ans"]], test["analysis"])
                }
            ]
        })

    print("创建:多选题问题...")
    for test in tqdm(tests):
        if test["type"] != 2:
            continue
        content = test["content"].replace("##n##", "\n")
        dataset.append({
            "conversation": [
                {
                    "system": system_prompt,
                    "input": "(多选题){}:A.{} B.{} C.{} D.{}".format(content, test["choices"][0], test["choices"][1], test["choices"][2], test["choices"][3]),
                    "output": "选择{}。{}".format(test["ans"], test["analysis"])
                }
            ]
        })

    print("创建:综合类问题...")
    for test in tqdm(tests):
        if test["type"] != 3:
            continue
        content = test["content"].replace("##n##", "\n")
        dataset.append({
            "conversation": [
                {
                    "system": system_prompt,
                    "input": "{}?".format(content),
                    "output": "答案:{}".format(test["ans"])
                }
            ]
        })

    print("创建:身份认知类问题...")
    dataset.append({
        "conversation": [
            {
                "system": system_prompt,
                "input": "你是谁?",
                "output": "我是考研政治学习助手,内在是InternLM-1.8B大模型。"
            }
        ]
    })
    dataset.append({
        "conversation": [
            {
                "system": system_prompt,
                "input": "请介绍以下你自己。",
                "output": "我是考研政治学习助手,内在是InternLM-1.8B大模型。"
            }
        ]
    })
    dataset.append({
        "conversation": [
            {
                "system": system_prompt,
                "input": "做一下自我介绍。",
                "output": "我是考研政治学习助手,内在是InternLM-1.8B大模型。"
            }
        ]
    })
    dataset.append({
        "conversation": [
            {
                "system": system_prompt,
                "input": "为什么要开发你?",
                "output": "政治学科作为重要学科,对于考生的发展具有深远的影响。"
            }
        ]
    })

    print(len(dataset))
    output = json.dumps(dataset, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ':'))
    with open(os.path.join("datasets", "politics.json"), "w", encoding='utf-8') as f:
        f.write(output)

最终的得到的训练数据集文件:

至此,得到了满足模型要求的训练数据集。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值