Merge branch 'develop' into 12-12-testdoubao

This commit is contained in:
zy123 2024-12-12 18:03:21 +08:00
commit c77ada480c
9 changed files with 108 additions and 32 deletions

View File

@ -3,11 +3,15 @@ import os
from PyPDF2 import PdfReader, PdfWriter
#合并PDF
def merge_pdfs(paths, output_path):
# 检查是否所有路径都是空字符串或仅包含空白字符
if not any(path.strip() for path in paths):
return ""
pdf_writer = PdfWriter()
last_page_text = None # 用于存储上一个PDF的最后一页的文本
for path in paths:
# 跳过空字符串或无效路径
# 跳过空字符串或仅包含空白字符的路径
if not path.strip():
continue
try:
@ -17,25 +21,34 @@ def merge_pdfs(paths, output_path):
# 如果这不是第一个文件,并且有上一个文件的最后一页文本
if last_page_text is not None and len(pages) > 0:
current_first_page_text = pages[0].extract_text() if pages[0].extract_text() else ""
current_first_page_text = pages[0].extract_text() or ""
# 比较当前文件的第一页和上一个文件的最后一页的文本
if current_first_page_text == last_page_text:
start_index = 1 # 如果相同,跳过当前文件的第一页
# 添加当前PDF的页面到写入器
for page in range(start_index, len(pages)):
pdf_writer.add_page(pages[page])
for page_num in range(start_index, len(pages)):
pdf_writer.add_page(pages[page_num])
# 更新 last_page_text 为当前PDF的最后一页的文本
if len(pages) > 0:
last_page_text = pages[-1].extract_text() if pages[-1].extract_text() else ""
last_page_text = pages[-1].extract_text() or ""
except Exception as e:
print(f"文件 '{path}' 无法处理,错误: {e}")
continue
# 如果没有添加任何页面,返回空字符串
if len(pdf_writer.pages) == 0:
return ""
# 写入合并后的PDF到文件
try:
with open(output_path, 'wb') as out:
pdf_writer.write(out)
return output_path
except Exception as e:
print(f"无法写入输出文件,错误: {e}")
return ""
def judge_file_exist(original_path, new_suffix):
# 提取目录路径和原始文件名

View File

