# [CCKS2024——大模型知识编辑评测](https://tianchi.aliyun.com/competition/entrance/532182)

文档目录如下：
---
<!-- TOC -->
- [初赛](#初赛)   
  - [1.任务目标](#1任务目标)   
  - [2.数据集介绍](#2数据集介绍)   
  - [3.环境安装](#3环境安装)   
  - [4.快速运行(Wiki_recent和ZsRE)：](#4快速运行wiki_recent和zsre)                 
  - [5.快速运行(SafeEdit):](#5快速运行safeedit)    
  - [6.文件提交](#6文件提交)
- [复赛](#复赛)    
  - [1.复赛任务设定](#1复赛任务设定)   
  - [2.数据集介绍](#2数据集介绍)   
  - [3.环境安装](#3环境安装)    
  - [4.快速运行](#4快速运行)      
  - [5.文件提交](#5文件提交)   
  - [6.评测指标](#6评测指标)      
<!-- /TOC -->



# 初赛

这个部分是关于如何复现天池比赛“CCKS2024——大模型知识编辑评测”初赛中baseline的说明，本次比赛baseline由大模型知识编辑工具[EasyEdit](https://github.com/zjunlp/EasyEdit)提供。

## 1.任务目标
知识编辑的目标是通过修改大模型中的特定知识以缓解知识谬误问题。知识编辑通常包含三个基本的设定：知识新增、知识修改和知识删除。(1)知识新增旨在让大模型习得新知识。(2)知识修改旨在改变已存储在大模型内部的知识。(3)知识删除旨在让大模型遗忘已习得的知识。

## 2.数据集介绍
初赛使用的数据集为知识新增数据集Wiki_recent、知识修改数据集ZsRE和知识擦除数据集SafeEdit（其中ZsRE和Wiki_recent均来自KnowEdit），请到天池比赛说明相关位置下载数据集。

## 3.环境安装
```
git clone https://github.com/zjunlp/EasyEdit.git
conda create -n EasyEdit python=3.9.7
conda activate EasyEdit
pip install -r requirements.txt
```

## 4.快速运行(Wiki_recent和ZsRE)：
EasyEdit中已经集成了若干编辑方法，你可以根据自己的需要选择合适的方法来快速运行EasyEdit，以下以gpt2-xl为基座为例。
- 在使用特定的method进行编辑之前请先到该方法对应的.../EasyEdit/hparams/method/目录下修改或创建gpt2-xl.yaml文件。
- 请将三个数据集放入 ./data 文件夹，目录如下：
```
EasyEdit
├── data
│   ├── recent_test.json
│   ├── SafeEdit_test_ccks.json
│   ├── ZsRE-test-all.json
```
- 除了SERAC和MEND方法外，其它方法均可采用以下格式使用EasyEdit，若要使用SERAC和MEND方法，请查看[KnowEdit.md](https://github.com/zjunlp/EasyEdit/blob/main/examples/KnowEdit.md)相应描述。
### (1)对于wiki_recent：
#### ROME
```
python run_knowedit_llama2.py \
    --editing_method=ROME \
    --hparams_dir=.../EasyEdit/hparams/ROME/gpt2-xl.yaml \
    --data_dir=./data/recent_test.json \
    --datatype='recent'
```
#### FT
```
python run_knowedit_llama2.py \
    --editing_method=FT \
    --hparams_dir=.../EasyEdit/hparams/FT/gpt2-xl.yaml \
    --data_dir=./data/recent_test.json \
    --datatype='recent'
```
### (2)对于ZsRE：
#### ROME
```
python run_knowedit_llama2.py \
    --editing_method=ROME \
    --hparams_dir=.../EasyEdit/hparams/ROME/gpt2-xl.yaml \
    --data_dir=./data/ZsRE-test-all.json \
    --datatype='zsre'
```
#### FT
```
python run_knowedit_llama2.py \
    --editing_method=FT \
    --hparams_dir=.../EasyEdit/hparams/FT/gpt2-xl.yaml \
    --data_dir=./data/ZsRE-test-all.json \
    --datatype='zsre'
```
## 5.快速运行(SafeEdit):

Move this file **[run_ccks_SafeEdit_gpt2-xl.py](https://github.com/zjunlp/EasyEdit/blob/main/examples/run_ccks_SafeEdit_gpt2-xl.py)** to **./**, and run:

```
python run_ccks_SafeEdit_gpt2-xl.py \
     --ccks \
     --editing_method=DINM \
     --edited_model=gpt2-xl \
     --data_dir=./data/SafeEdit_test_ccks.json \
     --hparams_dir=./hparams/DINM/gpt2-xl.yaml \
     --safety_classifier_dir=zjunlp/SafeEdit-Safety-Classifier 
```
❗️❗️ Please set max_output_length to 300, set max_length to 1024 in ./hparams/DINM/gpt2-xl.yaml.
For some role-playing attack prompts, LLMs may initially generate safe responses and then suddenly generate toxic text. Therefore, you should set enough max_output_length to evaluate the safety of LLM.
Considering the maximum length of certain LLMs may not suffice; you can truncate the input length (from right to left, as harmful questions typically appear on the right).

## 6.文件提交
得到三个test.json对应的输出文件之后，按照天池比赛说明所规定的顺序将3个json文件合并为一个列表，再进行评测提交，可用如下代码：
```
import os
import json

def merge_json_folder(folder_path, output_file):
    json_files = [f for f in os.listdir(folder_path) if f.endswith('.json')]  # 获取文件夹中的所有 JSON 文件路径

    merged_data = []  # 创建一个空列表，用于存储合并后的 JSON 数据

    for file in json_files:
        file_path = os.path.join(folder_path, file)  # 构建完整的文件路径
        with open(file_path, 'r') as json_file:
            data = json.load(json_file)  # 读取 JSON 文件并解析为 Python 对象
            merged_data.append(data)  # 将解析后的 JSON 数据添加到列表中
 
    # 将合并后的数据转换为 JSON 字符串
    merged_json = json.dumps(merged_data, indent=4)
 
    # 将合并后的 JSON 字符串写入目标文件
    with open(output_file, 'w') as output:
        output.write(merged_json)

folder_path = "results_folder"  # 存放 JSON 文件的文件夹路径，请确保三个json文件的顺序如规定所言
output_file = "final_result.json"  # 合并后的 JSON 文件路径
merge_json_folder(folder_path, output_file)
```


# 复赛

这个部分是关于如何复现天池比赛“CCKS2024——大模型知识编辑评测”复赛中baseline的说明，本次比赛baseline由大模型知识编辑工具[EasyEdit](https://github.com/zjunlp/EasyEdit)提供。

## 1.复赛任务设定
本次知识编辑比赛复赛的任务设定是对大模型中的部分中文知识进行编辑，即通过修改大模型中的参数化特定中文知识来缓解知识谬误问题，主要包含两个基本的设定：知识新增和知识修改。

## 2.数据集介绍
本次复赛使用的数据集(ccks-CKnowEdit)全部来源于全新的中文知识编辑数据集CKnowEdit，根据不同的中文知识来源和中文知识类型划分，CKnowEdit中的数据可以细分为以下7种类型：(1)古诗，(2)谚语，(3)成语，(4)拼音注音，(5)文言文，(6)中国地理，(7)百度贴吧ruozhi吧。(请到天池平台比赛页面相关位置下载数据集。)

本次复赛使用的数据集(ccks-CKnowEdit)类别上涵盖了CKnowEdit的全部7种类型，共由700条数据组成，以下是本次复赛数据集中7种类型的数量分布：

| 数据类型 | 数量 |
| ---- | ---- |
| 古诗 | 133 |
| 谚语 | 80 |
| 成语 | 40 |
| 拼音注音 | 50 |
| 文言文 | 70 |
| 中国地理 | 50 |
| ruozhi吧 | 277 |


以下是一个sample示例：
```
{
    "prompt": "请解释被在一日昼寝被中，落被于地中的意思。仅需给出该字意思即可，无需解释全文。",
    "target_old": "被在这里是动词，意思是盖、裹的意思。",
    "target_new": "被子",
    "portability": [
        {
            "prompt": "请解释被在被褥之下中的意思。仅需给出该字意思即可，无需解释全文。",
            "answer": "此处'被'是名词，指盖在身上的被子"
        }
    ],
    "locality": [
        {
            "prompt": "请解释被在信而见疑，忠而被谤中的意思。仅需给出该字意思即可，无需解释全文。",
            "answer": "表被动"
        }
    ],
    "rephrase": [
        "请描述被字在句子‘一日昼寝被中，落被于地’中的含义。无需全文解释。",
        "请阐释在‘一日昼寝被中，落被于地’中，‘被’的意思是什么？不必解释整句。",
        "在‘一日昼寝被中，落被于地’这个句子中，词‘被’的解释是什么？仅限词义。"
    ]
}
```
各字段的解释如下：

“prompt”：提示；"target_old"：模型对prompt的错误的回复，反应了模型中的知识谬误；“target_new”：新知识答案；“portability”：和新知识有关联的知识提示和答案；“locality”（并非所有sample都有）：与新知识无关的知识提示和答案；“rephrase”：prompt的同义表达

## 3.环境安装
```
git clone https://github.com/zjunlp/EasyEdit.git
conda create -n EasyEdit python=3.9.7
conda activate EasyEdit
pip install -r requirements.txt
```

## 4.快速运行
EasyEdit中已经集成了若干编辑方法，你可以根据自己的需要选择合适的方法来快速运行EasyEdit，由于本次复赛要求使用的基座模型为Qwen-1.8B-chat，所以以下说明以Qwen-1.8B-chat为例。
- 在使用特定的method进行编辑之前请先到该方法对应的.../EasyEdit/hparams/method/目录下修改或创建qwen-1.8b-chat.yaml文件。
- 除了SERAC和MEND方法外，其它方法均可采用以下格式使用EasyEdit，若要使用SERAC和MEND方法，请查看[KnowEdit.md](https://github.com/zjunlp/EasyEdit/blob/main/examples/KnowEdit.md)相应描述。
-以LoRA和FT方法为例：
### LoRA
```
python run_CKnowEdit_qwen-1.8B.py \
    --editing_method=LoRA \
    --hparams_dir=./EasyEdit/hparams/LoRA/qwen-1.8b-chat.yaml \
    --data_dir=./ccks-CKnowEdit.json \
    --chinese_ds_type='CKnowEdit'
```
### FT
```
python run_CKnowEdit_qwen-1.8B.py \
    --editing_method=FT \
    --hparams_dir=./EasyEdit/hparams/FT/qwen-1.8b-chat.yaml \
    --data_dir=./ccks-CKnowEdit.json \
    --chinese_ds_type='CKnowEdit'
```

## 5.文件提交
得到输出文件之后，若输出文件中各字段的值为Unicode转义序列而并非有效的中文字符，以下为示例：
```
{
    "pre": {
        "rewrite_ans": "\u5929\u5c06\u964d\u5927\u4efb\u4e8e\u662f\u4eba\u4e5f\u3002\n",
        "rephrase_ans": "\u5468\u516c\u5410\u54fa\u3002\n",
        "portability_ans": [
            "\u4eba\u5fc3\u6240\u5411\uff0c\u4ea6\u662f\u6210\u529f\u4e4b\u8def\u3002\n"
        ]
    },
    "case_id": 0,
    "requested_rewrite": {
        "prompt": "\u8bf7\u586b\u5199\u4e0b\u5217\u53e4\u8bd7\u6587\u7684\u540e\u4e00\u53e5\uff1a\u514b\u5df1\u590d\u793c\u4e3a\u4ec1\u3002\u4e00\u65e5\u514b\u5df1\u590d\u793c\uff0c",
        "target_new": "\u5929\u4e0b\u5f52\u4ec1\u7109\u3002",
        "ground_truth": "\u5176\u65af\u800c\u5df2\u77e3\u3002",
        "portability": {
            "por_hop": {
                "prompt": [
                    "\u8bf7\u586b\u5199\u4e0b\u5217\u53e4\u8bd7\u6587\u7684\u524d\u4e00\u53e5\uff1a\u5929\u4e0b\u5f52\u4ec1\u7109\u3002"
                ],
                "ground_truth": [
                    "\u514b\u5df1\u590d\u793c\u4e3a\u4ec1\u3002\u4e00\u65e5\u514b\u5df1\u590d\u793c\uff0c"
                ]
            }
        },
        "locality": {},
        "subject": "\u8bf7\u586b\u5199\u4e0b\u5217\u53e4\u8bd7\u6587\u7684\u540e\u4e00\u53e5\uff1a\u514b\u5df1\u590d\u793c\u4e3a\u4ec1\u3002\u4e00\u65e5\u514b\u5df1\u590d\u793c\uff0c",
        "rephrase_prompt": "\u4e0b\u5217\u53e4\u8bd7\u6587\u7684\u63a5\u4e0b\u6765\u4e00\u53e5\u662f\u4ec0\u4e48\uff1f\u514b\u5df1\u590d\u793c\u4e3a\u4ec1\u3002\u4e00\u65e5\u514b\u5df1\u590d\u793c\uff0c"
    },
    "post": {
        "rewrite_ans": "\u793c\u4e4b\u4e8e\u4eba\u4e5f\uff0c\u72b9\u76d0\u4e4b\u4e8e\u5473\u4e5f\u3002\n",
        "rephrase_ans": "\u5929\u4e0b\u5f52\u4ec1\u7109\u3002\n",
        "portability_ans": [
            "\u4ec1\u8005\u7231\u4eba\uff0c\u6709\u793c\u8005\u53d7\u4e4b\u3002\n"
        ],
        "fluency": {
            "ngram_entropy": 4.238170767642218
        }
    }
}
```
那么请先使用如下代码对结果文件格式进行转换得到有效中文字符之后再进行提交：
```
import json

# 读取JSON文件
with open("./results.json", 'r', encoding='utf-8') as file:
    data = json.load(file)

# 将JSON对象转换为格式化的字符串，并确保中文显示正确
json_str = json.dumps(data, ensure_ascii=False, indent=4)

# 将转换后的字符串写回文件或输出
with open("./results.json", 'w', encoding='utf-8') as file:
    file.write(json_str)
```
提交示例请到天池平台比赛页面相应位置进行下载。

## 6.评测指标
与初赛中运行EasyEdit之后直接就可以得到各条数据的指标不同，复赛我们采用了一种更贴合CKnowEdit风格和中文文字特殊性的评估方法，即选手们只需要得到模型在编辑之后直接输出的答案并提交上传即可，后续的评测打分完全由天池平台来完成。
### word-level overlap metric：ROUGE-L
我们选用的是ROUGE-L，将模型生成的答案与标准答案进行对比，得到答案的字词级别的表面的准确度。
### Semantic similarity：Bert-score
我们通过使用嵌入编码器(具体来说是paraphrase-multilingual-MiniLM-L12-v2)计算编码后embedding的余弦相似度来评估语义相似度，以量化文本模型的理解深度，从而保证了超越单纯词汇匹配的合理性。

最终得分 = 0.5 * ROUGE-L + 0.5 * Bert-score
