參考: 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 分。'}]