更新提示配置和AI服务内容,增强信息提取助手的描述,明确提取要求,添加后处理逻辑以推断缺失字段,改进字段提取方法以提高数据提取的准确性和完整性。

This commit is contained in:
python 2025-12-09 12:56:28 +08:00
parent b8d89c28ec
commit eaa384cf7e
2 changed files with 180 additions and 18 deletions

View File

@ -1,15 +1,15 @@
{
"prompt_template": {
"intro": "请从以下输入文本中提取结构化信息。仔细分析文本内容,准确提取每个字段的值。",
"intro": "请从以下输入文本中提取结构化信息。仔细分析文本内容,准确提取每个字段的值。\n\n⚠ 重要提醒:请逐字逐句仔细阅读输入文本,不要遗漏任何信息。对于性别、年龄、职务、单位、文化程度等字段,请特别仔细查找,这些信息可能以各种形式出现在文本中。",
"input_text_label": "输入文本:",
"output_fields_label": "需要提取的字段(请仔细分析每个字段,确保提取完整):",
"json_format_label": "请严格按照以下JSON格式返回结果只返回JSON对象不要包含任何其他文字说明或markdown代码块标记",
"requirements_label": "重要要求(请严格遵守):",
"requirements": [
"逐字逐句仔细分析输入文本,不要遗漏任何信息",
"对于每个字段,请从多个角度思考:直接提及、同义词、隐含信息、可推断信息",
"如果文本中明确提到某个信息,必须提取出来,不能设为空",
"如果可以通过已有信息合理推断(如根据出生年月推算年龄),请进行推断并填写",
"⚠️ 逐字逐句仔细分析输入文本,不要遗漏任何信息。请特别关注性别、年龄、职务、单位、文化程度等字段",
"对于每个字段,请从多个角度思考:直接提及、同义词、隐含信息、可推断信息。例如:性别可能以\"男\"、\"女\"、\"男性\"、\"女性\"、\"先生\"、\"女士\"等形式出现",
"如果文本中明确提到某个信息(如\"30岁\"、\"男\"、\"总经理\"、\"某公司\"等),必须提取出来,不能设为空",
"如果可以通过已有信息合理推断,请进行推断并填写:\n - 根据出生年月如1980年05月和当前年份2024年计算年龄44岁\n - 从单位及职务(如\"某公司总经理\")中拆分单位(\"某公司\")和职务(\"总经理\"\n - 从工作基本情况中提取性别、文化程度等信息",
"如果某个字段在输入文本中确实找不到任何相关信息,该字段值才设为空字符串\"\"",
"日期格式统一为中文格式YYYY年MM月1980年05月表示1980年5月如果包含日期信息则格式为YYYY年MM月DD日1985年05月17日。注意年份必须是4位数字月份和日期必须是2位数字如1980年5月应格式化为1980年05月不是1980年5月",
"性别统一为\"男\"或\"女\",不要使用\"男性\"或\"女性\"。如果文本中提到\"男性\"、\"男\"、\"先生\"等,统一转换为\"男\";如果提到\"女性\"、\"女\"、\"女士\"等,统一转换为\"女\"",
@ -47,8 +47,11 @@
"description": "被核查人员性别",
"rules": [
"只能返回\"男\"或\"女\"",
"如果文本中提到\"男性\"、\"男性公民\"等,统一转换为\"男\"",
"如果文本中提到\"女性\"、\"女性公民\"等,统一转换为\"女\""
"如果文本中提到\"男性\"、\"男性公民\"、\"男\"、\"先生\"等,统一转换为\"男\"",
"如果文本中提到\"女性\"、\"女性公民\"、\"女\"、\"女士\"等,统一转换为\"女\"",
"请仔细查找文本中所有可能表示性别的词汇,不要遗漏",
"如果文本中提到\"XXX...\"或\"XXX...\",必须提取性别",
"如果工作基本情况中提到性别信息,必须提取"
]
},
"target_date_of_birth": {
@ -122,9 +125,10 @@
"target_age": {
"description": "被核查人员年龄",
"rules": [
"如果文本中直接提到年龄(如\"30岁\"、\"30周岁\"、\"年龄30\"),直接提取数字部分",
"如果只有出生年月(如\"1980年5月出生\"、\"198005\"可以根据当前年份2024年计算年龄",
"如果文本中直接提到年龄(如\"30岁\"、\"30周岁\"、\"年龄30\"、\"现年30\"),直接提取数字部分",
"如果只有出生年月(如\"1980年5月出生\"、\"1980年05月\"必须根据当前年份2024年计算年龄如1980年出生2024-1980=44岁",
"年龄格式:纯数字,单位为岁,如\"44\"表示44岁",
"⚠️ 如果已有出生年月信息,必须计算年龄,不能设为空字符串",
"如果文本中既没有直接提到年龄,也没有出生年月信息,则设为空字符串"
]
},
@ -144,8 +148,9 @@
"从单位及职务信息中提取单位名称部分",
"单位名称包括:公司、企业、机关、事业单位、部门等(如\"XX公司\"、\"XX局\"、\"XX部门\"、\"XX委员会\"等)",
"如果文本中只提到单位名称,直接提取",
"如果文本中提到\"XX公司总经理\",提取\"XX公司\"部分",
"⚠️ 如果文本中提到\"XX公司总经理\"必须提取\"XX公司\"部分,不能设为空",
"如果文本中提到\"XX单位XX职务\",提取\"XX单位\"部分",
"如果已有单位及职务字段target_organization_and_position必须从中拆分出单位名称",
"保持单位名称的完整性,不要遗漏"
]
},
@ -155,8 +160,9 @@
"从单位及职务信息中提取职务名称部分",
"职务名称包括:总经理、经理、局长、处长、科长、主任、书记、部长等",
"如果文本中只提到职务名称,直接提取",
"如果文本中提到\"XX公司总经理\",提取\"总经理\"部分",
"⚠️ 如果文本中提到\"XX公司总经理\"必须提取\"总经理\"部分,不能设为空",
"如果文本中提到\"XX单位XX职务\",提取\"XX职务\"部分",
"如果已有单位及职务字段target_organization_and_position必须从中拆分出职务名称",
"如果文本中提到多个职务,需要全部提取,用\"、\"连接",
"保持职务名称的准确性"
]