@ -213,12 +213,18 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
return DEFAULT_EVALUATION_REVIEW.copy()
def run_first_query(file_path):
print("判断有无评分")
# 上传文件并获取文件ID
file_id = upload_file(file_path)
# 定义用户查询
query = (
"根据该文档,你判断它是否有关于技术评分或商务评分或投标报价的具体的评分及要求,如果有,返回'',否则返回''"
"""根据该文档,你判断它是否有关于技术评分或商务评分或投标报价的具体的评分及要求如果有,返回'',否则返回''
要求与指南
1. 竞争性磋商文件通常无评分要求
2. 评分要求主要以表格形式呈现且会有评分因素及评分要求
3. 仅返回''''不需要其他解释或内容
"""
) # 应对竞争性谈判这种无评分要求的情况
# 执行查询
@ -232,15 +238,20 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
请以 JSON 格式返回结果最外层键名为 '技术评分''商务评分' '投标报价评分'在每大项下用键值对表示具体评分项键为具体的评审因素若评审因素存在嵌套表格中存在层级请使用嵌套键值对表示外层键名为主评审因素嵌套的子评审因素作为内层键名最内键值为列表列表中包含描述评分及要求的字典每个字典的键包括
'评分'具体得分或定性指标 '合格制'无评分时可删去'评分'键值对
'要求'说明评分标准
若这三大项评分中存在额外信息不属于某个评审因素即该大项评分的整体要求在该评分项内部新增键名为'备注' 值为该要求请勿擅自添加不属于'评审因素'的键名
若这三大项评分中存在额外信息不属于某个评审因素即该大项评分的整体要求在该评分项内部新增键名为'备注'
要求与指南
1. 请首先定位评分细则的表格不要回答有关资格审查的内容也不要从评标办法正文中提取回答
2. 你无需将表格的单元格内的内容进行拆分需要将它视为一个整体
3. '评分'的键值不能是一个范围数字'0-5分'应该是一个具体数字'5分'或者是一个定性的指标如'合格制'
4. 如果该招标活动有多个包则最外层键名为对应的包名,否则最外层键名为各大评分项
5. 若表格中商务和技术评分混合一起请你手动将它们区别商务评分通常包含'售后服务''质量保证''业绩''企业人员''企业信用'等商务因素
6. 若表中的评分大项不是这三个请你根据语义分别映射到'技术评分''商务评分''投标报价评分'而不必严格按照表格中的名称若大项的'xx评分'要求未在文中说明则键名'xx评分'的键值设为'本项目无xx评分项'例如"技术评分":"本项目无技术评分项"
5. 若表格中商务和技术评分混合一起请根据实际表格内容进行准确分类
6. 若表中的评分大项不是这三个请你根据语义分别映射到'技术评分''商务评分''投标报价评分'而不必严格按照表格中的名称
7. 若大项的'xx评分'要求未在文中说明则键名'xx评分'的键值设为'本项目无xx评分项'例如"技术评分":"本项目无技术评分项"
禁止内容
1. 确保所有输出内容均基于提供的实际招标文件内容除了最外层的三个评分大项名称不使用任何预设的示例作为回答
2. 不得擅自添加不属于评审因素的键名以及 `'备注'` 之外的其他键名
以下为示例输出仅供格式参考
{
@ -305,15 +316,20 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
请以 JSON 格式返回结果最外层键名为 '技术评分''商务评分' '投标报价评分'在每大项下用键值对表示具体评分项键为具体的评审因素若评审因素存在嵌套表格中存在层级请使用嵌套键值对表示外层键名为主评审因素嵌套的子评审因素作为内层键名最内键值为列表列表中包含描述评分及要求的字典每个字典的键包括
'评分'具体得分或定性指标 '合格制'无评分时可删去'评分'键值对
'要求'说明评分标准
若这三大项评分中存在额外信息不属于某个评审因素即该大项评分的整体要求在该评分项内部新增键名为'备注' 值为该要求请勿擅自添加不属于'评审因素'的键名
若这三大项评分中存在额外信息不属于某个评审因素即该大项评分的整体要求在该评分项内部新增键名为'备注'值为该要求
要求与指南
1. 请首先定位评分细则的表格不要回答有关资格审查的内容也不要从评标办法正文中提取回答
2. 你无需将表格的单元格内的内容进行拆分需要将它视为一个整体
3. '评分'的键值不能是一个范围数字'0-5分'应该是一个具体数字'5分'或者是一个定性的指标如'合格制'
4. 如果该招标活动有多个包则最外层键名为对应的包名,否则最外层键名为各大评分项
5. 若表格中商务和技术评分混合一起请你手动将它们区别商务评分通常包含'售后服务''质量保证''业绩''企业人员''企业信用'等商务因素
6. 若表中的评分大项不是这三个请你根据语义分别映射到'技术评分''商务评分''投标报价评分'而不必严格按照表格中的名称若大项的'xx评分'要求未在文中说明则键名'xx评分'的键值设为'本项目无xx评分项'例如"技术评分":"本项目无技术评分项"
5. 若表格中商务和技术评分混合一起请根据实际表格内容进行准确分类
6. 若表中的评分大项不是这三个请你根据语义分别映射到'技术评分''商务评分''投标报价评分'而不必严格按照表格中的名称
7. 若大项的'xx评分'要求未在文中说明则键名'xx评分'的键值设为'本项目无xx评分项'例如"技术评分":"本项目无技术评分项"
禁止内容
1. 确保所有输出内容均基于提供的实际招标文件内容除了最外层的三个评分大项名称不使用任何预设的示例作为回答
2. 不得擅自添加不属于评审因素的键名以及 `'备注'` 之外的其他键名
以下为示例输出仅供格式参考
{
@ -389,7 +405,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
# 执行 user_query 相关的逻辑
return run_second_qeury(file_id)
else:
judge_res,file_id=run_first_query(invalid_path)
judge_res,file_id=run_first_query(invalid_path) #调用
if '' in judge_res:
# 执行 user_query 相关的逻辑
return run_second_qeury(file_id)
@ -407,8 +423,8 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
if __name__ == "__main__":
start_time=time.time()
# truncate_file=r"C:\Users\Administrator\Desktop\招标文件-采购类\tmp2\2024-新疆-塔城地区公安局食药环分局快检实验室项目_evaluation_method.pdf"
evaluation_method_path = r'C:\Users\Administrator\Desktop\招标文件\output2\zbtest7_evaluation_method.pdf'
invalid_path=r'C:\Users\Administrator\Desktop\招标文件\output2\zbtest7_evaluation_method.pdf'
evaluation_method_path = r'C:\Users\Administrator\Desktop\fsdownload\91399aa4-1ee8-447d-a05b-03cd8d15ced5\ztbfile_evaluation_method.pdf'
invalid_path=r'C:\Users\Administrator\Desktop\fsdownload\91399aa4-1ee8-447d-a05b-03cd8d15ced5\ztbfile_invalid.pdf'
# truncate_file = "C:\\Users\\Administrator\\Desktop\\货物标\\output2\\2-招标文件统计局智能终端二次招标_evaluation_method.pdf"
# truncate_file="C:\\Users\\Administrator\\Desktop\\货物标\\output2\\广水市妇幼招标文件最新W改_evaluation_method.pdf"
# truncate_file = "C:\\Users\\Administrator\\Desktop\\fsdownload\\2d481945-1f82-45a5-8e56-7fafea4a7793\\ztbfile_evaluation_method.pdf"

View File

@ -75,7 +75,7 @@ def preprocess_files(output_folder, downloaded_file_path, file_type,unique_id,lo
merged_baseinfo_path=truncate_files[-1]
more_path=[merged_baseinfo_path,tobidders_notice]
merged_baseinfo_path_more=os.path.join(output_folder,"merged_baseinfo_path_more.pdf")
merge_pdfs(more_path,merged_baseinfo_path_more)
merged_baseinfo_path_more=merge_pdfs(more_path,merged_baseinfo_path_more)
clause_path = convert_clause_to_json(tobidders_notice, output_folder) # 投标人须知正文条款pdf->json
end_time=time.time()
logger.info(f"文件预处理 done耗时{end_time - start_time:.2f}")

View File

@ -274,6 +274,10 @@ def goods_bid_main(output_folder, file_path, file_type, unique_id):
#TODO:小解析考虑提速1直接pdf转文本再切分。后期考虑。
#TODO: ec7d5328-9c57-450f-baf4-2e5a6f90ed1d
#TODO:1.先截取合同、投标文件格式之前的页码 即 invalid 如果页码小于50页那么剩下的不切了直接仍。
# 2.废标项这边,考虑大模型+正则并用
# 3.限制评分项的因素。
#商务标这里改为列表最里层
#good_list 金额 截取上下文
if __name__ == "__main__":

View File

@ -289,7 +289,7 @@ def fetch_specific_pdf(output_folder):
if baseinfo_found and pdf_paths:
# 如果找到了 merged_baseinfo.pdf 和其他文件,则进行合并
output_path = os.path.join(output_folder, "merged_reviews.pdf")
merge_pdfs(pdf_paths, output_path)
output_path=merge_pdfs(pdf_paths, output_path)
return output_path
else:
# 如果未找到 merged_baseinfo.pdf 且没有 invalid.pdf 匹配

View File

@ -495,8 +495,18 @@ def truncate_pdf_main(input_path, output_folder, selection):
def truncate_pdf_multiple(input_path, output_folder, unique_id="123"):
global logger
logger = get_global_logger(unique_id)
# 新增逻辑:检查 PDF 总页数
try:
reader = PdfReader(input_path)
num_pages = len(reader.pages)
logger.info(f"PDF '{input_path}' 的总页数为: {num_pages}")
if num_pages <= 50:
logger.info(f"PDF页数小于或等于50页跳过切分逻辑。")
return ['', '', '', '', '', '', '']
except Exception as e:
logger.error(f"无法读取 PDF 页数: {e}")
return ['', '', '', '', '', '', '']
base_file_name = os.path.splitext(os.path.basename(input_path))[0] # 纯文件名
truncate_files = []
selections = range(1, 6) # 选择 1 到 5
@ -545,8 +555,17 @@ def truncate_pdf_multiple(input_path, output_folder, unique_id="123"):
def truncate_pdf_specific_engineering(pdf_path, output_folder, selections, unique_id="123"):
try:
global logger
logger = get_global_logger(unique_id)
try:
reader = PdfReader(input_path)
num_pages = len(reader.pages)
logger.info(f"PDF '{input_path}' 的总页数为: {num_pages}")
if num_pages <= 50:
logger.info(f"PDF页数小于或等于50页跳过切分逻辑。")
return ['', '', '', '']
except Exception as e:
logger.error(f"无法读取 PDF 页数: {e}")
return ['', '', '', '']
base_file_name = os.path.splitext(os.path.basename(pdf_path))[0]
truncate_files = []
@ -598,14 +617,14 @@ def truncate_pdf_specific_engineering(pdf_path, output_folder, selections, uniqu
if __name__ == "__main__":
start_time = time.time()
# input_path = r"C:\Users\Administrator\Desktop\new招标文件\工程标"
input_path=r"C:\Users\Administrator\Desktop\fsdownload\ec7d5328-9c57-450f-baf4-2e5a6f90ed1d\ztbfile.pdf"
input_path=r"C:\Users\Administrator\Desktop\fsdownload\91399aa4-1ee8-447d-a05b-03cd8d15ced5\西藏监管局办.pdf"
# input_path = "C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\2-招标文件.pdf"
# input_path=r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
output_folder = r"C:\Users\Administrator\Desktop\fsdownload\ec7d5328-9c57-450f-baf4-2e5a6f90ed1d\tmp"
output_folder = r"C:\Users\Administrator\Desktop\fsdownload\91399aa4-1ee8-447d-a05b-03cd8d15ced5\tmp"
files=truncate_pdf_multiple(input_path,output_folder)
print(files)
# selections = [4, 1] # 仅处理 selection 4、1
# files=truncate_pdf_specific_engineering(input_path,output_folder,selections)
print(files)
# selection = 2 # 例如1 - 投标人须知前附表+正文, 2 - 评标办法, 3 -资格审查条件 4-招标公告 5-无效标
# generated_files = truncate_pdf_main(input_path, output_folder, selection)
# print(generated_files)

View File

@ -70,7 +70,7 @@ def combine_review_standards(evaluation_method, qualification_path, output_folde
print("call 资格审查main(货物标)")
paths=[qualification_path,evaluation_method]
more_qualification_path=os.path.join(output_folder,"merged_qualification.pdf")
merge_pdfs(paths,more_qualification_path)
more_qualification_path=merge_pdfs(paths,more_qualification_path)
final_result=combine_qualification_review(invalid_path,more_qualification_path,notice_path)
else:
tobidders_notice_table_docx = pdf2docx(tobidders_notice_table) # 投标人须知前附表转docx

View File

@ -7,7 +7,7 @@ import os # 用于文件和文件夹操作
from flask_app.general.clean_pdf import clean_page_content, extract_common_header
from flask_app.general.format_change import docx2pdf
from flask_app.general.merge_pdfs import merge_and_cleanup, merge_pdfs, merge_selected_pdfs_for_goods
from flask_app.general.merge_pdfs import merge_and_cleanup, merge_selected_pdfs_for_goods
import concurrent.futures
@ -685,6 +685,18 @@ def process_input(input_path, output_folder, selection, output_suffix):
def truncate_pdf_multiple(pdf_path, output_folder, logger):
# 新增逻辑:检查 PDF 总页数
try:
reader = PdfReader(pdf_path)
num_pages = len(reader.pages)
logger.info(f"PDF '{pdf_path}' 的总页数为: {num_pages}")
if num_pages <= 50:
logger.info(f"PDF页数小于或等于50页跳过切分逻辑。")
return ['', '', '', '', '', '', '']
except Exception as e:
logger.error(f"无法读取 PDF 页数: {e}")
return ['', '', '', '', '', '', '']
base_file_name = os.path.splitext(os.path.basename(pdf_path))[0]
truncate_files = []
@ -738,6 +750,17 @@ def truncate_pdf_specific_goods(pdf_path, output_folder, selections, unique_id="
list: 截取的文件路径列表包括合并后的文件路径如果有
"""
logger = get_global_logger(unique_id)
# 新增逻辑:检查 PDF 总页数
try:
reader = PdfReader(pdf_path)
num_pages = len(reader.pages)
logger.info(f"PDF '{pdf_path}' 的总页数为: {num_pages}")
if num_pages <= 50:
logger.info(f"PDF页数小于或等于50页跳过切分逻辑。")
return ['', '', '', '']
except Exception as e:
logger.error(f"无法读取 PDF 页数: {e}")
return ['', '', '', '']
base_file_name = os.path.splitext(os.path.basename(pdf_path))[0]
truncate_files = []
@ -788,9 +811,9 @@ if __name__ == "__main__":
input_path=r"C:\Users\Administrator\Desktop\fsdownload\ff2acdba-3a55-48a7-aa7a-61d9f89b909a\ztbfile.pdf"
output_folder = r"C:\Users\Administrator\Desktop\fsdownload\ff2acdba-3a55-48a7-aa7a-61d9f89b909a\tmp"
# output_folder = r"C:\Users\Administrator\Desktop\new招标文件\output2"
files = truncate_pdf_multiple(input_path, output_folder,logger)
# selections = [3,5]
# files=truncate_pdf_specific_goods(input_path,output_folder,selections)
# files = truncate_pdf_multiple(input_path, output_folder,logger)
selections = [1,4]
files=truncate_pdf_specific_goods(input_path,output_folder,selections)
print(files)
# selection = 2 # 例如1 - 公告, 2 - 评标办法, 3 - 资格审查后缀有qualification1或qualification2与评标办法一致 4.投标人须知前附表part1 投标人须知正文part2 5-采购需求
# generated_files = truncate_pdf_main(input_path, output_folder, selection)

View File

@ -382,6 +382,7 @@ def get_technical_requirements(invalid_path,processed_filepath):
processed_data=truncate_system_keys(cleaned_res['采购需求'])
key_paths, grouped_paths, good_list, data_copy= generate_key_paths(processed_data) # 提取需要采购的货物清单 key_list交通监控视频子系统.高清视频抓拍像机 ... grouped_paths是同一系统下同时有'交换机-1'和'交换机-2',提取'交换机' 输出eg:{'交通标志.标志牌铝板', '交通信号灯.交换机'}
modified_data=rename_keys(data_copy)
print(json.dumps(modified_data,ensure_ascii=False,indent=4))
user_query_template = """请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。请以 JSON 格式返回结果,键名为\"{}\",键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求或功能说明的字符串,请按原文内容回答,保留三角▲、五角★和序号,不可擅自增删内容,尤其是不可擅自添加序号。
要求与指南
@ -526,8 +527,8 @@ def test_all_files_in_folder(input_folder, output_folder):
if __name__ == "__main__":
start_time=time.time()
# truncate_file="C:\\Users\\Administrator\\Desktop\\fsdownload\\469d2aee-9024-4993-896e-2ac7322d41b7\\ztbfile_procurement.docx"
truncate_docfile=r"C:\Users\Administrator\Desktop\new招标文件\货物标\HBDL-2024-0481-001-招标文件.docx"
truncate_file=r'C:\Users\Administrator\Desktop\new招标文件\货物标\HBDL-2024-0481-001-招标文件.pdf'
truncate_docfile=r"C:\Users\Administrator\Desktop\fsdownload\6b7ea51f-eb6d-4a4f-a518-dc1f57d27ea1\ztbfile.docx"
truncate_file=r'C:\Users\Administrator\Desktop\fsdownload\6b7ea51f-eb6d-4a4f-a518-dc1f57d27ea1\省考试院院内电子屏采购.pdf'
# invalid_path="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile.pdf"
# truncate_file="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile_procurement.docx"
# output_folder="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\tmp"