Hanah

Hanah

wow-agent-day03 OpenAI实现阅卷智能体

Reference: DataWhale wow agent day03
延用 day02 的环境配置和大模型设置。

定义函数#

提取大模型输出内容中的 json 部分#

import re
def extract_json_content(text):
  text = text.replace()

函数解析:
从文本中提取 JSON 内容并进行清理的函数

def extract_json_content(text):
    text = text.replace("\n","")
    pattern = r"```json(.*?)```"
    matches = re.findall(pattern, text, re.DOTALL)
    if matches:
        return matches[0].strip()
    return text
参数:
    text (str): 输入的文本字符串,通常包含JSON代码块
    
返回:
    str: 提取并清理后的JSON字符串
    
函数说明:
1. text.replace("\n","") - 删除文本中所有的换行符
2. pattern = r"```json(.*?)```" - 定义正则表达式模式,匹配```json和```之间的内容
3. re.findall() - 使用正则表达式查找所有匹配项,re.DOTALL允许.匹配换行符
4. matches[0].strip() - 获取第一个匹配结果并去除首尾空白
5. 如果没有匹配项则返回原文本

把 json 字符串解析成 python 对象#

对函数进行了一些修改

class JsonOutputParser:
    def parse(self, result):
        # 首先尝试直接解析
        try:
            return json.loads(result)
        except json.JSONDecodeError:
            pass
            
        # 尝试提取JSON内容
        cleaned_result = extract_json_content(result)
        try:
            return json.loads(cleaned_result)
        except json.JSONDecodeError:
            pass
            
        # 尝试修复常见JSON错误
        try:
            # 处理单引号
            fixed_result = cleaned_result.replace("'", '"')
            # 处理末尾多余的逗号
            fixed_result = re.sub(r',\s*}', '}', fixed_result)
            # 处理未闭合的引号
            fixed_result = re.sub(r'([^"])"([^"])', r'\1"\2', fixed_result)
            return json.loads(fixed_result)
        except json.JSONDecodeError as e:
            raise ValueError(f"无法解析JSON输出。原始输出: {result}\n错误信息: {str(e)}")

函数解析:

    参数:
        result (str): LLM生成的包含JSON的文本
    返回:
        dict: 解析后的JSON对象
        
    优化说明:
    1. 增加多种JSON提取方式,提高鲁棒性
    2. 添加JSON修复机制,处理常见错误
    3. 增加重试机制,提高成功率
    

定义 GradingOpenAI#

class GradingOpenAI:
    def __init__(self):
        self.model = "glm-4-flash"
        self.output_parser = JsonOutputParser()
        self.template = """你是一位中国专利代理师考试阅卷专家,
擅长根据给定的题目和答案为考生生成符合要求的评分和中文评语,
并按照特定的格式输出。
你的任务是,根据我输入的考题和答案,针对考生的作答生成评分和中文的评语,并以JSON格式返回。
阅卷标准适当宽松一些,只要考生回答出基本的意思就应当给分。
答案如果有数字标注,含义是考生如果答出这个知识点,这道题就会得到几分。
生成的中文评语需要能够被json.loads()这个函数正确解析。
生成的整个中文评语需要用英文的双引号包裹,在被包裹的字符串内部,请用中文的双引号。
中文评语中不可以出现换行符、转义字符等等。

输出格式为JSON:
{{
  "llmgetscore": 0,
  "llmcomments": "中文评语"
}}

比较学生的回答与正确答案,
并给出满分为10分的评分和中文评语。 
题目:{ques_title} 
答案:{answer} 
学生的回复:{reply}"""

    def create_prompt(self, ques_title, answer, reply):
        return self.template.format(
            ques_title=ques_title,
            answer=answer,
            reply=reply
        )

    def grade_answer(self, ques_title, answer, reply):
        success = False
        while not success:
            # 这里是一个不得已的权宜之计
            # 上面的json解析函数不是表现很差吗,那就多生成几遍,直到解析成功
            # 对大模型生成的内容先解析一下,如果解析失败,就再让大模型生成一遍
            try:
                response = client.chat.completions.create(
                    model=self.model,
                    messages=[
                        {"role": "system", "content": "你是一位专业的考试阅卷专家。"},
                        {"role": "user", "content": self.create_prompt(ques_title, answer, reply)}
                    ],
                    temperature=0.7
                )

                result = self.output_parser.parse(response.choices[0].message.content)
                success = True
            except Exception as e:
                print(f"Error occurred: {e}")
                continue

        return result['llmgetscore'], result['llmcomments']

    def run(self, input_data):
        output = []
        for item in input_data:
            score, comment = self.grade_answer(
                item['ques_title'], 
                item['answer'], 
                item['reply']
            )
            item['llmgetscore'] = score
            item['llmcomments'] = comment
            output.append(item)
        return output