View File

@ -204,7 +204,7 @@ class AIService:
"messages": [
{
"role": "system",
"content": "你是一个专业的数据提取助手。请仔细分析用户提供的输入文本提取所有相关信息并严格按照指定的JSON格式返回结果。只返回JSON对象不要包含任何其他文字说明、思考过程或markdown代码块标记"
"content": "你是一个专业的数据提取助手。请仔细分析用户提供的输入文本提取所有相关信息并严格按照指定的JSON格式返回结果。\n\n重要要求:\n1. 必须仔细阅读输入文本的每一个字,不要遗漏任何信息\n2. 对于每个字段,请从多个角度思考:直接提及、同义词、隐含信息、可推断信息\n3. 如果文本中明确提到某个信息(如性别、年龄、职务等),必须提取出来,不能设为空\n4. 如果可以通过已有信息合理推断(如根据出生年月推算年龄,从单位及职务中拆分单位和职务),请进行推断并填写\n5. 只返回JSON对象不要包含任何其他文字说明、思考过程或markdown代码块标记"
},
{
"role": "user",
@ -212,12 +212,12 @@ class AIService:
}
],
"stream": False,
"presence_penalty": 1.03,
"frequency_penalty": 1.0,
"repetition_penalty": 1.0,
"temperature": 0.3,
"top_p": 0.95,
"top_k": 1,
"presence_penalty": 1.05, # 提高presence_penalty鼓励模型提取更多不同字段
"frequency_penalty": 1.02, # 提高frequency_penalty减少重复
"repetition_penalty": 1.05, # 提高repetition_penalty避免重复
"temperature": 0.2, # 降低temperature提高确定性
"top_p": 0.9, # 降低top_p更聚焦
"top_k": 40, # 增加top_k允许更多选择
"seed": 1,
"max_tokens": self.api_max_tokens,
"n": 1,
@ -305,6 +305,12 @@ class AIService:
for key in ['target_name', 'target_gender', 'target_age', 'target_date_of_birth']:
if key in normalized_data:
print(f"[AI服务] 日期格式化后 {key} = '{normalized_data[key]}'")
# 后处理:从已有信息推断缺失字段
normalized_data = self._post_process_inferred_fields(normalized_data, output_fields)
# 打印后处理后的关键字段
for key in ['target_name', 'target_gender', 'target_age', 'target_date_of_birth', 'target_organization', 'target_position']:
if key in normalized_data:
print(f"[AI服务] 后处理后 {key} = '{normalized_data[key]}'")
return normalized_data
# 如果无法提取JSON记录错误
@ -840,6 +846,156 @@ class AIService:
# 如果无法解析,返回原值
return date_str
def _post_process_inferred_fields(self, data: Dict, output_fields: List[Dict]) -> Dict:
"""
后处理从已有信息推断缺失字段
Args:
data: 提取的数据字典
output_fields: 输出字段列表
Returns:
后处理后的数据字典
"""
# 创建字段编码到字段信息的映射
field_code_map = {field['field_code']: field for field in output_fields}
# 1. 从出生年月计算年龄
if 'target_age' in field_code_map and (not data.get('target_age') or data.get('target_age') == ''):
if 'target_date_of_birth' in data and data.get('target_date_of_birth'):
age = self._calculate_age_from_birth_date(data['target_date_of_birth'])
if age:
data['target_age'] = str(age)
print(f"[AI服务] 后处理:从出生年月 '{data['target_date_of_birth']}' 计算年龄: {age}")
# 2. 从单位及职务中拆分单位和职务
if 'target_organization_and_position' in data and data.get('target_organization_and_position'):
org_pos = data['target_organization_and_position']
# 拆分单位
if 'target_organization' in field_code_map and (not data.get('target_organization') or data.get('target_organization') == ''):
org = self._extract_organization_from_org_pos(org_pos)
if org:
data['target_organization'] = org
print(f"[AI服务] 后处理:从单位及职务 '{org_pos}' 提取单位: {org}")
# 拆分职务
if 'target_position' in field_code_map and (not data.get('target_position') or data.get('target_position') == ''):
pos = self._extract_position_from_org_pos(org_pos)
if pos:
data['target_position'] = pos
print(f"[AI服务] 后处理:从单位及职务 '{org_pos}' 提取职务: {pos}")
return data
def _calculate_age_from_birth_date(self, birth_date: str) -> Optional[int]:
"""
从出生年月计算年龄
Args:
birth_date: 出生年月格式如 "1980年05月" "198005"
Returns:
年龄整数如果无法计算则返回None
"""
if not birth_date:
return None
birth_date = str(birth_date).strip()
# 提取年份
year_match = re.search(r'(\d{4})', birth_date)
if not year_match:
return None
birth_year = int(year_match.group(1))
current_year = 2024 # 当前年份
# 计算年龄
age = current_year - birth_year
# 验证年龄合理性0-150岁
if 0 <= age <= 150:
return age
return None
def _extract_organization_from_org_pos(self, org_pos: str) -> Optional[str]:
"""
从单位及职务中提取单位名称
Args:
org_pos: 单位及职务 "某公司总经理"
Returns:
单位名称 "某公司"
"""
if not org_pos:
return None
org_pos = str(org_pos).strip()
# 常见职务关键词
position_keywords = [
'总经理', '经理', '局长', '处长', '科长', '主任', '书记', '部长',
'副部长', '副经理', '副局长', '副处长', '副科长', '副主任', '副书记',
'董事长', '副董事长', '总裁', '副总裁', '总监', '副总监',
'部长', '副部长', '司长', '副司长', '厅长', '副厅长',
'市长', '副市长', '县长', '副县长', '乡长', '副乡长',
'镇长', '副镇长', '村长', '副村长'
]
# 尝试匹配:单位 + 职务
for pos_keyword in position_keywords:
if pos_keyword in org_pos:
# 找到职务位置,提取前面的单位部分
pos_index = org_pos.find(pos_keyword)
if pos_index > 0:
org = org_pos[:pos_index].strip()
if org:
return org
# 如果没有找到明确的职务关键词,尝试其他模式
# 例如:"XX公司XX部门XX职务"
# 这里简单返回,可能需要更复杂的逻辑
return None
def _extract_position_from_org_pos(self, org_pos: str) -> Optional[str]:
"""
从单位及职务中提取职务名称
Args:
org_pos: 单位及职务 "某公司总经理"
Returns:
职务名称 "总经理"
"""
if not org_pos:
return None
org_pos = str(org_pos).strip()
# 常见职务关键词
position_keywords = [
'总经理', '经理', '局长', '处长', '科长', '主任', '书记', '部长',
'副部长', '副经理', '副局长', '副处长', '副科长', '副主任', '副书记',
'董事长', '副董事长', '总裁', '副总裁', '总监', '副总监',
'部长', '副部长', '司长', '副司长', '厅长', '副厅长',
'市长', '副市长', '县长', '副县长', '乡长', '副乡长',
'镇长', '副镇长', '村长', '副村长'
]
# 按长度从长到短排序,优先匹配长关键词(如"副经理"优先于"经理"
position_keywords.sort(key=len, reverse=True)
# 尝试匹配职务关键词
for pos_keyword in position_keywords:
if pos_keyword in org_pos:
return pos_keyword
return None
def _parse_text_response(self, text: str, output_fields: List[Dict]) -> Dict:
"""
从文本响应中解析字段值备用方案