From 4393452f5220c605569e3e77a442de45fbeb5f65 Mon Sep 17 00:00:00 2001 From: zy123 <646228430@qq.com> Date: Fri, 13 Sep 2024 16:05:16 +0800 Subject: [PATCH] 9.13 --- flask_app/main/start_up.py | 3 +- flask_app/货物标/test.py | 58 +++++++---- flask_app/货物标/技术服务商务要求提取.py | 125 ++++++++++++----------- flask_app/货物标/提取采购需求main.py | 5 +- flask_app/货物标/货物标截取pdf.py | 2 +- 5 files changed, 106 insertions(+), 87 deletions(-) diff --git a/flask_app/main/start_up.py b/flask_app/main/start_up.py index 956c8d4..e6a2594 100644 --- a/flask_app/main/start_up.py +++ b/flask_app/main/start_up.py @@ -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) diff --git a/flask_app/货物标/test.py b/flask_app/货物标/test.py index 14102b9..9bd85c0 100644 --- a/flask_app/货物标/test.py +++ b/flask_app/货物标/test.py @@ -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、报价要求:投标人的投标报价是基于市场实际成交价的基础上给予的优惠价格。每项货物内容只允许有一个报价。投标文件中的报价为投标人对采购单位提供该项货物的最高限价,且低于投标人市场成交的最低价。严格依据招标文件要求和我方投标文件的承诺,按中标价格优惠承诺向采购单位提供服务。不实行任何形式的区域限制,不在框架协议内容之外,提出任何附加条款。全面履行投标承诺,圆满完成采购单位的相关定点服务工作,确保质量,提供快捷、方便、满意的服务。", + "数量": "采购清单中未具体指定数量" + }, + "软件及耗材": { + "服务器": "/", + "台式计算机": "/", + "便携式计算机": "/", + "信息安全设备": "/", + "喷墨打印机": "/", + "激光打印机": "/", + "针式打印机": "/", + "液晶显示器": "/", + "扫描仪": "/", + "基础软件": "/", + "信息安全软件": "/", + "复印机": "/", + "投影仪": "/", + "多功能一体机": "/", + "触控一体机": "/", + "碎纸机": "/", + "复印纸": "/" + } } } diff --git a/flask_app/货物标/技术服务商务要求提取.py b/flask_app/货物标/技术服务商务要求提取.py index 01562fb..4a0c28e 100644 --- a/flask_app/货物标/技术服务商务要求提取.py +++ b/flask_app/货物标/技术服务商务要求提取.py @@ -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" diff --git a/flask_app/货物标/提取采购需求main.py b/flask_app/货物标/提取采购需求main.py index 6cef1cd..2bcb324 100644 --- a/flask_app/货物标/提取采购需求main.py +++ b/flask_app/货物标/提取采购需求main.py @@ -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" diff --git a/flask_app/货物标/货物标截取pdf.py b/flask_app/货物标/货物标截取pdf.py index ff5e417..4928b4d 100644 --- a/flask_app/货物标/货物标截取pdf.py +++ b/flask_app/货物标/货物标截取pdf.py @@ -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-招标公告-合同条款前