grading_openai = GradingOpenAI()

演示#

input

# 示例输入数据
input_data = [
 {'ques_title': '请解释共有技术特征、区别技术特征、附加技术特征、必要技术特征的含义',
  'answer': '共有技术特征:与最接近的现有技术共有的技术特征(2.5分); 区别技术特征:区别于最接近的现有技术的技术特征(2.5分); 附加技术特征:对所引用的技术特征进一步限定的技术特征,增加的技术特征(2.5分); 必要技术特征:为解决其技术问题所不可缺少的技术特征(2.5分)。',
  'fullscore': 10,
  'reply': '共有技术特征:与所对比的技术方案相同的技术特征\n区别技术特征:与所对比的技术方案相区别的技术特征\n附加技术特征:对引用的技术特征进一步限定的技术特征\n必要技术特征:解决技术问题必须可少的技术特征'},
 {'ques_title': '请解释前序部分、特征部分、引用部分、限定部分',
  'answer': '前序部分:独权中,主题+与最接近的现有技术共有的技术特征,在其特征在于之前(2.5分); 特征部分:独权中,与区别于最接近的现有技术的技术特征,在其特征在于之后(2.5分);引用部分:从权中引用的权利要求编号及主题 (2.5分);限定部分:从权中附加技术特征(2.5分)。',
  'fullscore': 10,
  'reply': '前序部分:独立权利要求中与现有技术相同的技术特征\n特征部分:独立权利要求中区别于现有技术的技术特征\n引用部分:从属权利要求中引用其他权利要求的部分\n限定部分:对所引用的权利要求进一步限定的技术特征'}]

运行智能体

graded_data = grading_openai.run(input_data)
print(graded_data)

结果
[{'ques_title': ' 请解释共有技术特征、区别技术特征、附加技术特征、必要技术特征的含义 ', 'answer': ' 共有技术特征:与最接近的现有技术共有的技术特征(2.5 分); 区别技术特征:区别于最接近的现有技术的技术特征(2.5 分); 附加技术特征:对所引用的技术特征进一步限定的技术特征,增加的技术特征(2.5 分); 必要技术特征:为解决其技术问题所不可缺少的技术特征(2.5 分)。', 'fullscore': 10, 'reply': ' 共有技术特征:与所对比的技术方案相同的技术特征 \n 区别技术特征:与所对比的技术方案相区别的技术特征 \n 附加技术特征:对引用的技术特征进一步限定的技术特征 \n 必要技术特征:解决技术问题必须可少的技术特征 ', 'llmgetscore': 10, 'llmcomments': ' 考生对共有技术特征、区别技术特征、附加技术特征、必要技术特征的解释基本正确,能够准确表达这些概念的含义,故给予满分。'}, {'ques_title': ' 请解释前序部分、特征部分、引用部分、限定部分 ', 'answer': ' 前序部分:独权中,主题 + 与最接近的现有技术共有的技术特征,在其特征在于之前(2.5 分); 特征部分:独权中,与区别于最接近的现有技术的技术特征,在其特征在于之后(2.5 分);引用部分:从权中引用的权利要求编号及主题 (2.5 分);限定部分:从权中附加技术特征(2.5 分)。', 'fullscore': 10, 'reply': ' 前序部分:独立权利要求中与现有技术相同的技术特征 \n 特征部分:独立权利要求中区别于现有技术的技术特征 \n 引用部分:从属权利要求中引用其他权利要求的部分 \n 限定部分:对所引用的权利要求进一步限定的技术特征 ', 'llmgetscore': 8, 'llmcomments': ' 学生的回答基本正确,对前序部分和特征部分的解释与标准答案相符,对引用部分和限定部分的理解也正确,但未完全表述出标准答案中的具体技术特征顺序和位置,因此给予 8 分。'}]

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。