This commit is contained in:
zy123 2024-09-13 16:05:16 +08:00
parent f079f705ea
commit 4393452f52
5 changed files with 106 additions and 87 deletions

View File

@ -39,8 +39,7 @@ def before_request():
def create_logger():
unique_id = str(uuid.uuid4())
g.unique_id = unique_id
# output_folder = f"flask_app/static/output/{unique_id}"
output_folder = f"C:/Users/Administrator/Desktop/货物标/zboutpub/{unique_id}"
output_folder = f"flask_app/static/output/{unique_id}"
os.makedirs(output_folder, exist_ok=True)
log_filename = "log.txt"
log_path = os.path.join(output_folder, log_filename)

View File

@ -1,30 +1,44 @@
# -*- encoding:utf-8 -*-
def postprocess(data):
"""转换字典中的值为列表,如果所有键对应的值都是'/', '{}''未知'"""
for key, value in data.items():
"""递归地转换字典中的值为列表,如果所有键对应的值都是'/', '{}''未知'"""
def convert_dict(value):
# 如果所有值是'/', '{}' 或 '未知'
if all(v in ['/', '未知', {}] for v in value.values()):
data[key] = list(value.keys())
return data
return list(value.keys())
else:
# 如果不满足条件,则递归处理嵌套的字典
return {k: convert_dict(v) if isinstance(v, dict) else v for k, v in value.items()}
# 递归处理顶层数据
return {key: convert_dict(val) if isinstance(val, dict) else val for key, val in data.items()}
# 示例数据
data = {
"第一包.耗材": {
"服务器": "未知",
"台式计算机": "未知",
"便携式计算机": "/",
"信息安全设备": {},
"喷墨打印机": "/",
"激光打印机": "/",
"针式打印机": "/",
"液晶显示器": "/",
"扫描仪": "/",
"基础软件": "/",
"信息安全软件": "/",
"复印机": "/",
"投影仪": "/",
"多功能一体机": "/",
"触控一体机": "/",
"碎纸机": "/",
"复印纸": "/"
"第一包": {
"办公电子设备": {
"技术参数或采购要求": "1、服务器、台式计算机、便携式计算机、信息安全设备、喷墨打印机、激光打印机、针式打印机、液晶显示器、扫描仪、基础软件、信息安全软件、复印机、投影仪、多功能一体机、触控一体机、碎纸机、复印纸 2、相关要求供应商必须在市内有固定的经营场所并提供相关经营场所的房产证明材料自有场所要求提供房产证不动产证等证明文件、租赁场所要求提供房产租赁合同等证明文件。供应商注册地不在湖北省内的应在项目地设立分支机构并提供相关证明材料以工商营业执照和财政监管部门核实或备案证明材料为准。所投货物应满足国家的强制性标准执行有关政府采购政策符合国家相关产业政策合法销售、原厂原装、全新产品。在质保期内严格执行“三包”服务规定提供设备标准现场保修、技术支持服务及备品、备件支持服务。安装的任何零配件必须是其投标货物制造商原产或是经其认可的产品。3、报价要求投标人的投标报价是基于市场实际成交价的基础上给予的优惠价格。每项货物内容只允许有一个报价。投标文件中的报价为投标人对采购单位提供该项货物的最高限价且低于投标人市场成交的最低价。严格依据招标文件要求和我方投标文件的承诺按中标价格优惠承诺向采购单位提供服务。不实行任何形式的区域限制不在框架协议内容之外提出任何附加条款。全面履行投标承诺圆满完成采购单位的相关定点服务工作确保质量提供快捷、方便、满意的服务。",
"数量": "采购清单中未具体指定数量"
},
"软件及耗材": {
"服务器": "/",
"台式计算机": "/",
"便携式计算机": "/",
"信息安全设备": "/",
"喷墨打印机": "/",
"激光打印机": "/",
"针式打印机": "/",
"液晶显示器": "/",
"扫描仪": "/",
"基础软件": "/",
"信息安全软件": "/",
"复印机": "/",
"投影仪": "/",
"多功能一体机": "/",
"触控一体机": "/",
"碎纸机": "/",
"复印纸": "/"
}
}
}

View File

@ -9,71 +9,36 @@ from flask_app.main.json_utils import clean_json_string, combine_json_results
def generate_key_paths(data, parent_key=''):
key_paths = []
no_keys_added = True # 默认假设没有添加任何键
for key, value in data.items():
current_key = f"{parent_key}.{key}" if parent_key else key
if isinstance(value, dict):
if value:
# 检查字典中的值是否为字典、列表或字符串'未知'
contains_dict_list_or_unknown = any(isinstance(v, (dict, list)) or v == "未知" for v in value.values())
if contains_dict_list_or_unknown:
# 递归生成键路径
sub_paths = generate_key_paths(value, current_key)
if sub_paths:
# 如果子路径非空,则扩展
key_paths.extend(sub_paths)
else:
# 当前字典内部为空或值全为"未知"
key_paths.append(current_key)
else:
# 字典中所有值都不是字典、列表或"未知",添加当前键
key_paths.append(current_key)
# 递归调用,并更新 no_keys_added 状态
sub_paths, sub_no_keys_added = generate_key_paths(value, current_key)
key_paths.extend(sub_paths)
no_keys_added = no_keys_added and sub_no_keys_added
else:
# 空字典,直接添加键路径
# 空字典也视为未添加键
key_paths.append(current_key)
no_keys_added = False
elif isinstance(value, list):
# 列表类型,添加包含列表的键的路径
if value: # 只有当列表非空时才添加
# 列表只在非空时视为添加了键
if value:
key_paths.append(current_key)
elif value == "未知":
# 值为"未知",添加键路径
no_keys_added = False
else:
no_keys_added = False
elif value == "未知" or value == "" or value == "/":
# 处理为"未知"或空字符串
key_paths.append(current_key)
no_keys_added = False
else:
# 值不是字典、列表、"未知"或空字符串,也不添加到键路径
no_keys_added = True and no_keys_added # 只保持 True 如果之前所有键都未添加
return key_paths
def get_technical_requirements(truncate_file):
user_query1 = "这是一份货物标中采购要求部分的内容请告诉我需要采购的系统货物如果有采购清单请直接根据清单上的货物名称给出结果若没有采购清单你要从文中摘取需要采购的系统货物采购需求中可能包含层次关系如大系统中包含若干子系统你需要保留这种层次关系给出系统货物名称请以json格式返回外层键名为\"采购需求\",嵌套键名为对应的系统名称或货物名称,需与原文保持一致,无需给出采购数量和单位,如有未知内容,在对应键值处填\"未知\""
file_id = upload_file(truncate_file)
res = qianwen_long(file_id, user_query1)
print(res)
cleaned_res = clean_json_string(res)
keys_list = generate_key_paths(cleaned_res['采购需求']) # 提取需要采购的货物清单
user_query_template = "这是一份货物标中采购要求部分的内容,请你给出\"{}\"的技术参数或采购要求和数量请以json格式返回结果外层键名为\"{}\", 键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减。"
queries = []
for key in keys_list:
# 替换 user_query2 中的 "网络硬盘录像机" 为当前 key
new_query = user_query_template.format(key, key)
print(new_query)
queries.append(new_query)
results = multi_threading(queries, "", file_id, 2)
technical_requirements = []
if not results:
print("errror!未获得大模型的回答!")
else:
# 打印结果
for question, response in results:
technical_requirements.append(response)
technical_requirements_combined_res = combine_json_results(technical_requirements)
"""根据所有键是否已添加处理技术要求"""
# 更新原始采购需求字典
combine_and_update_results(cleaned_res['采购需求'], technical_requirements_combined_res)
final_res = postprocess(cleaned_res['采购需求'])
print("更新后的采购需求处理完成.")
# 输出最终的 JSON 字符串
json_string = json.dumps(final_res, ensure_ascii=False, indent=4)
return json_string
return key_paths, no_keys_added
def combine_and_update_results(original_data, updates):
def recursive_update(data, key, value):
@ -88,13 +53,53 @@ def combine_and_update_results(original_data, updates):
for key, value in updates.items():
recursive_update(original_data, key, value)
return original_data
def postprocess(data):
"""转换字典中的值为列表,如果所有键对应的值都是'/', '{}''未知'"""
for key, value in data.items():
"""递归地转换字典中的值为列表,如果所有键对应的值都是'/', '{}''未知'"""
def convert_dict(value):
# 如果所有值是'/', '{}' 或 '未知'
if all(v in ['/', '未知', {}] for v in value.values()):
data[key] = list(value.keys())
return data
return list(value.keys())
else:
# 如果不满足条件,则递归处理嵌套的字典
return {k: convert_dict(v) if isinstance(v, dict) else v for k, v in value.items()}
# 递归处理顶层数据
return {key: convert_dict(val) if isinstance(val, dict) else val for key, val in data.items()}
def get_technical_requirements(truncate_file):
user_query1 = "这是一份货物标中采购要求部分的内容请告诉我需要采购的系统货物如果有采购清单请直接根据清单上的货物名称给出结果若没有采购清单你要从文中摘取需要采购的系统货物采购需求中可能包含层次关系如大系统中包含若干子系统你需要保留这种层次关系给出系统货物名称请以json格式返回外层键名为\"采购需求\",嵌套键名为对应的系统名称或货物名称,需与原文保持一致,无需给出采购数量和单位,如有未知内容,在对应键值处填\"未知\""
file_id = upload_file(truncate_file)
res = qianwen_long(file_id, user_query1)
print(res)
cleaned_res = clean_json_string(res)
keys_list ,no_keys_added= generate_key_paths(cleaned_res['采购需求']) # 提取需要采购的货物清单
if no_keys_added:
final_res = postprocess(cleaned_res['采购需求'])
else:
user_query_template = "这是一份货物标中采购要求部分的内容,请你给出\"{}\"的技术参数或采购要求和数量请以json格式返回结果外层键名为\"{}\", 键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减。"
queries = []
for key in keys_list:
# 替换 user_query2 中的 "网络硬盘录像机" 为当前 key
new_query = user_query_template.format(key, key)
print(new_query)
queries.append(new_query)
results = multi_threading(queries, "", file_id, 2)
technical_requirements = []
if not results:
print("errror!未获得大模型的回答!")
else:
# 打印结果
for question, response in results:
technical_requirements.append(response)
technical_requirements_combined_res = combine_json_results(technical_requirements)
"""根据所有键是否已添加处理技术要求"""
# 更新原始采购需求字典
combine_and_update_results(cleaned_res['采购需求'], technical_requirements_combined_res)
final_res = postprocess(cleaned_res['采购需求'])
print("更新后的采购需求处理完成.")
# 输出最终的 JSON 字符串
json_string = json.dumps(final_res, ensure_ascii=False, indent=4)
return json_string
def test_all_files_in_folder(input_folder, output_folder):
# 确保输出文件夹存在
if not os.path.exists(output_folder):
@ -120,7 +125,7 @@ def test_all_files_in_folder(input_folder, output_folder):
if __name__ == "__main__":
truncate_file="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\招标文件(107国道)_procurement.pdf"
truncate_file="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\招标文件(2)_procurement.pdf"
res=get_technical_requirements(truncate_file)
print(res)
# input_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1"

View File

@ -2,7 +2,7 @@ import json
from flask_app.货物标.货物标截取pdf import truncate_pdf_main
from flask_app.main.format_change import docx2pdf, pdf2docx
from flask_app.货物标.技术服务商务要求提取 import get_technical_requirements
#获取采购清单
def fetch_purchasing_list(file_path,output_folder,file_type):
@ -15,7 +15,8 @@ def fetch_purchasing_list(file_path,output_folder,file_type):
else:
print("未传入指定格式的文件!")
return None
truncate_path=truncate_pdf_main(pdf_path,output_folder,1)
truncate_file=truncate_pdf_main(pdf_path,output_folder,1)
tech_reqs=get_technical_requirements(truncate_file)
if __name__ == "__main__":
output_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\货物标output"

View File

@ -184,7 +184,7 @@ def truncate_pdf_multiple(input_path, output_folder):
return truncate_files
if __name__ == "__main__":
input_path = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\招标文件(107国道).pdf"
input_path = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\招标文件(2).pdf"
output_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1"
truncate_pdf_multiple(input_path,output_folder)
# selection = 1 # 例如1 - 投标人须知前附表, 2 - 评标办法, 3 - 投标人须知正文 4-招标公告-合同条款前