diff --git a/flask_app/general/little_zbparse.py b/flask_app/general/little_zbparse.py index 34dd212..3513a47 100644 --- a/flask_app/general/little_zbparse.py +++ b/flask_app/general/little_zbparse.py @@ -14,6 +14,7 @@ from flask_app.货物标.基础信息解析main import aggregate_basic_info_good from flask_app.货物标.货物标截取pdf import truncate_pdf_specific_goods from flask_app.main.截取pdf import truncate_pdf_specific_engineering from flask_app.main.post_processing import inner_post_processing +from flask_app.main.基础信息整合 import aggregate_basic_info_engineering def get_global_logger(unique_id): if unique_id is None: @@ -24,52 +25,70 @@ def get_global_logger(unique_id): logger = None -def merge(merged): - guarantee_key = '是否递交投标保证金' if '是否递交投标保证金' in merged else '是否递交磋商保证金' - if merged.get(guarantee_key) == '是': - return 1,"" - elif merged.get(guarantee_key) == '否': - guarantee_type = '投标' if '投标' in guarantee_key else '磋商' - merged[f'{guarantee_type}保证金'] = '不提交' - merged[f'退还{guarantee_type}保证金'] = '/' - merged.pop(guarantee_key, None) - return 0,merged - -def get_goods_baseinfo(baseinfo_file_path): - file_id = upload_file(baseinfo_file_path) - baseinfo_file_path='flask_app/static/提示词/基本信息货物标.txt' - # baseinfo_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\基本信息货物标.txt' - questions = read_questions_from_file(baseinfo_file_path) - more_query = "请你根据招标文件信息,回答以下问题:是否需要递交投标保证金(或磋商保证金)?请按json格式给我提供信息,键名分为'是否递交投标保证金'(或'是否递交磋商保证金'),键值仅限于'是','否','未知',若存在矛盾信息,请回答'未知'。" - questions.append(more_query) - baseinfo_results = multi_threading(questions, "", file_id, 2) # 1代表使用百炼rag 2代表使用qianwen-long - baseinfo_list = [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else [] - type,merged=merge(baseinfo_list.pop()) - if type: - judge_questions=["根据招标文件第二章投标人须知,该项目投标保证金(或磋商保证金)的内容或要求是什么?请按json格式给我提供信息,外层键名为'投标保证金'(或'磋商保证金'),若需要以嵌套键值对返回结果,那么嵌套键名为你对相应要求的总结,而对应键值需要完全与原文保持一致。"] - res2 = multi_threading(judge_questions, "", file_id, 2) # 调用千问-long - if not res2: - print("基础信息整合: multi_threading error!") - else: - for question, response in res2: - baseinfo_list.append(clean_json_string(response)) - else: - baseinfo_list.append(merged) - return baseinfo_list - -def get_engineering_baseinfo(baseinfo_file_path): - return [] - #货物标 -def little_parse_goods(output_folder,file_path): - files=truncate_pdf_specific_goods(file_path,output_folder) - baseinfo_list=get_goods_baseinfo(files[-1]) +def little_parse_goods(output_folder, file_path): + """ + 解析货物相关的基础信息。 + + 参数: + output_folder (str): 输出文件夹路径。 + file_path (str): 输入文件的路径。 + + 返回: + dict: 包含 '基础信息' 的字典。 + """ + # 截取特定的货物 PDF 文件 + files = truncate_pdf_specific_goods(file_path, output_folder) + if not files: + raise ValueError("未找到截取后的文件。") + # 假设最后一个文件是需要处理的基础信息文件 + baseinfo_file_path = files[-1] + # 上传文件并获取文件 ID + file_id = upload_file(baseinfo_file_path) + # 注意:以下路径被硬编码,确保该路径存在并且正确 + # baseinfo_prompt_file_path='flask_app/static/提示词/小解析基本信息货物标.txt' + baseinfo_prompt_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\小解析基本信息货物标.txt' + # 从提示词文件中读取问题 + questions = read_questions_from_file(baseinfo_prompt_file_path) + # 多线程处理问题,使用指定的处理模式(2 代表使用 qianwen-long) + baseinfo_results = multi_threading(questions, "", file_id, 2) + # 清理 JSON 字符串 + baseinfo_list = [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else [] + # 聚合基础信息 aggregated_baseinfo = aggregate_basic_info_goods(baseinfo_list) return {"基础信息": aggregated_baseinfo} -def little_parse_engineering(output_folder,file_path): - files=truncate_pdf_specific_engineering(file_path,output_folder) - baseinfo_list=get_engineering_baseinfo(files[-1]) - aggregated_baseinfo = aggregate_basic_info_goods(baseinfo_list) + + +def little_parse_engineering(output_folder, file_path): + """ + 解析工程相关的基础信息。 + + 参数: + output_folder (str): 输出文件夹路径。 + file_path (str): 输入文件的路径。 + + 返回: + dict: 包含 '基础信息' 的字典。 + """ + # 截取特定的工程 PDF 文件 + files = truncate_pdf_specific_engineering(file_path, output_folder) + if not files: + raise ValueError("未找到截取后的文件。") + # 假设最后一个文件是需要处理的基础信息文件 + baseinfo_file_path = files[-1] + # 上传文件并获取文件 ID + file_id = upload_file(baseinfo_file_path) + # 注意:以下路径被硬编码,确保该路径存在并且正确 + baseinfo_prompt_file_path='flask_app/static/提示词/小解析基本信息工程标.txt' + # baseinfo_prompt_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\小解析基本信息工程标.txt' + # 从提示词文件中读取问题 + questions = read_questions_from_file(baseinfo_prompt_file_path) + # 多线程处理问题,使用指定的处理模式(2 代表使用 qianwen-long) + baseinfo_results = multi_threading(questions, "", file_id, 2) + # 清理 JSON 字符串 + baseinfo_list = [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else [] + # 聚合基础信息 + aggregated_baseinfo = aggregate_basic_info_engineering(baseinfo_list) return {"基础信息": aggregated_baseinfo} def little_parse_main(output_folder, file_path, file_type,zb_type,unique_id): @@ -121,11 +140,15 @@ def little_parse_main(output_folder, file_path, file_type,zb_type,unique_id): return json_path if __name__ == "__main__": - output_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\little_parse_output" start_time = time.time() file_type = 2 # 1:docx 2:pdf 3:其他 - zb_type=2 #1:工程标 2:货物标 - input_file = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\ztbfile.pdf" + # output_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\little_parse_output" + # zb_type=2 #1:工程标 2:货物标 + # input_file = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\ztbfile.pdf" + + output_folder="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output" + zb_type=1 + input_file="C:\\Users\\Administrator\\Desktop\\招标文件\\招标test文件夹\\zbtest2.pdf" final_json_path=little_parse_main(output_folder, input_file, file_type, zb_type,"122334") with open(final_json_path, 'r', encoding='utf-8') as f: logger.info('final_json_path:' + final_json_path) diff --git a/flask_app/main/post_processing.py b/flask_app/main/post_processing.py index 7a8e479..a804d0f 100644 --- a/flask_app/main/post_processing.py +++ b/flask_app/main/post_processing.py @@ -4,6 +4,7 @@ import re def inner_post_processing(base_info): + print(json.dumps(base_info,ensure_ascii=False,indent=4)) """ 处理 '基础信息' 部分,提取所需字段。 @@ -123,7 +124,7 @@ def inner_post_processing(base_info): bidder_contact = get_nested(base_info, ["招标人/代理信息", "招标人联系方式"], {}) # 定义候选键列表,按优先级排序 - name_candidates = ["名称", "联系人", "招标"] + name_candidates = ["联系人","名称", "招标"] phone_candidates = ["电话", "手机", "联系方式"] # 提取 '联系人' @@ -210,114 +211,70 @@ def outer_post_processing(combined_data, includes): if __name__ == "__main__": combined_data={ "基础信息": { - "招标人/代理信息": { - "招标人": "湖北广水农村商业银行股份有限公司", - "招标人联系方式": { - "名称": "湖北广水农村商业银行股份有限公司", - "联系电话": "18771377804", - "地址": "广水市永阳大道 46号" - }, - "招标代理机构": "湖北兴立众工程咨询有限责任公司", - "招标代理机构联系方式": { - "名称": "湖北兴立众工程咨询有限责任公司", - "联系电话": "0722-6239009", - "地址": "广水市永阳大道 40号" - }, - "项目联系方式": { - "名称": "付女士", - "联系电话": "0722-6239009" - } + "招标人/代理信息": { + "招标人": "黄石临空建设管理有限公司", + "招标人联系方式": { + "名称": "黄石临空建设管理有限公司", + "地址": "大冶市还地桥镇", + "联系人": "王先生", + "电话": "13545510946", + "传真": "未知", + "电子邮件": "未知", + "网址": "未知", + "开户银行": "未知", + "账号": "未知" }, - "项目信息": { - "项目名称": "广水农商行门禁控制主机及基础验证设备采购项目(三次)", - "项目编号": "HBXLZ-2023-CS001", - "项目概况": "广水农商行门禁控制主机及基础验证设备采购项目(三次)的潜在供应商应在广水市永阳大道 40号六楼获取采购文件,2023年 5月 23日 9点 00分(北京时间)前提交响应文件。", - "项目基本情况": { - "项目编号": "HBXLZ-2023-CS001", - "项目名称": "广水农商行门禁控制主机及基础验证设备采购项目(三次)", - "采购方式": "竞争性磋商", - "预算金额": "51万元", - "最高限价": "51万元", - "采购需求": "采购监控中心平台 1套、安全门禁 82套,采购内容包括所需货物的生产、运输、安装、调试、检验以及售后服务等全部相关工作,详细技术参数及其它详见竞争性磋商文件第五部分采购要求及内容。", - "合同履行期限": "60日历天", - "本项目(是/否)接受联合体投标": "否" - }, - "招标控制价": "51万元", - "投标竞争下浮率": "未知", - "是否接受联合体投标": "否", - "分包": "不允许" - }, - "采购要求": { - "技术要求": { - "门禁管理系统": { - "门禁控制器": { - "技术参数": "1.系统采用 CS架构,支持 Web端登录,支持远程软硬件重启升级、维护、管理。2.★支持 TCP/IP、4G、RS485联网方式、有线与无线(WIFI)可自动切换 ,控制器支持百台到上千台设备组网,需满足大楼多门点的管理数量要求。3.★安装方式支持壁挂安装。4.★支持卡、密码、首卡、双卡、主卡/副卡、胁迫码、多卡分组、指纹识别+中心确认等开门方式。全面支持读卡器、指纹、人脸、指静脉、RS485识读设备的混合接入。5.支持胁迫报警、门未关妥报警、门被外力开起报警、开门等待超时报警、黑名单报警、非法卡超次报警、短信报警转发等功能。6.自动数据同步和断网断点数据补传,设备与服务器之间的数据可以自动同步,无论是设备上传状态事件信息还是服务器下载人员、权限数据等都支持网络恢复后自动补传,断点续传。7.★高性能、高安全性,符合国家标准 4级的要求,并提供公安部检测证明。8.★采用 ARM9 32位处理器,RAM:128MB,卡片容量:≥200000张卡片,支持脱机运行,脱机事件记录:≥1000000条,断电状态记录可保存 10年。9.开放 SKD,具有二次开发接口协议能力。10.★所投产品需提供公安部检测报告并加盖鲜章。", - "数量": "82" - }, - "出门按钮": { - "技术参数": "1)标准 86底盒安装方式,支持常开,常闭方式 2)结构:塑料面板 3)性能:最大耐电流 1.25A电压 250V", - "数量": "82" - }, - "单门电磁锁": { - "技术参数": "1)通电上锁,断电开锁,开门时间可调节。2)稳定性强,连续工作锁体无故障,使用更安全。3)安装方便、噪音低、寿命长、无剩磁、无机械故障,质保 3年起。4)★带门磁,具有信号反馈功能和指示灯指示。5)参数:开锁电压:DC12V,工作电流:450mA,0-255秒延时可调,额定拉力:280KG,工作环境:温度-10~+55℃,湿度 0~95%。6)★所投产品需提供公安部检测报告并加盖鲜章。", - "数量": "82" - }, - "指纹仪": { - "技术参数": "1.先进半导体传感器,全面领先于普通光学识别技术,更好的判别假指纹、湿指、污损破皮手指。2.直观的 LCD液晶显示及语音验证提示,配针孔摄像机,实现视频联动抓拍,手动布撤防,实现与监控中心门禁系统实现对讲(外置语音盒)。3.支持 IC卡、指纹、卡加密码、编号多种组合验证方式。4.辨识率和校正、容错性能强,支持脱机运行和联网运行。5.支持指纹仪离线、非法指纹、胁迫指纹报警,具有防止恶意使用报警功能。技术参数:比对方式:1:N或 1:1,识别速度:< 2s(1000枚指纹 1:N)/射频卡识别< 150ms,采集时间:1s,存储容量:1000枚指纹,安全等级:1-5 级可调,分辨率:508dpi,认假率<0.001%(安全等级为 3时),拒真率:<1.0%(安全等级为 3时),工作电压:DC 12V,工作电流:500mA,工作环境:温度-20℃~55℃、湿度 10%~95%,尺寸规格: 197mm(L)×97mm(W)×40mm(D)。6.★所投产品需提供公安部检测报告并加盖鲜章。", - "数量": "82" - }, - "门禁服务器": { - "技术参数": "CPU:1颗 intel至强系列处理器,核数≥12核,主频≥2.2GHz 内存:32G*2 DDR4,16根内存插槽,最大支持扩展至 2TB内存 硬盘:4块 600G 10K 2.5寸 SAS硬盘 阵列卡:SAS_HBA卡,支持 RAID 0/1/10 PCIE扩展:最大可支持 6个 PCIE扩展插槽 网口:2个千兆电口 其他接口:1个 RJ45管理接口,后置 2个 USB 3.0 接口,前置 2个 USB2.0接口,1个 VGA接口电源: 标配 550W(1+1)高效铂金 CRPS冗余电源", - "数量": "1" - } - } - }, - "商务要求": "", - "服务要求": { - "全国联保": "产品需全国联保,享受三包服务,保修期:3年。", - "通讯加密": "通过网络抓包工具,对软件与设备之间的通讯进行抓包,加密前为明码,加密后为乱码。提供公安部检测报告复印件加盖原厂鲜章证明。", - "自动数据同步": "设备可脱机使用(不联网),设备联网后可自动同步数据。", - "扩展功能": "系统扩展性能良好,可提供详尽的数据接口、DLL动态链接库及相关数据接口说明文件,包括样板程序,方便用户二次开发。", - "门禁系统标准": "门禁系统必须满足公安部 GA38-2021文件标准中对银行业的要求。", - "高性能高安全性": "高性能、高安全性,符合国家标准 4级的要求,并提供公安部检测证明。", - "开放SDK": "开放 SKD,具有二次开发接口协议能力。", - "公安部检测报告": "所投产品需提供公安部检测报告并加盖鲜章。" - }, - "其他要求": "" - }, - "关键时间/内容": { - "投标文件递交截止日期": "2023年5月23日 9点00分", - "投标文件递交地点": "广水市应山府华美不动产隔壁", - "开标时间": "2023年 5月 23日 9点 00分", - "开标地点": "广水市应山府华美不动产隔壁", - "澄清招标文件的截止时间": "未知", - "投标有效期": "提交首次响应文件截止时间后 90日历天", - "信息公示媒介": "中国政府采购网:http://www.ccgp.gov.cn" - }, - "保证金相关": { - "是否提交履约保证金": "未知", - "是否递交磋商保证金": "未知", - "是否递交投标保证金": "未知", - "质量保证金": "未知" - }, - "其他信息": { - "投标费用承担": "供应商应自行承担所有与参加磋商有关的费用。不论磋商的结果如何,招标人和采购代理机构在任何情况下均无义务和责任承担这些费用。", - "招标代理服务费": { - "收费标准": "招标代理服务费金额按原国家计委计价格[2002]1980号 《招标代理服务收费管理暂行办法》和国家发展与改革委员会办公厅发改办价格[2003]857号文所规定的收费标准计取。" - }, - "是否退还投标文件": "否", - "是否召开投标预备会": "未知", - "是否召开投标答疑会": "未知", - "偏离": { - "定义": "技术参数响应及偏离表是响应性文件的一部分,供应商须对本次采购项目要求的技术性能逐项作出实质性响应。", - "要求": "供应商必须保证其提供的相关资质证明文件的真实性、合法性、时效性,否则,磋商小组将不予推荐。", - "允许偏离项": "未知", - "偏离处理": "响应性文件应对竞争性磋商文件中各项做出实质性响应,否则该磋商将可能被拒绝。", - "其他": "供应商服务承诺书应按不低于竞争性磋商文件中的服务要求标准做出响应。" - }, - "踏勘现场": "不组织" + "招标代理机构": "湖北民成工程项目管理有限公司", + "招标代理机构联系方式": { + "名称": "湖北民成工程项目管理有限公司", + "地址": "大冶市港湖还建楼 20栋二单元 102室", + "联系人": "尹工", + "电话": "18327823905", + "传真": "未知", + "电子邮件": "未知", + "网址": "未知", + "开户银行": "未知", + "账号": "未知" } }, + "项目信息": { + "项目名称": "黄石临空区银山公益公墓(迁坟区)二期工程", + "招标编号": "冶招[2021]450号", + "项目概况": { + "建设地点": "大冶市还地桥镇下堰村和煤矿村交界处", + "建设规模": "招标文件及施工图纸、工程量清单全部范围", + "其他": "未知" + }, + "招标范围": { + "招标范围": "招标文件及施工图纸、工程量清单全部范围", + "标段划分": "未知", + "计划工期": "180日历天", + "招标控制价": "4364303元" + }, + "招标控制价": "4364303元", + "投标竞争下浮率": "未提供" + }, + "关键时间/内容": { + "投标文件递交截止日期": "未知", + "投标文件递交方式": "未提供", + "开标时间": "投标文件递交截止时间", + "开标地点": "未知", + "投标人要求澄清招标文件的截止时间": "未提供", + "投标有效期": "未提供", + "评标结果公示媒介": "黄石公共资源交易信息网、大冶政府网(招投标板块)" + }, + "保证金相关": { + "投标保证金额": "4.3万元", + "质量保证金": "未提供", + "退还投标保证金": "未提供" + }, + "其他信息": { + "重新招标、不再招标和终止招标": "未提供", + "投标费用承担": "未提供", + "招标代理服务费": "未提供", + "是否退还投标文件": "未提供" + } +}, "投标文件要求": { "响应性文件的编写": { "响应性文件的组成": { diff --git a/flask_app/main/start_up.py b/flask_app/main/start_up.py index 8f7c652..fb0b2ab 100644 --- a/flask_app/main/start_up.py +++ b/flask_app/main/start_up.py @@ -127,7 +127,7 @@ def validate_request(default_zb_type=1): return jsonify({'error': 'Invalid zb_type provided'}), 400 return file_url, zb_type - +#提取采购需求 @app.route('/procurement_reqs', methods=['POST']) def get_procurement_reqs(): logger = g.logger @@ -153,6 +153,7 @@ def get_procurement_reqs(): logger.error('Exception occurred: ' + str(e)) # 使用全局 logger 记录 return jsonify({'error': str(e)}), 500 +#提取采购需求 def download_and_process_file_for_procurement(file_url): logger = g.logger unique_id = g.unique_id diff --git a/flask_app/main/判断是否分包等.py b/flask_app/main/判断是否分包等.py index c827271..a1cbde3 100644 --- a/flask_app/main/判断是否分包等.py +++ b/flask_app/main/判断是否分包等.py @@ -4,34 +4,47 @@ import os.path import re from flask_app.main.json_utils import extract_content_from_json # 可以选择性地导入特定的函数 from flask_app.main.提取打勾符号 import read_pdf_and_judge_main -from flask_app.main.通义千问 import qianwen_ask +from flask_app.main.多线程提问 import multi_threading from flask_app.main.通义千问long import qianwen_long,upload_file #调用qianwen-ask之后,组织提示词问百炼。 def construct_judge_questions(json_data): - # 使用 extract_content_from_json 提取和解析 JSON 数据 - parsed_data = extract_content_from_json(json_data) - if not parsed_data: - return "" + """ + 根据提供的 JSON 数据,生成一个问题列表。每个问题针对一个值为 '未知' 的键, + 要求以 JSON 格式提供该键的值,仅限于 '是', '否', '未知'。 - question_keys = [] - for key, value in parsed_data.items(): - if value == '未知': - question_keys.append(f"'{key}'") + Args: + json_data (str or dict): 输入的 JSON 数据,可以是 JSON 字符串或字典。 + Returns: + list: 包含生成的问题的列表。如果没有符合条件的键,则返回空列表。 + """ + # 如果 json_data 是字符串,尝试将其解析为字典 + if isinstance(json_data, str): + try: + parsed_data = json.loads(json_data) + except json.JSONDecodeError: + print("输入的 json_data 不是有效的 JSON 字符串。") + return [] + elif isinstance(json_data, dict): + parsed_data = json_data + else: + print("输入的 json_data 必须是 JSON 字符串或字典。") + return [] + # 提取值为 '未知' 的键 + question_keys = [key for key, value in parsed_data.items() if value == '未知'] + # 如果没有符合条件的键,返回空列表 if not question_keys: - return "" - - # 移除单引号后的键名列表字符串 - questions_without_quotes = ', '.join(key.strip("'") for key in question_keys) # 移除单引号 - - if not questions_without_quotes: # 检查 questions_without_quotes 是否为空 - return "" - - keys_str = ",".join(question_keys) - question = f"请你依据文档中的信息回答,{questions_without_quotes}?请按json格式给我提供信息,键名分别为{keys_str},键值仅限于'是','否','未知'。" - - return question + return [] + # 生成问题列表 + questions = [] + for key in question_keys: + question = ( + f"请你根据投标人须知前附表中的信息回答,本项目{key}," + f"请按json格式给我提供信息,键名为'{key}',键值仅限于'是','否','未知',如果原文中对应内容处为'/'或者'\',键值填'否'。" + ) + questions.append(question) + return questions def merge_json_to_list(merged): @@ -122,34 +135,35 @@ def read_questions_from_judge(file_path, indices): def judge_whether_main(file_path,output_folder): #传入招标文件中‘投标人须知前附表’ user_query1 = "请你依据以上信息,回答以下问题:是否组织踏勘现场?是否召开投标预备会?是否允许偏离?是否退还投标文件?是否允许分包? 是否需要递交投标保证金?是否需要提交履约保证金(履约担保)?是否有招标代理服务费?请按json格式给我提供信息,键名分别为'是否组织踏勘现场','是否召开投标预备会','是否允许偏离','是否退还投标文件',是否允许分包','是否递交投标保证金','是否提交履约保证金','是否有招标代理服务费',键值仅限于'是','否','未知',若存在矛盾信息,请回答'未知'。" - output_json_path = os.path.join(output_folder,'judge_exist.json') - read_pdf_and_judge_main(file_path, output_json_path) #提取打勾符号 - qianwen_answer = qianwen_ask(output_json_path, user_query1) # 调用普通千问判断是、否、未知 - user_query2 = construct_judge_questions(qianwen_answer) # 提取回答为”未知“的键 + output_txt_path = os.path.join(output_folder,'judge_exist.txt') + read_pdf_and_judge_main(file_path, output_txt_path) #提取打勾符号 + file_id=upload_file(output_txt_path) + qianwen_answer=qianwen_long(file_id,user_query1) + user_querys = construct_judge_questions(extract_content_from_json(qianwen_answer)) # 提取回答为”未知“的键 # 判断user_query2是否为空 - if user_query2: + if user_querys: file_id = upload_file(file_path) - res = qianwen_long(file_id, user_query2) #整个前附表一起传问千问long - return process_judge_content(qianwen_answer, res) + qianwen_results = multi_threading(user_querys, "", file_id, 2) # 1代表使用百炼rag 2代表使用qianwen-long + qianwen_list = [extract_content_from_json(res) for _, res in qianwen_results] if qianwen_results else [] #整个前附表一起传问千问long + return process_judge_content(qianwen_answer, qianwen_list) else: print("正常现象,没有'未知',无需调用qianwen-long") original = extract_content_from_json(qianwen_answer) return merge_json_to_list(original) - -def process_judge_content(original_json, update_json): #用新的数据合并旧数据 +def process_judge_content(original_json, qianwen_list): #用新的数据合并旧数据 """Process judging content by merging updates into the original JSON data.""" original = extract_content_from_json(original_json) - updates = extract_content_from_json(update_json) - original.update(updates) + for i in qianwen_list: + original.update(i) return merge_json_to_list(original) if __name__ == "__main__": - file_path="C:\\Users\\Administrator\\Desktop\\fsdownload\\temp8\\a95a9a0a-f2dd-4007-b849-6b0a1a4c2b91\\ztbfile_tobidders_notice_table.pdf" - output_dir="C:\\Users\\Administrator\\Desktop\\fsdownload\\temp8\\a95a9a0a-f2dd-4007-b849-6b0a1a4c2b91\\output" + file_path="C:\\Users\Administrator\\Desktop\\fsdownload\\ee2d8828-bae0-465a-9171-7b2dd7453251\\ztbfile_tobidders_notice_table.pdf" + output_dir='C:\\Users\Administrator\\Desktop\\fsdownload\\ee2d8828-bae0-465a-9171-7b2dd7453251\\tmp' chosen_numbers, merged=judge_whether_main(file_path,output_dir) print(chosen_numbers) print(merged) diff --git a/flask_app/main/基础信息整合.py b/flask_app/main/基础信息整合.py index d7c5b4f..a05cf0d 100644 --- a/flask_app/main/基础信息整合.py +++ b/flask_app/main/基础信息整合.py @@ -7,7 +7,7 @@ from flask_app.main.多线程提问 import read_questions_from_file, multi_threa from flask_app.main.通义千问long import upload_file -def aggregate_basic_info(baseinfo_list): +def aggregate_basic_info_engineering(baseinfo_list): """ 将基础信息列表中的数据进行合并和分类。 @@ -114,8 +114,8 @@ def combine_basic_info(knowledge_name, truncate0, output_folder, clause_path): - dict: 综合后的基础信息。 """ baseinfo_list = [] - baseinfo_file_path = 'flask_app/static/提示词/前两章提问总结.txt' - # baseinfo_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\前两章提问总结.txt' + baseinfo_file_path = 'flask_app/static/提示词/基本信息工程标.txt' + # baseinfo_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\基本信息工程标.txt' questions = read_questions_from_file(baseinfo_file_path) res1 = multi_threading(questions, knowledge_name) @@ -156,7 +156,7 @@ def combine_basic_info(knowledge_name, truncate0, output_folder, clause_path): rebidding_situation = extract_from_notice(clause_path, 3) # "重新招标, 不再招标和终止招标"需从投标人须知正文提取 update_json = rename_outer_key(rebidding_situation, "重新招标、不再招标和终止招标") baseinfo_list.append(update_json) - aggregated_baseinfo = aggregate_basic_info(baseinfo_list) # 现在是一个字典 + aggregated_baseinfo = aggregate_basic_info_engineering(baseinfo_list) # 现在是一个字典 return {"基础信息": aggregated_baseinfo} if __name__ == "__main__": diff --git a/flask_app/main/多线程提问.py b/flask_app/main/多线程提问.py index f3dca74..5438deb 100644 --- a/flask_app/main/多线程提问.py +++ b/flask_app/main/多线程提问.py @@ -285,7 +285,7 @@ def multi_threading(queries, knowledge_name="", file_id="", llm_type=1): if __name__ == "__main__": start_time=time.time() # # 读取问题列表 - baseinfo_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\前两章提问总结.txt' + baseinfo_file_path = '/flask_app/static/提示词/基本信息工程标.txt' questions =read_questions_from_file(baseinfo_file_path) knowledge_name = "招标解析5word" llm_type=1 diff --git a/flask_app/main/截取pdf.py b/flask_app/main/截取pdf.py index 639f40b..d764627 100644 --- a/flask_app/main/截取pdf.py +++ b/flask_app/main/截取pdf.py @@ -398,10 +398,10 @@ def truncate_pdf_specific_engineering(pdf_path, output_folder): if __name__ == "__main__": # input_path = "C:\\Users\\Administrator\\Desktop\\fsdownload\\4bda9fde-89fc-4e5e-94a4-ce6c43010f74\\ztbfile.pdf" # output_folder = "C:\\Users\\Administrator\\Desktop\\fsdownload\\4bda9fde-89fc-4e5e-94a4-ce6c43010f74" - input_path="C:\\Users\\Administrator\\Desktop\\招标文件\\招标03.pdf" + input_path="C:\\Users\\Administrator\\Desktop\\招标文件\\招标test文件夹\\zbtest16.pdf" output_folder="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output" - files=truncate_pdf_multiple(input_path,output_folder) - # files=truncate_pdf_specific(input_path,output_folder) + # files=truncate_pdf_multiple(input_path,output_folder) + files=truncate_pdf_specific_engineering(input_path,output_folder) print(files) # selection = 3 # 例如:1 - 投标人须知前附表, 2 - 评标办法, 3 - 投标人须知正文 4-资格审查条件 5-招标公告 6-无效标 # generated_files = truncate_pdf_main(input_path, output_folder, selection) diff --git a/flask_app/main/提取打勾符号.py b/flask_app/main/提取打勾符号.py index 625998a..554672c 100644 --- a/flask_app/main/提取打勾符号.py +++ b/flask_app/main/提取打勾符号.py @@ -53,7 +53,8 @@ def extract_key_value_pairs(text): results[key] = "无" # 为键赋值"无" return results -def read_pdf_and_judge_main(file_path, output_json_path): + +def read_pdf_and_judge_main(file_path, output_txt_path): with open(file_path, 'rb') as file: reader = PyPDF2.PdfReader(file) num_pages = len(reader.pages) @@ -62,22 +63,29 @@ def read_pdf_and_judge_main(file_path, output_json_path): page = reader.pages[page_num] text = page.extract_text() if page.extract_text() else "" # 使用正则表达式删除每页开头的页码,格式通常为“数字+空格” - cleaned_text = re.sub(r'^\d+\s+', '', text) - # print(cleaned_text) - - key_value_pairs = extract_key_value_pairs(cleaned_text) + text = re.sub(r'^\s*\d+\s*(?=\D)', '', text) # 删除开头的页码,仅当紧跟非数字字符时 + text = re.sub(r'\s+\d+\s*$', '', text) # 删除结尾的页码 + text = re.sub(r'\s*\/\s*\d+\s*', '', text) # 删除形如 /129 的页码 + key_value_pairs = extract_key_value_pairs(text) all_data.update(key_value_pairs) - # 和有区别吗   - # 将所有数据保存为 JSON 文件 - with open(output_json_path, "w", encoding="utf-8") as json_file: - json.dump(all_data, json_file, ensure_ascii=False, indent=4) - print(f"da_gou signal: Data extraction complete and saved to '{output_json_path}'.") + # 将所有数据保存为 TXT 文件 + with open(output_txt_path, "w", encoding="utf-8") as txt_file: + for idx, (key, value) in enumerate(all_data.items()): + if idx == 0: + line = f'"{key}": "{value}",\n' + else: + line = f'"{key}": "{value}",\n' + txt_file.write(line) + + print(f"da_gou signal: Data extraction complete and saved to '{output_txt_path}'.") + + if __name__ == "__main__": # 示例调用 - file_path ="C:\\Users\\Administrator\\Desktop\\fsdownload\\temp8\\a95a9a0a-f2dd-4007-b849-6b0a1a4c2b91\\ztbfile_tobidders_notice_table.pdf" + file_path ="C:\\Users\Administrator\\Desktop\\fsdownload\\ee2d8828-bae0-465a-9171-7b2dd7453251\\ztbfile_tobidders_notice_table.pdf" # file_path="C:\\Users\\Administrator\\Desktop\\货物标\\output\ztb_20240903100337\\ztb_20240903100337_14-20.pdf" - output_json_path = 'judge_exist.json' - read_pdf_and_judge_main(file_path, output_json_path) + output_txt_path = 'C:\\Users\Administrator\\Desktop\\fsdownload\\ee2d8828-bae0-465a-9171-7b2dd7453251\\tmp\\judge_exist.txt' + output_path=read_pdf_and_judge_main(file_path, output_txt_path) diff --git a/flask_app/static/提示词/前两章提问总结.txt b/flask_app/static/提示词/基本信息工程标.txt similarity index 100% rename from flask_app/static/提示词/前两章提问总结.txt rename to flask_app/static/提示词/基本信息工程标.txt diff --git a/flask_app/static/提示词/小解析基本信息工程标.txt b/flask_app/static/提示词/小解析基本信息工程标.txt new file mode 100644 index 0000000..37de833 --- /dev/null +++ b/flask_app/static/提示词/小解析基本信息工程标.txt @@ -0,0 +1,15 @@ +1.该招标文件的项目名称(或工程名称)是?招标编号(或项目编号)是?招标人是?招标代理机构是?请按json格式给我提供信息,键名分别是'项目名称','招标编号','招标人','招标代理机构',若存在未知信息,在对应的键值中填'未知'。 + +2.该招标文件的工程概况(或项目概况)是?招标范围是?请按json格式给我提供信息,键名分别为'项目概况','招标范围',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,若存在未知信息,在对应的键值中填'未知'。 + +3.该招标文件的招标控制价(或投标限价或预算金额或合同估算价,但非监理费用)是?请按json格式给我提供信息,键名为'招标控制价',若存在未知信息,在对应的键值中填'未知'。 + +4.投标文件递交截止日期是?请按json格式给我提供信息,键名是'投标文件递交截止日期',若存在未知信息,在对应的键值中填'未知'。 + +5.招标人和招标代理机构的联系方式是?请按json格式给我提供信息,键名分别是'招标人联系方式','招标代理机构联系方式',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,若存在未知信息,在对应的键值中填'未知'。 + +6.该招标文件的评标结果(或相关信息)公示媒介在哪?请按json格式给我提供信息,键名是'评标结果公示媒介',若存在未知信息,在对应的键值中填'未知'。 + +7.该项目的开标时间(或开启时间)和开标地点是?请按json格式给我提供信息,键名为'开标时间'和'开标地点',若原文中没有明确的开标时间,请回答投标文件递交的截止时间,若存在未知信息,在对应的键值中填'未知'。 + +8.请你根据招标文件信息,投标人需要递交的投标保证金(或磋商保证金)是多少?请按json格式给我提供信息,键名为'投标保证金额',键值为原文中的具体金额,如果不需要递交保证金或者金额未知,键值为"其他"。 \ No newline at end of file diff --git a/flask_app/static/提示词/小解析基本信息货物标.txt b/flask_app/static/提示词/小解析基本信息货物标.txt new file mode 100644 index 0000000..fb30fce --- /dev/null +++ b/flask_app/static/提示词/小解析基本信息货物标.txt @@ -0,0 +1,33 @@ +1.该招标文件的项目名称是?项目编号(或招标编号)是?采购人(或招标人)是?采购代理机构(或招标代理机构)是?请按json格式给我提供信息,键名分别是'项目名称','项目编号','招标人','招标代理机构',若存在未知信息,在对应的键值中填'未知'。 + +2.该招标文件的项目概况是?项目基本情况是?请按json格式给我提供信息,键名分别为'项目概况','项目基本情况',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,而嵌套键值必须与原文保持一致,若存在未知信息,在对应的键值中填'未知'。 + +3.该招标文件的最高限价(或招标控制价或预算金额)是?请按json格式给我提供信息,键名为'招标控制价',若存在未知信息,在对应的键值中填'未知'。 + +4.投标文件(或响应文件)递交截止时间是?请按json格式给我提供信息,键名是'投标文件递交截止日期',若存在未知信息,在对应的键值中填'未知'。 + +5.采购人(招标人)和采购代理机构(或招标代理机构)和项目的联系方式是?请按json格式给我提供信息,外层键名分别是'招标人联系方式','招标代理机构联系方式',"项目联系方式",嵌套键名至少包含"名称"和"联系电话",若还有其他字段则添加在后面,若存在未知信息,在对应的键值中填'未知'。示例输出如下: +{ + "招标人联系方式":{ + "名称":"广水市中医医院", + "联系电话":"13972990000", + "地址":"洪山街道" + }, + "招标代理机构联系方式":{ + "名称":"湖北众恒永业工程项目管理有限公司广水分公司", + "联系电话":"13972991234" + }, + "项目联系方式":{ + "名称":"张三", + "联系电话":"未知" + } +} + +6.该招标文件的信息公示媒介在哪?请按json格式给我提供信息,键名是'信息公示媒介',若存在未知信息,在对应的键值中填'未知'。 + +7.该项目的开标时间(或开启时间)和开标地点是?请按json格式给我提供信息,键名为'开标时间'和'开标地点',若存在未知信息,在对应的键值中填'未知'。 + +8.请你根据招标文件信息,投标人需要递交的投标保证金(或磋商保证金)是多少?请按json格式给我提供信息,键名为'投标保证金额',键值为原文中的具体金额的完整表述,如果不需要递交保证金或者金额未知,键值为"其他"。 + + +