1.3 修改bug
This commit is contained in:
parent
ced16ca2db
commit
65a7ddf1b8
@ -1,8 +1,8 @@
|
|||||||
import re
|
import re
|
||||||
from PyPDF2 import PdfReader
|
from PyPDF2 import PdfReader
|
||||||
|
|
||||||
def extract_common_header(pdf_path):
|
|
||||||
|
|
||||||
|
def extract_common_header(pdf_path):
|
||||||
def get_headers(pdf_document, start_page, pages_to_read):
|
def get_headers(pdf_document, start_page, pages_to_read):
|
||||||
headers = []
|
headers = []
|
||||||
for i in range(start_page, min(start_page + pages_to_read, len(pdf_document.pages))):
|
for i in range(start_page, min(start_page + pages_to_read, len(pdf_document.pages))):
|
||||||
@ -14,32 +14,39 @@ def extract_common_header(pdf_path):
|
|||||||
headers.append(first_lines)
|
headers.append(first_lines)
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
def longest_common_prefix(strs):
|
|
||||||
if not strs:
|
|
||||||
return ""
|
|
||||||
# 找到最短的字符串长度
|
|
||||||
min_len = min(len(s) for s in strs)
|
|
||||||
if min_len == 0:
|
|
||||||
return ""
|
|
||||||
# 从第一个字符开始逐个比较
|
|
||||||
for i in range(min_len):
|
|
||||||
char = strs[0][i]
|
|
||||||
for s in strs[1:]:
|
|
||||||
if s[i] != char:
|
|
||||||
return strs[0][:i]
|
|
||||||
return strs[0][:min_len]
|
|
||||||
|
|
||||||
def find_common_headers(headers):
|
def find_common_headers(headers):
|
||||||
if not headers:
|
if not headers:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# 使用 zip 对齐所有页的对应行
|
# 转置,使得每一行对应所有页的同一行
|
||||||
|
transposed_headers = list(zip(*headers))
|
||||||
common_headers = []
|
common_headers = []
|
||||||
for lines in zip(*headers):
|
|
||||||
# 找到所有行的最长公共前缀
|
for lines in transposed_headers:
|
||||||
common_prefix = longest_common_prefix(lines)
|
# 将每行按空格分割成部分
|
||||||
if len(common_prefix) >= 5: # 可以根据实际情况调整最小长度
|
split_lines = [line.split() for line in lines]
|
||||||
common_headers.append(common_prefix)
|
|
||||||
|
# 找出所有行中最短的部分数
|
||||||
|
min_parts = min(len(parts) for parts in split_lines)
|
||||||
|
if min_parts == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
common_parts = []
|
||||||
|
for part_idx in range(min_parts):
|
||||||
|
# 获取当前部分在所有行中的值
|
||||||
|
current_parts = [parts[part_idx] for parts in split_lines]
|
||||||
|
# 检查所有部分是否相同
|
||||||
|
if all(part == current_parts[0] for part in current_parts[1:]):
|
||||||
|
common_parts.append(current_parts[0])
|
||||||
|
else:
|
||||||
|
break # 如果某部分不相同,停止进一步比较
|
||||||
|
|
||||||
|
if common_parts:
|
||||||
|
# 将共同的部分重新组合成字符串
|
||||||
|
common_header_line = ' '.join(common_parts)
|
||||||
|
if len(common_header_line) >= 5: # 可以根据实际情况调整最小长度
|
||||||
|
common_headers.append(common_header_line)
|
||||||
|
|
||||||
return common_headers
|
return common_headers
|
||||||
|
|
||||||
pdf_document = PdfReader(pdf_path)
|
pdf_document = PdfReader(pdf_path)
|
||||||
@ -89,6 +96,8 @@ def clean_page_content(text, common_header):
|
|||||||
if header_line.strip(): # 只处理非空行
|
if header_line.strip(): # 只处理非空行
|
||||||
# 替换首次出现的完整行
|
# 替换首次出现的完整行
|
||||||
text = re.sub(r'^' + re.escape(header_line.strip()) + r'\n?', '', text, count=1)
|
text = re.sub(r'^' + re.escape(header_line.strip()) + r'\n?', '', text, count=1)
|
||||||
|
# 预处理:删除文本开头的所有空白字符(包括空格、制表符等)
|
||||||
|
text = text.lstrip()
|
||||||
# 删除文本开头的“第x页”格式的页码
|
# 删除文本开头的“第x页”格式的页码
|
||||||
text = re.sub(r'^第\d+页\s*', '', text)
|
text = re.sub(r'^第\d+页\s*', '', text)
|
||||||
# 删除页码 eg:89/129 这个代码分三步走可以把89/129完全删除
|
# 删除页码 eg:89/129 这个代码分三步走可以把89/129完全删除
|
||||||
|
@ -227,6 +227,7 @@ def parse_json_with_duplicates(raw_string):
|
|||||||
print("未找到有效的 JSON 内容。")
|
print("未找到有效的 JSON 内容。")
|
||||||
return {} # 返回空字典
|
return {} # 返回空字典
|
||||||
|
|
||||||
|
#作为最后手段,因为它是统计{ }的数量,存在缺陷:如果字符串中包含'{ }' 会出错!
|
||||||
def extract_first_json(s):
|
def extract_first_json(s):
|
||||||
"""
|
"""
|
||||||
从字符串中提取第一个完整的 JSON 对象。如果 JSON 对象不完整,尝试补全缺失的括号。
|
从字符串中提取第一个完整的 JSON 对象。如果 JSON 对象不完整,尝试补全缺失的括号。
|
||||||
@ -327,7 +328,8 @@ def extract_content_from_json(input_string,flag=False):
|
|||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
print("方法3(非法转义修复)解析失败。")
|
print("方法3(非法转义修复)解析失败。")
|
||||||
# 所有方法均失败后,尝试使用 extract_first_json 作为最后手段
|
# 所有方法均失败后,尝试使用 extract_first_json 作为最后手段
|
||||||
print("尝试使用 extract_first_json 作为最后手段。")
|
print("尝试使用 extract_first_json 作为最后手段:")
|
||||||
|
print(input_string)
|
||||||
fixed_json_final = extract_first_json(input_string)
|
fixed_json_final = extract_first_json(input_string)
|
||||||
if fixed_json_final:
|
if fixed_json_final:
|
||||||
try:
|
try:
|
||||||
|
@ -116,13 +116,13 @@ if __name__ == "__main__":
|
|||||||
# pdf_path=r"C:\Users\Administrator\Desktop\货物标\zbfiles\094定稿-湖北工业大学轻武器模拟射击设备采购项目招标文件.pdf"
|
# pdf_path=r"C:\Users\Administrator\Desktop\货物标\zbfiles\094定稿-湖北工业大学轻武器模拟射击设备采购项目招标文件.pdf"
|
||||||
# pdf_path = r"C:\Users\Administrator\Desktop\货物标\zbfiles\zbtest4_evaluation_method.pdf"
|
# pdf_path = r"C:\Users\Administrator\Desktop\货物标\zbfiles\zbtest4_evaluation_method.pdf"
|
||||||
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件\招标02.pdf"
|
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件\招标02.pdf"
|
||||||
pdf_path=r"C:\Users\Administrator\Downloads\河北省承德监狱2025年供应站水果及干果采购项目招标文件(定).pdf"
|
pdf_path=r"C:\Users\Administrator\Desktop\工程\test\2022-广东-鹏华基金管理有限公司深圳深业上城办公室装修项目.pdf"
|
||||||
# input_path=r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
|
# input_path=r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
|
||||||
output_folder = r"C:\Users\Administrator\Desktop\货物\test"
|
output_folder = r"C:\Users\Administrator\Desktop\工程\test"
|
||||||
# selections = [1, 4] # 仅处理 selection 4、1
|
# selections = [1, 4] # 仅处理 selection 4、1
|
||||||
# selections = [1, 2, 3, 5]
|
# selections = [1, 2, 3, 5]
|
||||||
# files = truncate_pdf_multiple(pdf_path, output_folder, logger, 'goods', selections)
|
# files = truncate_pdf_multiple(pdf_path, output_folder, logger, 'goods', selections) #engineering
|
||||||
files = truncate_pdf_multiple(pdf_path, output_folder, logger, 'goods')
|
files = truncate_pdf_multiple(pdf_path, output_folder, logger, 'engineering')
|
||||||
print(files)
|
print(files)
|
||||||
# print(files[-1])
|
# print(files[-1])
|
||||||
# print(files[-2])
|
# print(files[-2])
|
||||||
|
@ -118,7 +118,7 @@ def save_extracted_text_to_txt(pdf_path, txt_path):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# file_path='D:\\flask_project\\flask_app\\static\\output\\output1\\648e094b-e677-47ce-9073-09e0c82af210\\ztbfile_tobidders_notice_part2.pdf'
|
# file_path='D:\\flask_project\\flask_app\\static\\output\\output1\\648e094b-e677-47ce-9073-09e0c82af210\\ztbfile_tobidders_notice_part2.pdf'
|
||||||
file_path=r"C:\Users\Administrator\Desktop\fsdownload\80286859-52da-4b29-8396-52b3d104c32b\ztbfile.pdf"
|
file_path=r"C:\Users\Administrator\Downloads\2024-福建-2024年度防汛抢险物资储备.pdf"
|
||||||
# file_path = r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
|
# file_path = r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
|
||||||
# file_path = 'C:\\Users\\Administrator\\Desktop\\货物标\\截取test\\交警支队机动车查验监管系统项目采购_tobidders_notice_part1.pdf'
|
# file_path = 'C:\\Users\\Administrator\\Desktop\\货物标\\截取test\\交警支队机动车查验监管系统项目采购_tobidders_notice_part1.pdf'
|
||||||
# file_path = "C:\\Users\\Administrator\\Desktop\\招标文件\\招标test文件夹\\zbtest8.pdf"
|
# file_path = "C:\\Users\\Administrator\\Desktop\\招标文件\\招标test文件夹\\zbtest8.pdf"
|
||||||
|
@ -4,9 +4,32 @@ import logging
|
|||||||
import re
|
import re
|
||||||
from flask_app.general.json_utils import clean_json_string
|
from flask_app.general.json_utils import clean_json_string
|
||||||
from flask_app.general.多线程提问 import multi_threading
|
from flask_app.general.多线程提问 import multi_threading
|
||||||
|
from flask_app.general.通义千问long import upload_file, qianwen_long
|
||||||
from flask_app.工程标.判断是否分包等 import read_questions_from_judge
|
from flask_app.工程标.判断是否分包等 import read_questions_from_judge
|
||||||
|
|
||||||
def process_judge_questions(judge_file_path, chosen_numbers, file_id, baseinfo_list1):
|
def get_deviation_requirements(invalid_path):
|
||||||
|
file_id=upload_file(invalid_path)
|
||||||
|
user_query="""该招标文件对响应文件(投标文件)偏离项的要求或内容是怎样的?请不要回答具体的技术参数,也不要回答具体的评分要求。请以json格式给我提供信息,外层键名为'偏离',若存在嵌套信息,嵌套内容键名为文件中对应字段或是你的总结,而嵌套键值必须与原文保持一致,若文中未涉及相关内容,在键值中填'未知'。
|
||||||
|
注意:不使用任何预设的示例作为回答,示例仅作为格式参考。
|
||||||
|
禁止内容:
|
||||||
|
确保所有输出内容均基于提供的实际招标文件内容,不使用任何预设的示例作为回答。
|
||||||
|
示例1,嵌套键值对情况:
|
||||||
|
{
|
||||||
|
"偏离":{
|
||||||
|
"技术要求":"以★标示的内容不允许负偏离",
|
||||||
|
"商务要求":"以★标示的内容不允许负偏离"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
示例2,无嵌套键值对情况:
|
||||||
|
{
|
||||||
|
"偏离":"所有参数需在技术响应偏离表内响应,如应答有缺项,且无有效证明材料的,评标委员会有权不予认可,视同负偏离处理"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
model_res=qianwen_long(file_id,user_query)
|
||||||
|
return clean_json_string(model_res)
|
||||||
|
|
||||||
|
def process_judge_questions(judge_file_path, chosen_numbers, invalid_path, baseinfo_list1):
|
||||||
|
file_id=upload_file(invalid_path)
|
||||||
judge_questions = read_questions_from_judge(judge_file_path, chosen_numbers)
|
judge_questions = read_questions_from_judge(judge_file_path, chosen_numbers)
|
||||||
judge_consortium = judge_consortium_bidding(baseinfo_list1)
|
judge_consortium = judge_consortium_bidding(baseinfo_list1)
|
||||||
if judge_consortium:
|
if judge_consortium:
|
||||||
@ -44,11 +67,10 @@ def aggregate_basic_info(baseinfo_list,mode="engineering"):
|
|||||||
"投标有效期",
|
"投标有效期",
|
||||||
"信息公示媒介"
|
"信息公示媒介"
|
||||||
],
|
],
|
||||||
"保证金相关": ["质量保证金"],
|
"保证金相关": [],
|
||||||
"其他信息": [
|
"其他信息": [
|
||||||
"重新招标、不再招标和终止招标",
|
"重新招标、不再招标和终止招标",
|
||||||
"投标费用承担",
|
"投标费用承担",
|
||||||
"招标代理服务费",
|
|
||||||
"是否退还投标文件",
|
"是否退还投标文件",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -114,16 +136,13 @@ def dynamic_key_handling(key_groups, detected_keys):
|
|||||||
# 确保"技术、服务要求"存在于"采购要求"组中
|
# 确保"技术、服务要求"存在于"采购要求"组中
|
||||||
if "技术、服务要求" not in key_groups["采购要求"]:
|
if "技术、服务要求" not in key_groups["采购要求"]:
|
||||||
key_groups["采购要求"].insert(1, "技术、服务要求")
|
key_groups["采购要求"].insert(1, "技术、服务要求")
|
||||||
# 处理“保证金相关”组,插到"质量保证金"前
|
# 处理“保证金相关”组
|
||||||
elif "保证金" in key:
|
elif "保证金" in key:
|
||||||
group = key_groups["保证金相关"]
|
if "保证金相关" not in key_groups:
|
||||||
insert_before = "质量保证金"
|
key_groups["保证金相关"] = []
|
||||||
if insert_before in group:
|
# 直接追加到 "保证金相关" 组的末尾
|
||||||
index = group.index(insert_before)
|
if key not in key_groups["保证金相关"]:
|
||||||
if key not in group: # 避免重复插入
|
key_groups["保证金相关"].append(key)
|
||||||
group.insert(index, key)
|
|
||||||
else:
|
|
||||||
group.append(key) # 如果没有找到特定键,则追加到末尾
|
|
||||||
elif "联合体" in key:
|
elif "联合体" in key:
|
||||||
key_groups["项目信息"].append(key)
|
key_groups["项目信息"].append(key)
|
||||||
elif "分包" in key:
|
elif "分包" in key:
|
||||||
|
@ -71,6 +71,7 @@ def preprocess_files(output_folder, file_path, file_type,logger):
|
|||||||
invalid_deleted_docx=pdf2docx(invalid_path)
|
invalid_deleted_docx=pdf2docx(invalid_path)
|
||||||
merged_baseinfo_path=truncate_files[-1]
|
merged_baseinfo_path=truncate_files[-1]
|
||||||
more_path=[merged_baseinfo_path,tobidders_notice]
|
more_path=[merged_baseinfo_path,tobidders_notice]
|
||||||
|
|
||||||
merged_baseinfo_path_more=os.path.join(output_folder,"merged_baseinfo_path_more.pdf")
|
merged_baseinfo_path_more=os.path.join(output_folder,"merged_baseinfo_path_more.pdf")
|
||||||
merged_baseinfo_path_more=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
|
clause_path = convert_clause_to_json(tobidders_notice, output_folder) # 投标人须知正文条款pdf->json
|
||||||
@ -83,7 +84,6 @@ def preprocess_files(output_folder, file_path, file_type,logger):
|
|||||||
'invalid_added_docx': invalid_added_docx,
|
'invalid_added_docx': invalid_added_docx,
|
||||||
'notice_path':notice_path,
|
'notice_path':notice_path,
|
||||||
'tobidders_notice_table': tobidders_notice_table,
|
'tobidders_notice_table': tobidders_notice_table,
|
||||||
'tobidders_notice': tobidders_notice,
|
|
||||||
'evaluation_method':evaluation_method,
|
'evaluation_method':evaluation_method,
|
||||||
'qualification': qualification,
|
'qualification': qualification,
|
||||||
'merged_baseinfo_path':merged_baseinfo_path,
|
'merged_baseinfo_path':merged_baseinfo_path,
|
||||||
@ -92,7 +92,7 @@ def preprocess_files(output_folder, file_path, file_type,logger):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# 基本信息
|
# 基本信息
|
||||||
def fetch_project_basic_info(invalid_deleted_docx, merged_baseinfo_path, merged_baseinfo_path_more, tobidders_notice, clause_path, logger):
|
def fetch_project_basic_info(invalid_deleted_docx, merged_baseinfo_path, merged_baseinfo_path_more,clause_path, logger):
|
||||||
logger.info("starting 基础信息...")
|
logger.info("starting 基础信息...")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
try:
|
try:
|
||||||
@ -100,9 +100,7 @@ def fetch_project_basic_info(invalid_deleted_docx, merged_baseinfo_path, merged_
|
|||||||
merged_baseinfo_path = invalid_deleted_docx
|
merged_baseinfo_path = invalid_deleted_docx
|
||||||
if not merged_baseinfo_path_more:
|
if not merged_baseinfo_path_more:
|
||||||
merged_baseinfo_path_more = invalid_deleted_docx
|
merged_baseinfo_path_more = invalid_deleted_docx
|
||||||
if not tobidders_notice:
|
basic_res = combine_basic_info(merged_baseinfo_path, merged_baseinfo_path_more, clause_path,invalid_deleted_docx)
|
||||||
tobidders_notice = invalid_deleted_docx
|
|
||||||
basic_res = combine_basic_info(merged_baseinfo_path, merged_baseinfo_path_more, tobidders_notice, clause_path)
|
|
||||||
result = basic_res
|
result = basic_res
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
logger.info(f"基础信息 done,耗时:{end_time - start_time:.2f} 秒")
|
logger.info(f"基础信息 done,耗时:{end_time - start_time:.2f} 秒")
|
||||||
@ -217,7 +215,7 @@ def engineering_bid_main(output_folder, file_path, file_type, unique_id):
|
|||||||
# 立即启动不依赖 knowledge_name 和 index 的任务
|
# 立即启动不依赖 knowledge_name 和 index 的任务
|
||||||
futures = {
|
futures = {
|
||||||
'base_info': executor.submit(fetch_project_basic_info,processed_data['invalid_deleted_docx'] ,processed_data['merged_baseinfo_path'],processed_data['merged_baseinfo_path_more'],
|
'base_info': executor.submit(fetch_project_basic_info,processed_data['invalid_deleted_docx'] ,processed_data['merged_baseinfo_path'],processed_data['merged_baseinfo_path_more'],
|
||||||
processed_data['tobidders_notice'], processed_data['clause_path'],logger),
|
processed_data['clause_path'],logger),
|
||||||
'qualification_review': executor.submit(fetch_qualification_review, processed_data['evaluation_method'],
|
'qualification_review': executor.submit(fetch_qualification_review, processed_data['evaluation_method'],
|
||||||
processed_data['qualification'], output_folder,
|
processed_data['qualification'], output_folder,
|
||||||
processed_data['tobidders_notice_table'],
|
processed_data['tobidders_notice_table'],
|
||||||
|
@ -35,13 +35,17 @@
|
|||||||
|
|
||||||
9.该招标文件中对投标人(或供应商)准备和参加投标活动中发生的费用是如何规定的?请以json的格式给我提供信息,键名是'投标费用承担',若存在未知信息,在对应的键值中填'未知'。
|
9.该招标文件中对投标人(或供应商)准备和参加投标活动中发生的费用是如何规定的?请以json的格式给我提供信息,键名是'投标费用承担',若存在未知信息,在对应的键值中填'未知'。
|
||||||
|
|
||||||
10.招标人(或招标代理机构)对招标文件的澄清(或答疑)的截止时间是?请以json的格式给我提供信息,键名是'澄清招标文件的截止时间',若存在未知信息,在对应的键值中填'未知'。
|
10.根据提供的实际招标文件内容,招标人(或招标代理机构)对招标文件的澄清(或答疑)的截止时间是?请以json的格式给我提供信息,键名是'澄清招标文件的截止时间',键值为原文中有关澄清截止时间的相关表述,不一定是明确的时间节点。
|
||||||
|
禁止内容:
|
||||||
|
确保所有输出内容均基于提供的实际招标文件内容,不使用任何预设的示例作为回答。
|
||||||
|
示例输出如下,仅供格式参考:
|
||||||
|
{
|
||||||
|
"澄清招标文件的截止时间":"在投标截止时间至少 20 个日历日前"
|
||||||
|
}
|
||||||
|
|
||||||
11.该文档要求扣留的质量保证金百分比是多少,请以json格式给我提供信息,键名为'质量保证金',如果没有则以'未知'填充。
|
11.该项目是否接受联合体投标?请按json格式给我提供信息,键名为'是否接受联合体投标','是否接受联合体投标'的键值仅限于'是'、'否'、'未知'。
|
||||||
|
|
||||||
12.该项目是否接受联合体投标?请按json格式给我提供信息,键名为'是否接受联合体投标','是否接受联合体投标'的键值仅限于'是'、'否'、'未知'。
|
12.该项目的开标时间(或开启时间)和开标地点(或开启地点、开启方式)是?请按json格式给我提供信息,键名为'开标时间'和'开标地点',键值为原文中相关内容的表述。
|
||||||
|
|
||||||
13.该项目的开标时间(或开启时间)和开标地点(或开启地点、开启方式)是?请按json格式给我提供信息,键名为'开标时间'和'开标地点',键值为原文中相关内容的表述。
|
|
||||||
对于'开标时间',若文中没有明确时间却有诸如'同投标截止时间'的表述,则将相关表述返回;若存在未知信息,在对应的键值中填'未知',
|
对于'开标时间',若文中没有明确时间却有诸如'同投标截止时间'的表述,则将相关表述返回;若存在未知信息,在对应的键值中填'未知',
|
||||||
示例输出如下,仅供格式参考:
|
示例输出如下,仅供格式参考:
|
||||||
{
|
{
|
||||||
@ -49,15 +53,4 @@
|
|||||||
"开标地点":"线上开标"
|
"开标地点":"线上开标"
|
||||||
}
|
}
|
||||||
|
|
||||||
13.该招标文件对响应文件(投标文件)偏离项的要求或内容是怎样的?请不要回答具体的技术参数,也不要回答具体的评分要求。请以json格式给我提供信息,外层键名为'偏离',若存在嵌套信息,嵌套内容键名为文件中对应字段或是你的总结,而嵌套键值必须与原文保持一致,若存在未知信息,在对应的键值中填'未知'。示例输出如下,仅供格式参考:
|
13.请你根据招标文件信息,回答以下问题:是否组织踏勘现场?是否召开投标预备会(或投标答疑会)?是否退还投标文件?是否允许分包? 是否需要递交投标保证金(或磋商保证金)?是否需要提交履约保证金(或履约担保)?是否有招标代理服务费(或中标、成交服务费或采购代理服务费)?是否需要提交质量保证金?请按json格式给我提供信息,键名分别为'是否组织踏勘现场','是否召开投标预备会'(或'是否召开投标答疑会'),'是否退还投标文件',是否允许分包','是否递交投标保证金'(或'是否递交磋商保证金'),'是否提交履约保证金','是否有招标代理服务费','是否有质量保证金',键值仅限于'是','否','未知',若存在前后矛盾或原文中未提及的信息,请回答'未知'。
|
||||||
示例1,嵌套键值对情况:
|
|
||||||
{
|
|
||||||
"偏离":{
|
|
||||||
"技术和服务要求":"以★标示的内容为不允许负偏离的实质性要求",
|
|
||||||
"商务要求":"以★标示的内容为不允许负偏离的实质性要求"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
示例2,无嵌套键值对情况:
|
|
||||||
{
|
|
||||||
"偏离":"所有参数需在技术响应偏离表内响应,如应答有缺项,且无有效证明材料的,评标委员会有权不予认可,视同负偏离处理"
|
|
||||||
}
|
|
||||||
|
@ -35,13 +35,17 @@
|
|||||||
|
|
||||||
9.该招标文件中对投标人(或供应商)准备和参加投标活动中发生的费用是如何规定的?请以json的格式给我提供信息,键名是'投标费用承担',若存在未知信息,在对应的键值中填'未知'。
|
9.该招标文件中对投标人(或供应商)准备和参加投标活动中发生的费用是如何规定的?请以json的格式给我提供信息,键名是'投标费用承担',若存在未知信息,在对应的键值中填'未知'。
|
||||||
|
|
||||||
10.招标人(或招标代理机构)对招标文件的澄清(或答疑)的截止时间是?请以json的格式给我提供信息,键名是'澄清招标文件的截止时间',若存在未知信息,在对应的键值中填'未知'。
|
10.根据提供的实际招标文件内容,招标人(或招标代理机构)对招标文件的澄清(或答疑)的截止时间是?请以json的格式给我提供信息,键名是'澄清招标文件的截止时间',键值为原文中有关澄清截止时间的相关表述,不一定是明确的时间节点。
|
||||||
|
禁止内容:
|
||||||
|
确保所有输出内容均基于提供的实际招标文件内容,不使用任何预设的示例作为回答。
|
||||||
|
示例输出如下,仅供格式参考:
|
||||||
|
{
|
||||||
|
"澄清招标文件的截止时间":"在投标截止时间至少 20 个日历日前"
|
||||||
|
}
|
||||||
|
|
||||||
11.该文档要求扣留的质量保证金百分比是多少,请以json格式给我提供信息,键名为'质量保证金',如果没有则以'未知'填充。
|
11.该项目是否接受联合体投标?请按json格式给我提供信息,键名为'是否接受联合体投标','是否接受联合体投标'的键值仅限于'是'、'否'、'未知'。
|
||||||
|
|
||||||
12.该项目是否接受联合体投标?请按json格式给我提供信息,键名为'是否接受联合体投标','是否接受联合体投标'的键值仅限于'是'、'否'、'未知'。
|
12.该项目的开标时间(或开启时间)和开标地点(或开启地点、开启方式)是?请按json格式给我提供信息,键名为'开标时间'和'开标地点',键值为原文中相关内容的表述。
|
||||||
|
|
||||||
13.该项目的开标时间(或开启时间)和开标地点(或开启地点、开启方式)是?请按json格式给我提供信息,键名为'开标时间'和'开标地点',键值为原文中相关内容的表述。
|
|
||||||
对于'开标时间',若文中没有明确时间却有诸如'同投标截止时间'的表述,则将相关表述返回;若存在未知信息,在对应的键值中填'未知'。
|
对于'开标时间',若文中没有明确时间却有诸如'同投标截止时间'的表述,则将相关表述返回;若存在未知信息,在对应的键值中填'未知'。
|
||||||
示例输出如下,仅供格式参考:
|
示例输出如下,仅供格式参考:
|
||||||
{
|
{
|
||||||
@ -49,6 +53,9 @@
|
|||||||
"开标地点":"线上开标"
|
"开标地点":"线上开标"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13.请你根据招标文件信息,回答以下问题:是否组织踏勘现场?是否召开投标预备会(或答疑会)?是否退还投标文件?是否允许分包? 是否需要递交投标保证金(或磋商保证金)?是否需要提交履约保证金(或履约担保)?是否有招标代理服务费(或中标、成交服务费或采购代理服务费)?是否需要提交质量保证金?请按json格式给我提供信息,键名分别为'是否组织踏勘现场','是否召开投标预备会'(或'是否召开投标答疑会'),'是否退还投标文件',是否允许分包','是否递交投标保证金'(或'是否递交磋商保证金'),'是否提交履约保证金','是否有招标代理服务费','是否有质量保证金',键值仅限于'是','否','未知',若存在前后矛盾或原文中未提及的信息,请回答'未知'。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
2.该招标文件的项目概况(或工程概况)是?项目基本情况是?请按json格式给我提供信息,键名分别为'项目概况','项目基本情况',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,若存在未知信息,在对应的键值中填'未知'。
|
2.该招标文件的项目概况(或工程概况)是?项目基本情况是?请按json格式给我提供信息,键名分别为'项目概况','项目基本情况',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,若存在未知信息,在对应的键值中填'未知'。
|
||||||
|
|
||||||
3.该招标文件的招标控制价(或投标限价或项目预算金额)是?请按json格式给我提供信息,键名为'招标控制价',若存在未知信息,在对应的键值中填'未知'。
|
3.该招标文件的招标控制价(或投标限价或项目预算金额)是?请返回具体的金额,并按json格式给我提供信息,键名为'招标控制价',若存在未知信息,在对应的键值中填'未知'。
|
||||||
|
|
||||||
4.投标文件递交截止日期是?请按json格式给我提供信息,键名是'投标文件递交截止日期',若原文未提及明确日期时间,请返回原文对应的内容,若存在未知信息,在对应的键值中填'未知'。示例输出格式如下:
|
4.投标文件递交截止日期是?请按json格式给我提供信息,键名是'投标文件递交截止日期',若原文未提及明确日期时间,请返回原文对应的内容,若存在未知信息,在对应的键值中填'未知'。示例输出格式如下:
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
2.该招标文件的项目概况是?项目基本情况是?请按json格式给我提供信息,键名分别为'项目概况','项目基本情况',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,而嵌套键值必须与原文保持一致,若存在未知信息,在对应的键值中填'未知'。
|
2.该招标文件的项目概况是?项目基本情况是?请按json格式给我提供信息,键名分别为'项目概况','项目基本情况',若存在嵌套信息,嵌套内容键名以文件中对应字段命名,而嵌套键值必须与原文保持一致,若存在未知信息,在对应的键值中填'未知'。
|
||||||
|
|
||||||
3.该招标文件的最高限价(或招标控制价或预算金额)是?请按json格式给我提供信息,键名为'招标控制价',若存在未知信息,在对应的键值中填'未知'。
|
3.该招标文件的最高限价(或招标控制价或预算金额)是?请返回具体的金额,并按json格式给我提供信息,键名为'招标控制价',若存在未知信息,在对应的键值中填'未知'。
|
||||||
|
|
||||||
4.投标文件(或响应文件)递交截止时间是?请按json格式给我提供信息,键名是'投标文件递交截止日期',若原文未提及明确日期时间,请返回原文对应的内容,若存在未知信息,在对应的键值中填'未知'。示例输出格式如下:
|
4.投标文件(或响应文件)递交截止时间是?请按json格式给我提供信息,键名是'投标文件递交截止日期',若原文未提及明确日期时间,请返回原文对应的内容,若存在未知信息,在对应的键值中填'未知'。示例输出格式如下:
|
||||||
{
|
{
|
||||||
|
@ -1,16 +1,81 @@
|
|||||||
1.该招标文件对于分包的要求是怎样的?请按json格式给我提供信息,键名为'分包',若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
1.该招标文件对于分包的要求是怎样的?请按json格式给我提供信息,键名为'分包',若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
||||||
|
|
||||||
2.该项目的投标保证金(或磋商保证金)的内容或要求是什么?请按json格式给我提供信息,外层键名为"投标保证金"(或"磋商保证金"),若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
2.根据提供的实际招标文件内容,提取“投标保证金”(或“磋商保证金”)的具体要求,并以JSON格式返回。JSON的外层键名固定为“投标保证金”(或“磋商保证金”),必须包含以下内容:
|
||||||
|
-至少包含一个嵌套键名'金额',用于说明需要递交的具体投标保证金额或是相对金额百分比描述;
|
||||||
|
-如果文件中有其他关于投标保证金的内容及要求,也需将其逐一提取为嵌套键值对。嵌套键的键名可直接使用原文中的子标题,或基于内容进行简要总结;对应的键值必须与原文表述一致,不得修改或添加解释。
|
||||||
|
禁止内容:
|
||||||
|
确保所有输出内容均基于提供的实际招标文件内容,不使用任何预设的示例作为回答。
|
||||||
|
示例输出如下,仅供格式参考:
|
||||||
|
{
|
||||||
|
"投标保证金":{
|
||||||
|
"金额":50000,
|
||||||
|
"递交方式":"1)采用现金方式。2)银行转账"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
3.该招标文件对于投标保证金的退还相关的规章办法是怎样的?请按json格式给我提供信息,键名为'退还投标保证金',示例输出格式如下:
|
3.该招标文件对于投标保证金的退还相关的规章办法是怎样的?请按json格式给我提供信息,键名为'退还投标保证金',示例输出如下,仅供格式参考:
|
||||||
{
|
{
|
||||||
"退还投标保证金":"投标保证金的退还按《xxx》相关条款执行。"
|
"退还投标保证金":"投标保证金的退还按《xxx》相关条款执行。"
|
||||||
}
|
}
|
||||||
|
|
||||||
4.该项目对于履约保证金(履约担保)的内容或要求是怎样的,请按json格式给我提供信息,外层键名为"履约保证金",若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
4.根据提供的实际招标文件内容,提取“履约保证金”(或“履约担保”)的具体要求,并以JSON格式返回。JSON的外层键名固定为“履约保证金”,必须包含以下内容:
|
||||||
|
-至少包含一个嵌套键名'金额',用于说明需要递交的具体履约保证金额或相对金额的百分比描述;
|
||||||
|
-如果文件中有其他关于履约保证金的要求,也需将其逐一提取为嵌套键值对。嵌套键的键名可直接使用原文中的子标题,或基于内容进行简要总结;对应的键值必须与原文表述完全一致,不得修改或添加解释。
|
||||||
|
禁止事项:
|
||||||
|
确保所有输出内容均基于实际提供的招标文件内容;
|
||||||
|
不得凭空假设或使用任何预设示例作为答案。
|
||||||
|
示例输出如下,仅供格式参考:
|
||||||
|
{
|
||||||
|
"履约保证金":{
|
||||||
|
"金额":10000元,
|
||||||
|
"递交方式":"1)采用现金方式。2)银行转账"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
5.本项目的招标代理服务费(或中标服务费、成交服务费、采购代理服务费)的相关内容是怎样的,请按json格式给我提供信息,外层键名为'招标代理服务费',若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
5.根据提供的实际招标文件内容,提取招标代理服务费(或中标服务费、成交服务费、采购代理服务费)的具体内容,并以JSON格式返回。外层键名为'招标代理服务费',必须包含以下内容:
|
||||||
|
-至少包含一个嵌套键名'金额',用于说明需要递交的具体招标代理服务费金额或是相对金额百分比描述;
|
||||||
|
-如果文件中有其他关于招标代理服务费的内容及要求,也需将其逐一提取为嵌套键值对。嵌套键的键名可直接使用原文中的子标题,或基于内容进行简要总结;对应的键值必须与原文表述一致,不得修改或添加解释。
|
||||||
|
禁止内容:
|
||||||
|
确保所有输出内容均基于提供的实际招标文件内容,不使用任何预设的示例作为回答。
|
||||||
|
示例输出如下,仅供格式参考:
|
||||||
|
{
|
||||||
|
"招标代理服务费":{
|
||||||
|
"金额":10000,
|
||||||
|
"递交方式":"1)采用现金方式。2)银行转账"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
6.该招标文件对于踏勘现场的内容或要求是怎样的,请按json格式给我提供信息,外层键名为"踏勘现场",若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
6.该招标文件对于踏勘现场的内容或要求是怎样的,请按json格式给我提供信息,外层键名为"踏勘现场",若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
||||||
|
|
||||||
7.该招标文件对于投标预备会(或投标答疑会)内容是怎样的,请按json格式给我提供信息,外层键名为"投标预备会"(或"投标答疑会"),若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
7.该招标文件对于投标预备会(或投标答疑会)内容是怎样的,请按json格式给我提供信息,外层键名为"投标预备会"(或"投标答疑会"),若需要以嵌套键值对返回结果,那么嵌套键名为原文中的子标题或是你对相应要求的总结,而对应键值需要完全与原文保持一致。
|
||||||
|
|
||||||
|
8.根据提供的实际招标文件内容,提取“质量保证金”的具体内容,并以JSON格式返回。JSON的外层键名固定为“质量保证金”,必须包含以下内容:
|
||||||
|
-至少包含一个嵌套键名'金额',用于说明需要递交的具体履约保证金额或相对金额的百分比描述;
|
||||||
|
-如果文件中有其他关于履质量保证金的要求,也需将其逐一提取为嵌套键值对。嵌套键的键名可直接使用原文中的子标题,或基于内容进行简要总结;对应的键值必须与原文表述完全一致,不得修改或添加解释。
|
||||||
|
禁止事项:
|
||||||
|
确保所有输出内容均基于实际提供的招标文件内容;
|
||||||
|
不得凭空假设或使用任何预设示例作为答案。
|
||||||
|
示例输出如下,仅供格式参考:
|
||||||
|
{
|
||||||
|
"履约保证金":{
|
||||||
|
"金额":10000元,
|
||||||
|
"递交方式":"1)采用现金方式。2)银行转账"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
9.该招标文件对响应文件(投标文件)偏离项的要求或内容是怎样的?请不要回答具体的技术参数,也不要回答具体的评分要求。请以json格式给我提供信息,外层键名为'偏离',若存在嵌套信息,嵌套内容键名为文件中对应字段或是你的总结,而嵌套键值必须与原文保持一致,若文中未涉及相关内容,在键值中填'未知'。
|
||||||
|
注意:不使用任何预设的示例作为回答,示例仅作为格式参考。
|
||||||
|
禁止内容:
|
||||||
|
确保所有输出内容均基于提供的实际招标文件内容;
|
||||||
|
不使用任何预设的示例作为回答。
|
||||||
|
示例1,嵌套键值对情况:
|
||||||
|
{
|
||||||
|
"偏离":{
|
||||||
|
"技术要求":"以★标示的内容不允许负偏离",
|
||||||
|
"商务要求":"以★标示的内容不允许负偏离"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
示例2,无嵌套键值对情况:
|
||||||
|
{
|
||||||
|
"偏离":"所有参数需在技术响应偏离表内响应,如应答有缺项,且无有效证明材料的,评标委员会有权不予认可,视同负偏离处理"
|
||||||
|
}
|
||||||
|
@ -48,24 +48,24 @@ def construct_judge_questions(json_data):
|
|||||||
|
|
||||||
|
|
||||||
def merge_json_to_list(merged,tobidders_notice=""):
|
def merge_json_to_list(merged,tobidders_notice=""):
|
||||||
|
|
||||||
# print(json.dumps(merged,ensure_ascii=False,indent=4))
|
# print(json.dumps(merged,ensure_ascii=False,indent=4))
|
||||||
"""Merge updates into the original data by modifying specific keys based on their value ('是' or '否'), and create a list based on these values."""
|
"""Merge updates into the original data by modifying specific keys based on their value ('是' or '否'), and create a list based on these values."""
|
||||||
chosen_numbers = []
|
chosen_numbers = []
|
||||||
|
chosen_numbers.append(9)
|
||||||
|
|
||||||
# 定义键名映射
|
# # 定义键名映射
|
||||||
key_mapping = {
|
# key_mapping = {
|
||||||
'是否允许分包': '分包',
|
# '是否允许分包': '分包',
|
||||||
'是否递交投标保证金': '投标保证金',
|
# '是否递交投标保证金': '投标保证金',
|
||||||
'是否递交磋商保证金': '磋商保证金',
|
# '是否递交磋商保证金': '磋商保证金',
|
||||||
'是否提交履约保证金': '履约保证金',
|
# '是否提交履约保证金': '履约保证金',
|
||||||
'是否有招标代理服务费': '招标代理服务费',
|
# '是否有招标代理服务费': '招标代理服务费',
|
||||||
'是否组织踏勘现场': '踏勘现场',
|
# '是否组织踏勘现场': '踏勘现场',
|
||||||
'是否召开投标预备会': '投标预备会',
|
# '是否召开投标预备会': '投标预备会',
|
||||||
'是否召开投标答疑会': '投标答疑会',
|
# '是否召开投标答疑会': '投标答疑会',
|
||||||
'是否允许偏离': '偏离',
|
# '是否允许偏离': '偏离',
|
||||||
'是否退还投标文件':'退还投标文件'
|
# '是否退还投标文件':'退还投标文件'
|
||||||
}
|
# }
|
||||||
|
|
||||||
# 处理是否允许分包
|
# 处理是否允许分包
|
||||||
if merged.get('是否允许分包') == '是':
|
if merged.get('是否允许分包') == '是':
|
||||||
@ -82,12 +82,14 @@ def merge_json_to_list(merged,tobidders_notice=""):
|
|||||||
guarantee_type = '投标' if '投标' in guarantee_key else '磋商'
|
guarantee_type = '投标' if '投标' in guarantee_key else '磋商'
|
||||||
if merged[guarantee_key] == '是':
|
if merged[guarantee_key] == '是':
|
||||||
chosen_numbers.extend([2, 3])
|
chosen_numbers.extend([2, 3])
|
||||||
|
merged.pop(guarantee_key, None)
|
||||||
elif merged[guarantee_key] == '否':
|
elif merged[guarantee_key] == '否':
|
||||||
merged[f'{guarantee_type}保证金'] = '不提交'
|
merged[f'{guarantee_type}保证金'] = '不提交'
|
||||||
|
merged.pop(guarantee_key, None)
|
||||||
merged[f'退还{guarantee_type}保证金'] = '/'
|
merged[f'退还{guarantee_type}保证金'] = '/'
|
||||||
else:
|
else:
|
||||||
# 当既不是 '是' 也不是 '否' 时执行
|
# 当既不是 '是' 也不是 '否' 时执行
|
||||||
merged[f'退还{guarantee_type}保证金'] = '未知'
|
merged[f'是否退还{guarantee_type}保证金'] = '未知'
|
||||||
guarantee_processed = True
|
guarantee_processed = True
|
||||||
elif guarantee_key in merged and guarantee_processed:
|
elif guarantee_key in merged and guarantee_processed:
|
||||||
merged.pop(guarantee_key, None)
|
merged.pop(guarantee_key, None)
|
||||||
@ -119,15 +121,27 @@ def merge_json_to_list(merged,tobidders_notice=""):
|
|||||||
# 处理预备会/答疑会
|
# 处理预备会/答疑会
|
||||||
meeting_processed = False
|
meeting_processed = False
|
||||||
for preparation_key in ['是否召开投标预备会', '是否召开投标答疑会']:
|
for preparation_key in ['是否召开投标预备会', '是否召开投标答疑会']:
|
||||||
if preparation_key in merged:
|
if preparation_key in merged and not meeting_processed:
|
||||||
if not meeting_processed:
|
meeting_type = '预备会' if '预备会' in preparation_key else '答疑会'
|
||||||
if merged[preparation_key] == '是':
|
if merged[preparation_key] == '是':
|
||||||
chosen_numbers.append(7)
|
chosen_numbers.append(7)
|
||||||
|
merged.pop(preparation_key,None)
|
||||||
elif merged[preparation_key] == '否':
|
elif merged[preparation_key] == '否':
|
||||||
meeting_type = '预备会' if '预备会' in preparation_key else '答疑会'
|
|
||||||
merged[f'投标{meeting_type}'] = '不召开'
|
merged[f'投标{meeting_type}'] = '不召开'
|
||||||
meeting_processed = True
|
|
||||||
merged.pop(preparation_key, None)
|
merged.pop(preparation_key, None)
|
||||||
|
else:
|
||||||
|
# 当既不是 '是' 也不是 '否' 时执行
|
||||||
|
merged[f'是否召开投标{meeting_type}'] = '未知'
|
||||||
|
meeting_processed = True
|
||||||
|
elif preparation_key in merged and meeting_processed:
|
||||||
|
merged.pop(preparation_key, None)
|
||||||
|
|
||||||
|
if merged.get('是否有质量保证金') == '是':
|
||||||
|
chosen_numbers.append(8)
|
||||||
|
merged.pop('是否有质量保证金',None)
|
||||||
|
elif merged.get('是否有质量保证金') == '否':
|
||||||
|
merged['质量保证金']='不提交'
|
||||||
|
merged.pop('是否有质量保证金',None)
|
||||||
|
|
||||||
#11.12这里有问题,正文部分的信息重要性不高,而且这里的key不好设置,先注释了
|
#11.12这里有问题,正文部分的信息重要性不高,而且这里的key不好设置,先注释了
|
||||||
# # 初始化 questions_list
|
# # 初始化 questions_list
|
||||||
@ -158,6 +172,8 @@ def merge_json_to_list(merged,tobidders_notice=""):
|
|||||||
# for info in baseinfo_list:
|
# for info in baseinfo_list:
|
||||||
# merged.update(info)
|
# merged.update(info)
|
||||||
|
|
||||||
|
# print(chosen_numbers)
|
||||||
|
# print(json.dumps(merged,ensure_ascii=False,indent=4))
|
||||||
return chosen_numbers, merged
|
return chosen_numbers, merged
|
||||||
|
|
||||||
def read_questions_from_judge(file_path, indices):
|
def read_questions_from_judge(file_path, indices):
|
||||||
|
@ -32,25 +32,25 @@ def update_baseinfo_lists(baseinfo_list1, baseinfo_list2):
|
|||||||
return updated_list
|
return updated_list
|
||||||
|
|
||||||
#先不带投标人须知正文,如果是未知,再直接问正文,
|
#先不带投标人须知正文,如果是未知,再直接问正文,
|
||||||
def process_baseinfo_list(baseinfo_list, tobidders_notice):
|
def process_baseinfo_list(baseinfo_list, merged_baseinfo_path):
|
||||||
questions_list = []
|
questions_list = []
|
||||||
for item in baseinfo_list:
|
for item in baseinfo_list:
|
||||||
# print(json.dumps(item, ensure_ascii=False, indent=4))
|
# print(json.dumps(item, ensure_ascii=False, indent=4))
|
||||||
for key, value in item.items():
|
for key, value in item.items():
|
||||||
if value == "未知" or (isinstance(value, dict) and all(v == "未知" for v in value.values())):
|
if value == "未知" or (isinstance(value, dict) and all(v == "未知" for v in value.values())):
|
||||||
question = (
|
question = (
|
||||||
f"根据该招标文件中的信息,{key}的内容是怎样的?请按json格式给我提供信息,键名是'{key}',若存在嵌套信息,嵌套内容键名以文件中对应字段命名(或是你对相应要求的总结),而对应键值需要与原文保持一致。注意:默认情况用普通键值对返回结果即可,键名为{key};若原文中未提及'{key}'相关内容,在键值中填'未知'。"
|
f"根据该招标文件中的信息,{key}的内容是怎样的?请按json格式给我提供信息,键名是'{key}',若存在嵌套信息,嵌套内容键名以文件中对应字段命名(或是你对相应要求的总结),而对应键值需要与原文保持一致。注意:默认情况用普通键值对返回结果即可,外层键名为{key};若原文中未提及'{key}'相关内容,在键值中填'未知'。"
|
||||||
)
|
)
|
||||||
questions_list.append(question)
|
questions_list.append(question)
|
||||||
|
|
||||||
if questions_list:
|
if questions_list:
|
||||||
file_id = upload_file(tobidders_notice)
|
file_id = upload_file(merged_baseinfo_path)
|
||||||
baseinfo_results = multi_threading(questions_list, "", file_id, 2)
|
baseinfo_results = multi_threading(questions_list, "", file_id, 2)
|
||||||
return [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else []
|
return [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else []
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def combine_basic_info(merged_baseinfo_path,merged_baseinfo_path_more, tobidders_notice, clause_path):
|
def combine_basic_info(merged_baseinfo_path,merged_baseinfo_path_more, clause_path,invalid_path):
|
||||||
"""
|
"""
|
||||||
综合和处理基础信息,生成最终的基础信息字典。
|
综合和处理基础信息,生成最终的基础信息字典。
|
||||||
|
|
||||||
@ -67,8 +67,6 @@ def combine_basic_info(merged_baseinfo_path,merged_baseinfo_path_more, tobidders
|
|||||||
baseinfo_prompt_file_path = 'flask_app/static/提示词/基本信息工程标.txt'
|
baseinfo_prompt_file_path = 'flask_app/static/提示词/基本信息工程标.txt'
|
||||||
file_id = upload_file(merged_baseinfo_path)
|
file_id = upload_file(merged_baseinfo_path)
|
||||||
questions = read_questions_from_file(baseinfo_prompt_file_path)
|
questions = read_questions_from_file(baseinfo_prompt_file_path)
|
||||||
more_query = "请你根据招标文件信息,回答以下问题:是否组织踏勘现场?是否召开投标预备会(或投标答疑会)?是否退还投标文件?是否允许分包? 是否需要递交投标保证金?是否需要提交履约保证金(履约担保)?是否有招标代理服务费?请按json格式给我提供信息,键名分别为'是否组织踏勘现场','是否召开投标预备会','是否退还投标文件',是否允许分包','是否递交投标保证金','是否提交履约保证金','是否有招标代理服务费',键值仅限于'是','否','未知',若存在矛盾信息,请回答'未知'。"
|
|
||||||
questions.append(more_query)
|
|
||||||
baseinfo_results = multi_threading(questions, "", file_id, 2)
|
baseinfo_results = multi_threading(questions, "", file_id, 2)
|
||||||
baseinfo_list1 = [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else []
|
baseinfo_list1 = [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else []
|
||||||
chosen_numbers, merged = merge_json_to_list(baseinfo_list1.pop())
|
chosen_numbers, merged = merge_json_to_list(baseinfo_list1.pop())
|
||||||
@ -79,8 +77,8 @@ def combine_basic_info(merged_baseinfo_path,merged_baseinfo_path_more, tobidders
|
|||||||
|
|
||||||
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
|
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
|
||||||
# 提交两个任务
|
# 提交两个任务
|
||||||
future1 = executor.submit(process_judge_questions, judge_file_path, chosen_numbers, file_id, baseinfo_list1)
|
future1 = executor.submit(process_judge_questions, judge_file_path, chosen_numbers, invalid_path, baseinfo_list1)
|
||||||
future2 = executor.submit(process_baseinfo_list, baseinfo_list1_copy, tobidders_notice) #只问tobidders_notice
|
future2 = executor.submit(process_baseinfo_list, baseinfo_list1_copy, merged_baseinfo_path) #未知的内容再问一次
|
||||||
future3 = executor.submit(extract_from_notice, merged_baseinfo_path_more, clause_path, 3) # 新增的多线程任务
|
future3 = executor.submit(extract_from_notice, merged_baseinfo_path_more, clause_path, 3) # 新增的多线程任务
|
||||||
|
|
||||||
# 等待两个任务完成并获取结果
|
# 等待两个任务完成并获取结果
|
||||||
@ -88,23 +86,24 @@ def combine_basic_info(merged_baseinfo_path,merged_baseinfo_path_more, tobidders
|
|||||||
baseinfo_list2 = future2.result()
|
baseinfo_list2 = future2.result()
|
||||||
rebidding_situation = future3.result() # 获取提取失败的情况
|
rebidding_situation = future3.result() # 获取提取失败的情况
|
||||||
|
|
||||||
updated_list = update_baseinfo_lists(baseinfo_list1, baseinfo_list2)
|
updated_baseinfo_list = update_baseinfo_lists(baseinfo_list1, baseinfo_list2)
|
||||||
update_json = add_outer_key(rebidding_situation, "重新招标、不再招标和终止招标")
|
update_json = add_outer_key(rebidding_situation, "重新招标、不再招标和终止招标")
|
||||||
updated_list.append(update_json)
|
updated_baseinfo_list.append(update_json)
|
||||||
aggregated_baseinfo = aggregate_basic_info(updated_list)
|
aggregated_baseinfo = aggregate_basic_info(updated_baseinfo_list)
|
||||||
|
|
||||||
return {"基础信息": aggregated_baseinfo}
|
return {"基础信息": aggregated_baseinfo}
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
merged_baseinfo_path = r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\ztbfile_merged_baseinfo.pdf"
|
merged_baseinfo_path = r"C:\Users\Administrator\Desktop\工程\test\2022-广东-鹏华基金管理有限公司深圳深业上城办公室装修项目.docx"
|
||||||
more=r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\merged_baseinfo_path_more.pdf"
|
more=r"C:\Users\Administrator\Desktop\工程\test\2022-广东-鹏华基金管理有限公司深圳深业上城办公室装修项目.docx"
|
||||||
# output_folder="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output"
|
# output_folder="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output"
|
||||||
tobidders_notice_table = r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\ztbfile_tobidders_notice_table.pdf"
|
tobidders_notice_table = r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\ztbfile_tobidders_notice_table.pdf"
|
||||||
tobidders_notice = r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\ztbfile_tobidders_notice.pdf"
|
# tobidders_notice = r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\ztbfile_tobidders_notice.pdf"
|
||||||
clause_path = r"D:\flask_project\flask_app\static\output\output1\6f2010ee-d7cd-4787-a26a-2db8233d179a\clause1.json"
|
clause_path = ""
|
||||||
res = combine_basic_info(merged_baseinfo_path,more,tobidders_notice, clause_path)
|
invalid_path=r"C:\Users\Administrator\Desktop\工程\test\2022-广东-鹏华基金管理有限公司深圳深业上城办公室装修项目.docx"
|
||||||
|
res = combine_basic_info(merged_baseinfo_path,more, clause_path,invalid_path)
|
||||||
print(json.dumps(res, ensure_ascii=False, indent=4))
|
print(json.dumps(res, ensure_ascii=False, indent=4))
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
print("elapsed_time:" + str(end_time - start_time))
|
print("elapsed_time:" + str(end_time - start_time))
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
#flask_app/工程标/截取pdf工程标版.py
|
# flask_app/工程标/截取pdf工程标版.py
|
||||||
import regex
|
import regex
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from PyPDF2 import PdfReader, PdfWriter
|
from PyPDF2 import PdfReader, PdfWriter
|
||||||
from flask_app.general.clean_pdf import clean_page_content
|
from flask_app.general.clean_pdf import clean_page_content
|
||||||
|
|
||||||
from flask_app.general.截取pdf通用函数 import get_start_and_common_header,save_extracted_pages,get_invalid_file
|
from flask_app.general.截取pdf通用函数 import get_start_and_common_header, save_extracted_pages, get_invalid_file
|
||||||
from flask_app.general.通用功能函数 import get_global_logger
|
from flask_app.general.通用功能函数 import get_global_logger
|
||||||
|
|
||||||
|
|
||||||
def extract_pages_tobidders_notice(pdf_path, output_folder, begin_pattern, begin_page, common_header,
|
def extract_pages_tobidders_notice(pdf_path, output_folder, begin_pattern, begin_page, common_header,
|
||||||
is_secondary_match):
|
is_secondary_match):
|
||||||
pdf_document = PdfReader(pdf_path)
|
pdf_document = PdfReader(pdf_path)
|
||||||
exclusion_pattern = regex.compile(r'文件的构成|文件的组成|须对应|需对应|须按照|需按照|须根据|需根据|文件组成|文件构成|文件的编制|文件编制')
|
exclusion_pattern = regex.compile(
|
||||||
|
r'文件的构成|文件的组成|须对应|需对应|须按照|需按照|须根据|需根据|文件组成|文件构成|文件的编制|文件编制')
|
||||||
|
|
||||||
def run_extraction():
|
def run_extraction():
|
||||||
start_page = None
|
start_page = None
|
||||||
mid_page = None
|
mid_page = None
|
||||||
end_page = None
|
end_page = None
|
||||||
chapter_type = None # 用于存储“章”或“部分”
|
chapter_type = None # 用于存储“章”或“部分”
|
||||||
combined_mid_pattern= None
|
combined_mid_pattern = None
|
||||||
end_pattern = None
|
end_pattern = None
|
||||||
|
|
||||||
for i, page in enumerate(pdf_document.pages):
|
for i, page in enumerate(pdf_document.pages):
|
||||||
@ -130,8 +132,9 @@ def extract_pages(pdf_path, output_folder, begin_pattern, begin_page, end_patter
|
|||||||
pdf_document = PdfReader(pdf_path)
|
pdf_document = PdfReader(pdf_path)
|
||||||
start_page = None
|
start_page = None
|
||||||
end_page = None
|
end_page = None
|
||||||
flag=True
|
flag = True
|
||||||
exclusion_pattern = regex.compile(r'文件的构成|文件的组成|须对应|需对应|须按照|需按照|须根据|需根据|文件组成|文件构成|文件的编制|文件编制')
|
exclusion_pattern = regex.compile(
|
||||||
|
r'文件的构成|文件的组成|须对应|需对应|须按照|需按照|须根据|需根据|文件组成|文件构成|文件的编制|文件编制')
|
||||||
# 遍历文档的每一页,查找开始和结束短语的位置
|
# 遍历文档的每一页,查找开始和结束短语的位置
|
||||||
for i in range(len(pdf_document.pages)):
|
for i in range(len(pdf_document.pages)):
|
||||||
page = pdf_document.pages[i]
|
page = pdf_document.pages[i]
|
||||||
@ -139,14 +142,15 @@ def extract_pages(pdf_path, output_folder, begin_pattern, begin_page, end_patter
|
|||||||
if text:
|
if text:
|
||||||
cleaned_text = clean_page_content(text, common_header)
|
cleaned_text = clean_page_content(text, common_header)
|
||||||
if flag and regex.search(exclusion_pattern, cleaned_text):
|
if flag and regex.search(exclusion_pattern, cleaned_text):
|
||||||
flag=False
|
flag = False
|
||||||
continue
|
continue
|
||||||
if regex.search(begin_pattern, cleaned_text) and i >= begin_page:
|
if regex.search(begin_pattern, cleaned_text) and i >= begin_page:
|
||||||
if start_page and (output_suffix == "notice" or output_suffix == "invalid"):
|
if start_page and (output_suffix == "notice" or output_suffix == "invalid"):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
start_page = i
|
start_page = i
|
||||||
if start_page is not None and regex.search(end_pattern, cleaned_text) and not regex.search(begin_pattern,cleaned_text):
|
if start_page is not None and regex.search(end_pattern, cleaned_text) and not regex.search(begin_pattern,
|
||||||
|
cleaned_text):
|
||||||
condition = i > start_page
|
condition = i > start_page
|
||||||
if condition:
|
if condition:
|
||||||
is_invalid_condition = output_suffix == "invalid" and i > 30 # 这边默认无效投标至少有30页
|
is_invalid_condition = output_suffix == "invalid" and i > 30 # 这边默认无效投标至少有30页
|
||||||
@ -172,7 +176,8 @@ def extract_pages_twice(pdf_path, output_folder, output_suffix, common_header, l
|
|||||||
if output_suffix == "qualification":
|
if output_suffix == "qualification":
|
||||||
print("twice:qualificaiton!")
|
print("twice:qualificaiton!")
|
||||||
# 动态设置 include_keys
|
# 动态设置 include_keys
|
||||||
include_keys = ["资格审查", "资质审查", "符合性审查", "资格性检查", "符合性检查","资格检查","能力","信誉"]
|
include_keys = ["资格审查", "资质审查", "符合性审查", "资格性检查", "符合性检查", "资格检查", "能力",
|
||||||
|
"信誉"]
|
||||||
# 定义起始匹配模式,仅匹配“附录”、“附件”或“附表”
|
# 定义起始匹配模式,仅匹配“附录”、“附件”或“附表”
|
||||||
begin_pattern = r'^(?:附录(?:[一1])?[::]|附件(?:[一1])?[::]|附表(?:[一1])?[::])'
|
begin_pattern = r'^(?:附录(?:[一1])?[::]|附件(?:[一1])?[::]|附表(?:[一1])?[::])'
|
||||||
# 定义结束匹配模式 - 附录、附件、附表等(移除负向前瞻)
|
# 定义结束匹配模式 - 附录、附件、附表等(移除负向前瞻)
|
||||||
@ -221,7 +226,8 @@ def extract_pages_twice(pdf_path, output_folder, output_suffix, common_header, l
|
|||||||
print(f"{output_suffix} twice: 未找到起始或结束页在文件 {pdf_path} 中!")
|
print(f"{output_suffix} twice: 未找到起始或结束页在文件 {pdf_path} 中!")
|
||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
return [save_extracted_pages(pdf_path, output_folder, start_page, end_page, output_suffix, common_header)]
|
return [
|
||||||
|
save_extracted_pages(pdf_path, output_folder, start_page, end_page, output_suffix, common_header)]
|
||||||
else:
|
else:
|
||||||
print(f"{output_suffix} twice: 未定义的输出后缀。")
|
print(f"{output_suffix} twice: 未定义的输出后缀。")
|
||||||
return []
|
return []
|
||||||
@ -230,7 +236,7 @@ def extract_pages_twice(pdf_path, output_folder, output_suffix, common_header, l
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def truncate_pdf_main_engineering(input_path, output_folder, selection,logger,output_suffix="default"):
|
def truncate_pdf_main_engineering(input_path, output_folder, selection, logger, output_suffix="default"):
|
||||||
try:
|
try:
|
||||||
# 内嵌的处理单个文件的函数
|
# 内嵌的处理单个文件的函数
|
||||||
def process_single_file(file_path, output_folder, selection):
|
def process_single_file(file_path, output_folder, selection):
|
||||||
@ -284,7 +290,8 @@ def truncate_pdf_main_engineering(input_path, output_folder, selection,logger,ou
|
|||||||
r'(?:[\u4e00-\u9fff、()()]*?)'
|
r'(?:[\u4e00-\u9fff、()()]*?)'
|
||||||
r'(?=.*(?:(?:磋商|谈判)(?=.*(?:办法|方法|内容))|(?:评标|评定|评审)))' # 修改的部分
|
r'(?=.*(?:(?:磋商|谈判)(?=.*(?:办法|方法|内容))|(?:评标|评定|评审)))' # 修改的部分
|
||||||
r'[\u4e00-\u9fff、()()]*\s*$|'
|
r'[\u4e00-\u9fff、()()]*\s*$|'
|
||||||
r'^\s*(?<!见\s*)(?<!与\s*)(?<!"\s*)(?<!"\s*)(?<!"\s*)评标(方法|办法)前附表\s*$)', # 第二种模式
|
r'^\s*(?<!见\s*)(?<!与\s*)(?<!"\s*)(?<!"\s*)(?<!"\s*)评标(方法|办法)前附表\s*$)',
|
||||||
|
# 第二种模式
|
||||||
regex.MULTILINE
|
regex.MULTILINE
|
||||||
),
|
),
|
||||||
regex.compile(
|
regex.compile(
|
||||||
@ -340,8 +347,8 @@ def truncate_pdf_main_engineering(input_path, output_folder, selection,logger,ou
|
|||||||
]
|
]
|
||||||
output_suffix = "tobidders_notice"
|
output_suffix = "tobidders_notice"
|
||||||
elif selection == 5:
|
elif selection == 5:
|
||||||
begin_page=last_begin_index
|
begin_page = last_begin_index
|
||||||
invalid_path = get_invalid_file(file_path,output_folder,common_header,begin_page)
|
invalid_path = get_invalid_file(file_path, output_folder, common_header, begin_page)
|
||||||
if invalid_path:
|
if invalid_path:
|
||||||
return [invalid_path]
|
return [invalid_path]
|
||||||
else:
|
else:
|
||||||
@ -432,17 +439,18 @@ def truncate_pdf_main_engineering(input_path, output_folder, selection,logger,ou
|
|||||||
print(f"Error in truncate_pdf_main_goods: {e}")
|
print(f"Error in truncate_pdf_main_goods: {e}")
|
||||||
return [""] * (2 if selection == 4 else 1)
|
return [""] * (2 if selection == 4 else 1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logger=get_global_logger("123")
|
logger = get_global_logger("123")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
# input_path = r"C:\Users\Administrator\Desktop\new招标文件\工程标"
|
# input_path = r"C:\Users\Administrator\Desktop\new招标文件\工程标"
|
||||||
pdf_path=r"C:\Users\Administrator\Desktop\fsdownload\305c1fea-e0bd-4135-955f-38fb46388166\ztbfile.pdf"
|
pdf_path = r"C:\Users\Administrator\Desktop\工程\test\2022-广东-鹏华基金管理有限公司深圳深业上城办公室装修项目.pdf"
|
||||||
|
|
||||||
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件\招标02.pdf"
|
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件\招标02.pdf"
|
||||||
# input_path=r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
|
# input_path=r"C:\Users\Administrator\Desktop\招标文件\招标test文件夹\zbtest8.pdf"
|
||||||
output_folder = r"C:\Users\Administrator\Desktop\fsdownload\305c1fea-e0bd-4135-955f-38fb46388166\tmp"
|
output_folder = r"C:\Users\Administrator\Desktop\fsdownload\305c1fea-e0bd-4135-955f-38fb46388166\tmp"
|
||||||
selection = 5 # 例如:1 - 招标公告, 2 - 评标办法, 3 -资格审查条件 4-投标人须知前附表+正文 5-无效标
|
selection = 5 # 例如:1 - 招标公告, 2 - 评标办法, 3 -资格审查条件 4-投标人须知前附表+正文 5-无效标
|
||||||
generated_files = truncate_pdf_main_engineering(pdf_path, output_folder, selection,logger)
|
generated_files = truncate_pdf_main_engineering(pdf_path, output_folder, selection, logger)
|
||||||
print(generated_files)
|
print(generated_files)
|
||||||
# print("生成的文件:", generated_files)
|
# print("生成的文件:", generated_files)
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
|
@ -4,7 +4,7 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
from flask_app.general.json_utils import clean_json_string, add_outer_key
|
from flask_app.general.json_utils import clean_json_string, add_outer_key
|
||||||
from flask_app.general.通用功能函数 import process_judge_questions, aggregate_basic_info
|
from flask_app.general.通用功能函数 import process_judge_questions, aggregate_basic_info, get_deviation_requirements
|
||||||
from flask_app.general.多线程提问 import read_questions_from_file, multi_threading
|
from flask_app.general.多线程提问 import read_questions_from_file, multi_threading
|
||||||
from flask_app.general.通义千问long import upload_file
|
from flask_app.general.通义千问long import upload_file
|
||||||
from flask_app.工程标.判断是否分包等 import merge_json_to_list
|
from flask_app.工程标.判断是否分包等 import merge_json_to_list
|
||||||
@ -12,24 +12,21 @@ from flask_app.general.投标人须知正文提取指定内容 import extract_fr
|
|||||||
from flask_app.货物标.提取采购需求main import fetch_procurement_reqs
|
from flask_app.货物标.提取采购需求main import fetch_procurement_reqs
|
||||||
|
|
||||||
|
|
||||||
def get_base_info(merged_baseinfo_path,clause_path):
|
def get_base_info(merged_baseinfo_path,clause_path,invalid_path):
|
||||||
file_id = upload_file(merged_baseinfo_path)
|
file_id = upload_file(merged_baseinfo_path)
|
||||||
baseinfo_file_path='flask_app/static/提示词/基本信息货物标.txt'
|
baseinfo_file_path='flask_app/static/提示词/基本信息货物标.txt'
|
||||||
# baseinfo_file_path = r'D:\flask_project\flask_app\static\提示词\基本信息货物标.txt'
|
# baseinfo_file_path = r'D:\flask_project\flask_app\static\提示词\基本信息货物标.txt'
|
||||||
questions = read_questions_from_file(baseinfo_file_path)
|
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_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 []
|
baseinfo_list = [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else []
|
||||||
chosen_numbers, merged = merge_json_to_list(baseinfo_list.pop())
|
chosen_numbers, merged = merge_json_to_list(baseinfo_list.pop()) #取出并处理最后一个回答 '是否xxx'
|
||||||
baseinfo_list.append(merged)
|
baseinfo_list.append(merged)
|
||||||
judge_file_path = 'flask_app/static/提示词/是否相关问题.txt'
|
judge_file_path = 'flask_app/static/提示词/是否相关问题.txt'
|
||||||
# judge_file_path =r'D:\flask_project\flask_app\static\提示词\是否相关问题.txt'
|
# judge_file_path =r'D:\flask_project\flask_app\static\提示词\是否相关问题.txt'
|
||||||
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
||||||
# 提交两个任务
|
# 提交两个任务
|
||||||
future1 = executor.submit(process_judge_questions, judge_file_path, chosen_numbers, file_id,
|
future1 = executor.submit(process_judge_questions, judge_file_path, chosen_numbers, invalid_path,baseinfo_list)
|
||||||
baseinfo_list)
|
future2 = executor.submit(extract_from_notice, merged_baseinfo_path, clause_path, 3) #重新招标
|
||||||
future2 = executor.submit(extract_from_notice, merged_baseinfo_path, clause_path, 3) # 新增的多线程任务
|
|
||||||
|
|
||||||
# 等待两个任务完成并获取结果
|
# 等待两个任务完成并获取结果
|
||||||
future1.result() # process_judge_questions 直接修改 baseinfo_list,不需要返回值
|
future1.result() # process_judge_questions 直接修改 baseinfo_list,不需要返回值
|
||||||
@ -45,7 +42,7 @@ def combine_basic_info(merged_baseinfo_path, procurement_path,clause_path,invali
|
|||||||
# 定义一个线程函数来获取基础信息
|
# 定义一个线程函数来获取基础信息
|
||||||
def get_base_info_thread():
|
def get_base_info_thread():
|
||||||
nonlocal temp_list
|
nonlocal temp_list
|
||||||
temp_list = get_base_info(merged_baseinfo_path,clause_path)
|
temp_list = get_base_info(merged_baseinfo_path,clause_path,invalid_path)
|
||||||
# 定义一个线程函数来获取采购需求
|
# 定义一个线程函数来获取采购需求
|
||||||
def fetch_procurement_reqs_thread():
|
def fetch_procurement_reqs_thread():
|
||||||
nonlocal procurement_reqs
|
nonlocal procurement_reqs
|
||||||
@ -67,16 +64,16 @@ def combine_basic_info(merged_baseinfo_path, procurement_path,clause_path,invali
|
|||||||
|
|
||||||
return {"基础信息": aggregated_baseinfo}
|
return {"基础信息": aggregated_baseinfo}
|
||||||
|
|
||||||
|
#TODO:招标控制价50000怎么来的
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
start_time=time.time()
|
start_time=time.time()
|
||||||
# baseinfo_file_path = "C:\\Users\\Administrator\\Desktop\\货物标\\truncate_all\\ztbfile_merged_baseinfo\\ztbfile_merged_baseinfo_3-31.pdf"
|
# baseinfo_file_path = "C:\\Users\\Administrator\\Desktop\\货物标\\truncate_all\\ztbfile_merged_baseinfo\\ztbfile_merged_baseinfo_3-31.pdf"
|
||||||
merged_baseinfo_path=r"D:\flask_project\flask_app\static\output\output1\eabefc28-142f-4bb5-b1be-e86e43bb87b5\invalid_del.docx"
|
merged_baseinfo_path=r"D:\flask_project\flask_app\static\output\output1\3783ce68-1839-4449-97e6-cd07749d8664\ztbfile_merged_baseinfo.pdf"
|
||||||
# procurement_file_path = "C:\\Users\\Administrator\\Desktop\\fsdownload\\b4601ea1-f087-4fa2-88ae-336ad4d8e1e9\\tmp\\ztbfile_procurement.pdf"
|
# procurement_file_path = "C:\\Users\\Administrator\\Desktop\\fsdownload\\b4601ea1-f087-4fa2-88ae-336ad4d8e1e9\\tmp\\ztbfile_procurement.pdf"
|
||||||
procurement_file_path = r"D:\flask_project\flask_app\static\output\output1\83ae3e35-9136-4402-a74f-01d7adfcbb73\invalid_added.docx"
|
clause_path=r'D:\flask_project\flask_app\static\output\output1\3783ce68-1839-4449-97e6-cd07749d8664\clause1.json'
|
||||||
clause_path='D:\\flask_project\\flask_app\\static\\output\\output1\\bf225a5e-16d0-45c8-8c19-54a1a94cf3e2\\clause1.json'
|
invalid_path=r'D:\flask_project\flask_app\static\output\output1\3783ce68-1839-4449-97e6-cd07749d8664\invalid_del.docx'
|
||||||
# res = combine_basic_info(merged_baseinfo_path, procurement_file_path,clause_path)
|
# res = combine_basic_info(merged_baseinfo_path, procurement_file_path,clause_path)
|
||||||
res=get_base_info(merged_baseinfo_path,"")
|
res=combine_basic_info(merged_baseinfo_path,"",clause_path,invalid_path)
|
||||||
print("------------------------------------")
|
print("------------------------------------")
|
||||||
print(json.dumps(res, ensure_ascii=False, indent=4))
|
print(json.dumps(res, ensure_ascii=False, indent=4))
|
||||||
end_time=time.time()
|
end_time=time.time()
|
||||||
|
@ -93,14 +93,13 @@ def extract_pages(pdf_path, output_folder, begin_pattern, begin_page, end_patter
|
|||||||
print(f"Error processing {pdf_path}: {e}")
|
print(f"Error processing {pdf_path}: {e}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def get_patterns_for_procurement():
|
def get_patterns_for_procurement():
|
||||||
begin_pattern = regex.compile(
|
begin_pattern = regex.compile(
|
||||||
r'(?<!见\s*)(?<!与\s*)(?<!"\s*)(?<!“\s*)(?<!”\s*)'
|
r'(?<!见\s*)(?<!与\s*)(?<!"\s*)(?<!“\s*)(?<!”\s*)'
|
||||||
r'第[一二三四五六七八九十1-9]+(?:章|部分)\s*' # 匹配“第X章”或“第X部分”
|
r'第[一二三四五六七八九十1-9]+(?:章|部分)\s*(?!.*说明)' # 匹配“第X章”或“第X部分”
|
||||||
r'[\u4e00-\u9fff、()()]*?' # 匹配允许的字符
|
r'[\u4e00-\u9fff、()()]*?' # 匹配允许的字符
|
||||||
r'(?:(?:服务|项目|商务|技术|供货)[\u4e00-\u9fff、()()]*?要求[\u4e00-\u9fff、()()]*?\s*$|' # 匹配“服务”、“项目”、“商务”或“技术”后跟“要求”
|
r'(?:(?:服务|项目|商务|技术|供货)[\u4e00-\u9fff、()()]*?要求[\u4e00-\u9fff、()()]*?\s*$|' # 匹配“服务”、“项目”、“商务”或“技术”后跟“要求”
|
||||||
r'(?:(采购|招标)(?:内容|要求|需求))[\u4e00-\u9fff、()()]*?|'
|
r'(?:采购.*?(?:内容|要求|需求)?|招标(?:内容|要求|需求))[\u4e00-\u9fff、()()]*?|'
|
||||||
r'需求书[\u4e00-\u9fff、()()]*?)\s*$',
|
r'需求书[\u4e00-\u9fff、()()]*?)\s*$',
|
||||||
regex.MULTILINE
|
regex.MULTILINE
|
||||||
)
|
)
|
||||||
@ -526,7 +525,7 @@ def truncate_pdf_main_goods(input_path, output_folder, selection,logger, output_
|
|||||||
elif selection == 5:
|
elif selection == 5:
|
||||||
begin_pattern = regex.compile(
|
begin_pattern = regex.compile(
|
||||||
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(?:服务|项目|商务|技术|供货).*?要求|'
|
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(?:服务|项目|商务|技术|供货).*?要求|'
|
||||||
r'^第[一二三四五六七八九十百千]+(?:章|部分)(?!.*说明).*(?:(采购|招标)(?:内容|要求|需求)).*|'
|
r'^第[一二三四五六七八九十百千]+(?:章|部分)(?!.*说明).*(?:采购.*?(?:内容|要求|需求)?|招标(?:内容|要求|需求)).*|'
|
||||||
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?需求书'
|
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?需求书'
|
||||||
)
|
)
|
||||||
end_pattern = regex.compile(
|
end_pattern = regex.compile(
|
||||||
@ -613,10 +612,10 @@ if __name__ == "__main__":
|
|||||||
logger = get_global_logger("123")
|
logger = get_global_logger("123")
|
||||||
# input_path = r"C:\Users\Administrator\Desktop\new招标文件\货物标"
|
# input_path = r"C:\Users\Administrator\Desktop\new招标文件\货物标"
|
||||||
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件-采购类\2024-贵州-贵州医科大学附属医院导视系统零星制作安装项目.pdf"
|
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件-采购类\2024-贵州-贵州医科大学附属医院导视系统零星制作安装项目.pdf"
|
||||||
pdf_path=r"C:\Users\Administrator\Downloads\河北省承德监狱2025年供应站水果及干果采购项目招标文件(定).pdf"
|
pdf_path=r"D:\flask_project\flask_app\static\output\output1\a43b4a55-06c1-465d-afb3-5844695ad9d8\ztbfile.pdf"
|
||||||
# input_path = r"C:\Users\Administrator\Desktop\货物标\zbfiles\2-招标文件(广水市教育局封闭管理).pdf"
|
# input_path = r"C:\Users\Administrator\Desktop\货物标\zbfiles\2-招标文件(广水市教育局封闭管理).pdf"
|
||||||
# pdf_path=r"C:\Users\Administrator\Desktop\文件解析问题\文件解析问题\1414cb9c-7bf4-401c-8761-2acde151b9c2\ztbfile.pdf"
|
# pdf_path=r"C:\Users\Administrator\Desktop\文件解析问题\文件解析问题\1414cb9c-7bf4-401c-8761-2acde151b9c2\ztbfile.pdf"
|
||||||
output_folder = r"C:\Users\Administrator\Desktop\货物标\output55"
|
output_folder = r"D:\flask_project\flask_app\static\output\output1\a43b4a55-06c1-465d-afb3-5844695ad9d8\tmp"
|
||||||
# output_folder = r"C:\Users\Administrator\Desktop\new招标文件\output2"
|
# output_folder = r"C:\Users\Administrator\Desktop\new招标文件\output2"
|
||||||
selection = 5 # 例如:1 - 公告, 2 - 评标办法, 3 - 资格审查后缀有qualification1或qualification2(与评标办法一致) 4.投标人须知前附表part1 投标人须知正文part2 5-采购需求
|
selection = 5 # 例如:1 - 公告, 2 - 评标办法, 3 - 资格审查后缀有qualification1或qualification2(与评标办法一致) 4.投标人须知前附表part1 投标人须知正文part2 5-采购需求
|
||||||
generated_files = truncate_pdf_main_goods(pdf_path, output_folder, selection,logger)
|
generated_files = truncate_pdf_main_goods(pdf_path, output_folder, selection,logger)
|
||||||
|
@ -1,505 +0,0 @@
|
|||||||
#这是一份货物标中采购要求部分的内容,你需要摘取出采购清单,一个大系统(大项)中可能包含多个小系统(小项),你需要保留这种层次关系,给出名称和数量和单位,请以json格式返回,外层键名为"采购需求",如有未知内容,在对应键值处填"未知"。
|
|
||||||
|
|
||||||
#这是一份货物标中采购要求部分的内容,你需要摘取出需要采购的系统(货物),一个大系统(大项)中可能包含多个小系统(小项),小系统中也可能包含多个货物,你需要保留这种层次关系,给出货物名称,请以json格式返回,外层键名为"采购需求",嵌套键名为对应的系统名称或货物名称,无需给出采购数量和单位,如有未知内容,在对应键值处填"未知"。
|
|
||||||
|
|
||||||
"这是一份货物标中采购要求部分的内容,你需要摘取出需要采购的系统(货物),一个大系统(大项)中可能包含多个小系统(小项),你需要保留这种层次关系,给出系统(货物)名称,请以json格式返回,外层键名为\"采购需求\",嵌套键名为对应的系统名称或货物名称,无需给出采购数量和单位,如有未知内容,在对应键值处填\"未知\"。"
|
|
||||||
|
|
||||||
|
|
||||||
#这是一份货物标中采购要求部分的内容,请你给出所需的设备名称以及设备的具体型号参数要求,请以json格式返回结果,外层键名为采购要求。
|
|
||||||
这是一份货物标中采购要求部分的内容,请你给出\"{}\"的具体型号参数要求和数量,请以json格式返回结果,外层键名为\"{}\", 键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减。
|
|
||||||
#这是一份货物标中采购要求部分的内容,请你给出"网络硬盘录像机"的具体型号参数要求,请以json格式返回结果,外层键名为"网络硬盘录像机",键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减。
|
|
||||||
user_query1 = "这是一份货物标中采购要求部分的内容,请告诉我需要采购的系统(货物),如果有采购清单,请直接根据清单上的货物名称给出结果,若没有采购清单,你要从文中摘取需要采购的系统(货物),采购需求中可能包含层次关系,如大系统中包含若干子系统,你需要保留这种层次关系,给出系统(货物)名称,请以json格式返回,外层键名为\"采购需求\",嵌套键名为对应的系统名称或货物名称,需与原文保持一致,无需给出采购数量和单位,如有未知内容,在对应键值处填\"未知\"。"
|
|
||||||
|
|
||||||
|
|
||||||
这是一份货物标中采购要求部分的内容,请告诉我商务要求和其他要求是什么,请以json格式返回结果,外层键名分别是"商务要求"和"其他要求",内层键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减,注意你无需回答具体设备的技术要求,若相关要求不存在,在键值中填"未知"。
|
|
||||||
|
|
||||||
"该招标文件中规定的资格性审查标准是怎样的?请以json格式给出,外层为'资格性审查',对于原文中的序号,你需要捕获它们之间的层级关系并生成嵌套键值对,你的回答无需包含序号,但其余内容要与原文一致,不可擅自总结删减,也不要回答符合性审查的内容。"
|
|
||||||
该招标文件中规定的资格性审查标准是怎样的?请以json格式给出,外层为'资格性审查',你的回答要与原文一致,不可擅自总结删减,也不要回答资格性审查的内容。
|
|
||||||
"该招标文件中规定的资格性审查标准是怎样的?请以json格式给出,外层为'资格性审查',对于原文中的序号,你仅需要捕获它们之间的层级关系并根据序号后的内容生成嵌套键值对,若多个内容位于同一层级,你应用字符串列表作为键值保存这些内容,你的回答需删去这些序号,但其余内容要与原文一致,不可擅自总结删减,也不要回答符合性审查的内容。"
|
|
||||||
|
|
||||||
"根据该文档中的评标办法前附表,请你列出该文件的技术标,商务标,投标报价评审标准以及它们对应的具体评分要求,若对应内容中存在其他信息,在键名如'技术标'中新增子键名'备注'存放该信息。如果评分内容不是这3个,则返回文档中给定的评分内容以及它的评分要求,都以json的格式返回结果。请不要回答有关形式、资格、响应性评审标准的内容")
|
|
||||||
|
|
||||||
"以上是从招标文件中摘取的内容,文本内之间的信息以'...............'分割,请你根据该内容回答:投标人或中标人或联合体各方或供应商不得存在的情况有哪些?请不要回答有关采购人或评标委员会不得存在的情况,请你准确筛选符合的信息并将它的序号返回。请以[x,x,x]格式返回给我结果,示例返回为[1,4,6],若情况不存在,返回[]。",
|
|
||||||
|
|
||||||
"以上是从招标文件中摘取的内容,文本内之间的信息以'...............'分割,每条信息规定了各方不得存在的情形,请回答:在这些信息中,主语是投标人或供应商或联合体投标各方或中标人的信息有哪些?不要返回主语是采购人或评标委员会的信息,请你准确筛选所需的信息并将它的序号返回。请以[x,x,x]格式返回给我结果,示例返回为[1,4,6],若情况不存在,返回[]。",
|
|
||||||
|
|
||||||
|
|
||||||
--- 营业执照 ---
|
|
||||||
该文件为投标文件格式要求,请你根据该招标文件回答:营业执照应该附在哪个地方?你可能需要查找以下章节出现的地方:'具有独立承担民事责任能力的法人', '投标人基本信息表', '法人或者其他组织的营业执照等证明文件,自然人的身份证明', '投标人情况介绍', '投标人简介', '企业相关证件',并确定所在章节。
|
|
||||||
我需要将营业执照贴在该章节的最后面,目前我需要定位到插入的位置,请你返回给我插入位置的上下文,字数限制在30字以内,以json格式返回,键名分别是'上文','下文',上下文格式内容应完全与原文保持一致,不得擅自删减总结,示例输出如下:
|
|
||||||
{
|
|
||||||
"上文":"投标人: (盖单位章)
|
|
||||||
年 月 日",
|
|
||||||
"下文":"四、投标保证金
|
|
||||||
(招标人名称):"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template = f"""这是投标文件模板,作为投标人,我需要把不同的投标材料填充到对应位置,请你根据该文件回答:{target}应该附在该文件哪个地方?以下是可能匹配的章节名称:{', '.join([f"'{chapter}'" for chapter in chapters])};或者可能匹配的关键字:{', '.join([f"'{kw}'" for kw in keywords])},你需要根据投标文件要求确定{target}需要插入的位置,请你返回给我插入位置的上下文内容,以便于我定位原文,上文是插入章节或小节末尾的内容,下文应该是下一章节或下一小节开头的内容,上下文合在一起应该是连续的,字数都限制在20字以内。你的回答以json格式返回,键名分别是'上文','下文',上下文内容应完全与原文保持一致,不得擅自删减总结,输出格式示例如下:
|
|
||||||
{{
|
|
||||||
{target}:{{
|
|
||||||
"上文":"上文测试投标人: (盖单位章)
|
|
||||||
年 月 日",
|
|
||||||
"下文":"下文测试章节名
|
|
||||||
(招标人名称):测试"
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
"""
|
|
||||||
|
|
||||||
{
|
|
||||||
"采购需求": {
|
|
||||||
"硬盘录像机 A": {},
|
|
||||||
"硬盘录像机 B": {},
|
|
||||||
"高清摄像机枪机": {},
|
|
||||||
"支架、防水盒": {},
|
|
||||||
"交换机": {},
|
|
||||||
"光模块": {},
|
|
||||||
"光纤尾纤": {},
|
|
||||||
"安装辅材": {},
|
|
||||||
"视频监控组网专线电路租赁": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"采购需求": {
|
|
||||||
"多媒体会议厅设备": {
|
|
||||||
"LED屏显示设备": {
|
|
||||||
"LED显示屏系统": "未知",
|
|
||||||
"户内全彩 LED屏": "未知",
|
|
||||||
"发送盒": "未知",
|
|
||||||
"LED显示屏控制系统": "未知",
|
|
||||||
"视频处理器": "未知",
|
|
||||||
"智能配电柜": "未知",
|
|
||||||
"台式电脑": "未知",
|
|
||||||
"控制桌": "未知",
|
|
||||||
"LED显示屏施工材料、技术服务费、包装费": {
|
|
||||||
"结构边框": "未知",
|
|
||||||
"线材": "未知",
|
|
||||||
"包装材料": "未知"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"扩声系统": {
|
|
||||||
"主扩全频专业音箱": "未知",
|
|
||||||
"专业功放": "未知",
|
|
||||||
"辅助专业音箱": "未知",
|
|
||||||
"壁挂支架": "未知",
|
|
||||||
"返听专业音箱": "未知",
|
|
||||||
"返听专业功放": "未知",
|
|
||||||
"超低频专业音箱": "未知",
|
|
||||||
"音箱地插": "未知",
|
|
||||||
"调音台": "未知",
|
|
||||||
"音频处理器": "未知",
|
|
||||||
"抑制器": "未知",
|
|
||||||
"无线话筒": "未知",
|
|
||||||
"话筒呼叫控制嵌入软件": "未知",
|
|
||||||
"天线分配器": "未知",
|
|
||||||
"有源监听音箱": "未知",
|
|
||||||
"电源时序器": "未知",
|
|
||||||
"辅助材料": {
|
|
||||||
"机柜": "未知",
|
|
||||||
"音频连接线": "未知",
|
|
||||||
"其它辅材": "未知"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"会议座椅": "未知",
|
|
||||||
"电动窗帘": "未知"
|
|
||||||
},
|
|
||||||
"云平台及备课电脑": {
|
|
||||||
"备课一体机电脑": "未知",
|
|
||||||
"云平台管理软件": "未知",
|
|
||||||
"教学互动应用软件": "未知"
|
|
||||||
},
|
|
||||||
"办公桌椅": "未知",
|
|
||||||
"文件柜": "未知",
|
|
||||||
"体育运动器材": {
|
|
||||||
"移动式标准篮球架": "未知"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
"采购需求": {
|
|
||||||
"第一包": {
|
|
||||||
"办公电子设备": [
|
|
||||||
"服务器",
|
|
||||||
"台式计算机",
|
|
||||||
"便携式计算机",
|
|
||||||
"信息安全设备",
|
|
||||||
"喷墨打印机",
|
|
||||||
"激光打印机",
|
|
||||||
"针式打印机",
|
|
||||||
"液晶显示器",
|
|
||||||
"扫描仪",
|
|
||||||
"基础软件",
|
|
||||||
"信息安全软件",
|
|
||||||
"复印机",
|
|
||||||
"投影仪",
|
|
||||||
"多功能一体机",
|
|
||||||
"触控一体机",
|
|
||||||
"碎纸机"
|
|
||||||
],
|
|
||||||
"软件": [
|
|
||||||
"基础软件",
|
|
||||||
"信息安全软件"
|
|
||||||
],
|
|
||||||
"耗材": [
|
|
||||||
"复印纸"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"第二包": {
|
|
||||||
"办公家电": [
|
|
||||||
"空调机"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"第三包": {
|
|
||||||
"家具用具": [
|
|
||||||
"床类",
|
|
||||||
"台、桌类",
|
|
||||||
"椅凳类",
|
|
||||||
"沙发类",
|
|
||||||
"柜类",
|
|
||||||
"架类",
|
|
||||||
"屏风类",
|
|
||||||
"厨卫用具",
|
|
||||||
"组合家具",
|
|
||||||
"家用家具零配件",
|
|
||||||
"其他家具用具"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"第四包": {
|
|
||||||
"印刷服务": "未知"
|
|
||||||
},
|
|
||||||
"第五包": {
|
|
||||||
"汽车维修和保养服务": "未知"
|
|
||||||
},
|
|
||||||
"第六包": {
|
|
||||||
"会计服务": "未知"
|
|
||||||
},
|
|
||||||
"第七包": {
|
|
||||||
"工程造价咨询服务": "未知"
|
|
||||||
},
|
|
||||||
"第八包": {
|
|
||||||
"机动车保险服务": "未知"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"子项xxx": [
|
|
||||||
{
|
|
||||||
"内容": "1. 国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的,则必须提供取得国家有关主管部门行政许可的证明材料。"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容": "2. 未被列入”信用中国“网站(www.creditchina.gov.cn)信用服务栏失信被执行人、重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单和”中国政府采购“网站(www.ccgp.gov.cn)政府采购严重违法失信行为记录名单,并提供网页截图以证明;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容": "3. 招标文件第一章”投标人资格要求“中有特殊要求的,投标人应提供其符合特殊要求的证明材料或者情况说明;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容": "4. 不符合联合体投标相关规定和要求的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容": "5. 投标人认为需提供的其它相关资格证明材料;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"内容": "6. 资格证明文件正本应为清晰彩色影印件且加盖单位公章。"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
input_data = {
|
|
||||||
"资格性审查": {
|
|
||||||
"1": {
|
|
||||||
"参加政府采购活动的供应商应当具备政府采购法第二十二条第一款规定的条件,提供下列材料": {
|
|
||||||
"1.1": "法人或者其他组织的营业执照等证明文件,自然人身份证明",
|
|
||||||
"1.2": "财务状况报告,依法缴纳税收和社会保障资金的相关资料",
|
|
||||||
"1.3": "具备履行合同所必需的设备和专业技术能力的证明材料",
|
|
||||||
"1.4": "参加政府采购活动前 3 年内在经营活动中没有重大违法记录的书面声明",
|
|
||||||
"1.5": "具备法律、行政法规规定的其他条件的证明材料"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"2": "单位负责人为同一人或者存在直接控股、管理关系的不同投标人,不得参加本项目同一合同项下的政府采购活动",
|
|
||||||
"3": "为本采购项目提供整体设计、规范编制或者项目管理、监理、检测等服务的,不得再参加本项目的其他招标采购活动",
|
|
||||||
"4": "未被列入”信用中国“网站(www.creditchina.gov.cn)失信被执行人、重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单的书面声明",
|
|
||||||
"5": "法定代表人携法定代表人身份证明和本人身份证原件或委托代理人携法定代表人授权委托书和本人身份证原件及委托人在本公司近三个月的缴纳社保证明"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"资格性审查": {
|
|
||||||
"资格证明文件审查说明": "资格审查内容要求提供的相关证明材料,投标人应对应放入投标文件的“第一部分资格证明文件”中,否则,将会导致投标无效。所递交的资格证明文件出现不符合下列情形之一或不足以证明其符合下列情形之一的,应视为资格审查不合格,并按照无效投标处理。",
|
|
||||||
"应具备《政府采购法》第二十二条第一款规定的条件": {
|
|
||||||
"提供下列材料": {
|
|
||||||
"法人或者其他组织的营业执照等证明文件": {
|
|
||||||
"法人": {
|
|
||||||
"(1)企业法人(包括合伙企业)": "提供工商部门注册的有效“企业法人营业执照”或“营业执照”;",
|
|
||||||
"(2)事业单位法人": "提供有效的“事业单位法人证书”。"
|
|
||||||
},
|
|
||||||
"其他组织": {
|
|
||||||
"(1)非企业专业服务机构": "提供执业许可证等证明文件;",
|
|
||||||
"(2)个体工商户": "提供有效的“个体工商户营业执照”。"
|
|
||||||
},
|
|
||||||
"自然人": "提供有效的自然人身份证明。(仅限中国公民)"
|
|
||||||
},
|
|
||||||
"财务状况报告": "依法缴纳税收和社会保障资金的相关材料:应严格按照附件格式提交“财务状况报告,依法缴纳税收和社会保障资金的声明函”",
|
|
||||||
"具备履行合同所必需的设备和专业技术能力的证明材料": {
|
|
||||||
"1.3.1": "提供具备足够数量的设施设备的证明材料;",
|
|
||||||
"1.3.2": "提供具备足够数量的技术人员的证明材料。"
|
|
||||||
},
|
|
||||||
"参加政府采购活动前 3年内在经营活动中没有重大违法记录的声明": {
|
|
||||||
"1.4.1": "应严格按照附件格式提交“无重大违法记录的声明函”;",
|
|
||||||
"1.4.2": "政府采购法第二十二条第一款第五项所称重大违法记录,是指供应商因违法经营受到刑事处罚或者责令停产停业、吊销许可证或者执照、较大数额罚款等行政处罚;",
|
|
||||||
"1.4.3": "按照财政部《关于规范政府采购行政处罚有关问题的通知》的规定,各级人民政府财政部门依法对参加政府采购活动的供应商作出的禁止参加政府采购活动等行政处罚决定在全国范围内生效。"
|
|
||||||
},
|
|
||||||
"具备法律、行政法规规定的其他条件的证明材料": {
|
|
||||||
"1.5.1": "国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的,则必须提供取得国家有关主管部门行政许可的证明材料。"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"单位负责人为同一人或者存在直接控股、管理关系的不同投标人": "不得参加本项目同一合同项下的政府采购活动;应严格按照附件格式提交“未与单位负责人为同一人或者存在直接控股、管理关系 的其它投标人,参加同一合同项下的政府采购活动声明函”",
|
|
||||||
"为本采购项目提供整体设计、规范编制或者项目管理、监理、检测等服务的": "不得再参加本项目的其他招标采购活动;应严格按照附件格式提交“未为本采购项目提供整体设计、规范编制或者项目管理、 监理、检测等服务的声明函”",
|
|
||||||
"未被“信用中国”网站(www.creditchina.gov.cn)、“中国政府采购网”(www.ccgp.gov.cn)": "列入失信被执行人、重大税收违法案件当事人名单、政府采购严重违法失信行为记 录名单:应严格按照附件格式提交“未被列入记录名单的声明函”",
|
|
||||||
"落实政府采购政策应提供的资料": "",
|
|
||||||
"招标文件第一章“投标人资格要求”中有特殊要求的": "投标人应提供其符合特殊要 求的证明材料或者情况说明:",
|
|
||||||
"投标人认为需提供的其它相关资格证明材料": "",
|
|
||||||
"资格证明文件应为清晰影印件且加盖单位公章": ""
|
|
||||||
},
|
|
||||||
"符合性审查": {
|
|
||||||
"说明": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。",
|
|
||||||
"审查标准": [
|
|
||||||
{
|
|
||||||
"序号": 1,
|
|
||||||
"内容": "投标总报价超过项目(分包)预算金额或最高限价的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 2,
|
|
||||||
"内容": "《投标书》、《法定代表人授权书》、《开标一览表(含明细)》未提供或不符合招标文件要求的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 3,
|
|
||||||
"内容": "工期(服务期限)、质保期不符合招标文件要求的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 4,
|
|
||||||
"内容": "出现两个或两个以上不同报价的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 5,
|
|
||||||
"内容": "出现两个或两个以上投标方案的(招标文件中要求提供备选方案的除外);"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 6,
|
|
||||||
"内容": "投标报价存在缺项、漏项的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 7,
|
|
||||||
"内容": "投标有效期不足的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 8,
|
|
||||||
"内容": "无法定代表人签字(签章)或签字人无法定代表人有效授权的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 9,
|
|
||||||
"内容": "未按要求提供加盖公章及签字(签章)的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 10,
|
|
||||||
"内容": "符合招标文件第二章“投标人须知”中 39条中规定情形,以分公司形式参与投标的,法定代表人授权书未由总公司法定代表人签字(签章)并加盖公章的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 11,
|
|
||||||
"内容": "依据财库[2019]9号文的规定,招标文件采购清单中为“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 12,
|
|
||||||
"内容": "所投货物是通过中国海关报关验放进入中国境内且产自关境外的(招标文件中注明已办理进口产品审核的除外);"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 13,
|
|
||||||
"内容": "未提供所投货物(工程或服务)的具体参数值或功能表述,或原文复制招标文件的技术规格相关部分内容作为其投标文件的一部分的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 14,
|
|
||||||
"内容": "不满足招标文件第三章“项目技术、服务和商务要求”中“★”号条款要求的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 15,
|
|
||||||
"内容": "含有采购人不能接受的附加条件的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 16,
|
|
||||||
"内容": "未按要求提供《符合性审查对照表》、《商务要求响应、偏离说明表》、《商务要求“★”号条款响应、偏离说明表》、《商务评议对照表》和《技术、服务要求响应、偏离说明表》、《技术、服务要求“★”号条款响应、偏离说明表》、《技术、服务评议对照表》的;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 17,
|
|
||||||
"内容": "不同投标人使用同一电脑(机器特征值一致:如 MAC地址等)或使用同一电子密钥,编制或上传电子投标文件;"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"序号": 18,
|
|
||||||
"内容": "法律、法规和招标文件规定的其他无效投标情形。"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"资格性审查": {
|
|
||||||
"资格证明文件审查": {
|
|
||||||
"法人或者其他组织的营业执照等证明文件": {
|
|
||||||
"法人": {
|
|
||||||
"企业法人(包括合伙企业)": "提供工商部门注册的有效“企业法人营业执照” 或“营业执照”",
|
|
||||||
"事业单位法人": "提供有效的“事业单位法人证书”"
|
|
||||||
},
|
|
||||||
"其他组织": {
|
|
||||||
"非企业专业服务机构": "提供执业许可证等证明文件",
|
|
||||||
"个体工商户": "提供有效的“个体工商户营业执照”"
|
|
||||||
},
|
|
||||||
"自然人": "提供有效的自然人身份证明。(仅限中国公民)"
|
|
||||||
},
|
|
||||||
"财务状况报告": {
|
|
||||||
"法人": {
|
|
||||||
"提供经第三方审计的财务报告": "(完整的财务报告,包括“四表一注”, 即资产负债表、利润表、现金流量表、所有者权益变动表及其附注),或其基 本开户银行出具的资信证明"
|
|
||||||
},
|
|
||||||
"部分其他组织和自然人": "没有经第三方审计的财务报告的,可以提供银行出 具的资信证明",
|
|
||||||
"投标人没有经第三方审计的财务报告和资信证明时": "也可以提供财政部门认 可的政府采购专业担保机构出具的投标担保函"
|
|
||||||
},
|
|
||||||
"依法缴纳税收和社会保障资金的相关材料": {
|
|
||||||
"法人": {
|
|
||||||
"税务登记证(国税、地税或多证合一)": "",
|
|
||||||
"参加政府采购活动前一段时间内缴纳增值税、营业税和企业所得税的凭据": "",
|
|
||||||
"社会保险登记证(或多证合一)": "",
|
|
||||||
"参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)": ""
|
|
||||||
},
|
|
||||||
"其他组织和自然人": {
|
|
||||||
"参加政府采购活动前一段时间内缴纳税收的凭据": "",
|
|
||||||
"参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)": ""
|
|
||||||
},
|
|
||||||
"依法免税或不需要缴纳社会保险资金的投标人": "提供其依法免税或不需要缴纳社会保险资金的相关证明文件"
|
|
||||||
},
|
|
||||||
"具备履行合同所必需的设备和专业技术能力的证明材料": {
|
|
||||||
"提供具备足够数量的设施设备的证明材料": "",
|
|
||||||
"提供具备足够数量的技术人员的证明材料": ""
|
|
||||||
},
|
|
||||||
"参加政府采购活动前 3年内在经营活动中没有重大违法记录的书面声明": {
|
|
||||||
"应严格按照附件格式提交“参加政府采购活动前三年内在经营活动中没有重大 违法记录的书面声明函”": "",
|
|
||||||
"政府采购法第二十二条第一款第五项所称重大违法记录": "是指供应商因违法经 营受到刑事处罚或者责令停产停业、吊销许可证或者执照、较大数额罚款等行政处罚",
|
|
||||||
"按照财政部《关于规范政府采购行政处罚有关问题的通知》的规定": "各级人民 政府财政部门依法对参加政府采购活动的供应商作出的禁止参加政府采购活动等行政 处罚决定在全国范围内生效"
|
|
||||||
},
|
|
||||||
"具备法律、行政法规规定的其他条件的证明材料": {
|
|
||||||
"国家对生产和销售相关产品或提供相关服务有专门法律、行政法规规定的": "则 必须提供取得国家有关主管部门行政许可的证明材料",
|
|
||||||
"未被列入“信用中国”网站(www.creditchina.gov.cn)信用服务栏失信被执行人、 重大税收违法案件当事人名单、政府采购严重违法失信行为记录名单和“中国 政府采购”网站(www.ccgp.gov.cn)政府采购严重违法失信行为记录名单": "并 提供网页截图以证明",
|
|
||||||
"招标文件第一章“投标人资格要求”中有特殊要求的": "投标人应提供其符合特 殊要求的证明材料或者情况说明",
|
|
||||||
"不符合联合体投标相关规定和要求的": "",
|
|
||||||
"投标人认为需提供的其它相关资格证明材料": "",
|
|
||||||
"资格证明文件正本应为清晰彩色影印件且加盖单位公章": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"符合性审查": {
|
|
||||||
"描述": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。",
|
|
||||||
"无效投标处理情形": [
|
|
||||||
"投标总报价超过项目(分包)预算金额或最高限价的",
|
|
||||||
"《投标书》、《法定代表人授权书》、《开标一览表》、《投标报价明细表》未提供或不符合招标文件要求的",
|
|
||||||
"工期(服务期限)、质保期不符合招标文件要求的",
|
|
||||||
"出现两个或两个以上不同报价的",
|
|
||||||
"出现两个或两个以上投标方案的(招标文件中要求提供备选方案的除外)",
|
|
||||||
"投标报价存在缺项、漏项的",
|
|
||||||
"投标有效期不足的",
|
|
||||||
"无法定代表人签字(签章)或签字人无法定代表人有效授权的",
|
|
||||||
"正本未按要求提供加盖公章及签字(签章)原件的",
|
|
||||||
"符合招标文件第二章“投标人须知”中 40条中规定情形,以分公司形式参与投标的,法定代表人授权书未由总公司法定代表人签字(签章)并加盖公章的",
|
|
||||||
"未按要求提供招标文件第二章“十、其他注意事项”中规定的书面声明的",
|
|
||||||
"所投货物是通过中国海关报关验放进入中国境内且产自关境外的(招标文件中注明已办理进口产品审核的除外)",
|
|
||||||
"依据财库[2019]9号文的规定,招标文件采购清单中注明“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的",
|
|
||||||
"未提供所投货物(工程或服务)的具体参数值或功能表述,或完全原文复制招标文件的技术规格相关部分内容作为其投标文件的一部分的",
|
|
||||||
"不满足招标文件第三章“项目技术、服务和商务要求”中“★”号条款要求的",
|
|
||||||
"含有采购人不能接受的附加条件的",
|
|
||||||
"未按要求提供《符合性审查对照表》、《商务要求响应、偏离说明表》、《商务要求“★”号条款响应、偏离说明表》、《商务评议对照表》和《技术、服务要求响应、偏离说明表》、《技术、服务要求“★”号条款响应、偏离说明表》、《技术、服务评议对照表》的",
|
|
||||||
"法律、法规和招标文件规定的其他无效投标情形"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"资格性审查": {
|
|
||||||
"资格证明文件审查": [
|
|
||||||
[
|
|
||||||
"应具备《政府采购法》第二十二条第一款规定的条件,提供下列材料:"
|
|
||||||
],
|
|
||||||
{
|
|
||||||
"法人或者其他组织的营业执照等证明文件,自然人的身份证明(投标人根据自身情况提供对应的证明材料)": [
|
|
||||||
{
|
|
||||||
"法人": [
|
|
||||||
"企业法人(包括合伙企业):提供工商部门注册的有效“企业法人营业执照” 或“营业执照”;",
|
|
||||||
"事业单位法人:提供有效的“事业单位法人证书”。"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"其他组织": [
|
|
||||||
"非企业专业服务机构:提供执业许可证等证明文件;",
|
|
||||||
"个体工商户:提供有效的“个体工商户营业执照”。"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"自然人:提供有效的自然人身份证明。(仅限中国公民)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"财务状况报告,依法缴纳税收和社会保障资金的相关材料(投标人根据自身情况提供对应的证明材料)": [
|
|
||||||
{
|
|
||||||
"法人": [
|
|
||||||
"税务登记证(国税、地税或多证合一);",
|
|
||||||
"参加政府采购活动前一段时间内缴纳增值税、营业税和企业所得税的凭据;",
|
|
||||||
"社会保险登记证(或多证合一);",
|
|
||||||
"参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)。"
|
|
||||||
],
|
|
||||||
"其他组织和自然人": [
|
|
||||||
"参加政府采购活动前一段时间内缴纳税收的凭据;",
|
|
||||||
"参加政府采购活动前一段时间内缴纳社会保险的凭据(专用收据或社会保险 缴纳清单)。"
|
|
||||||
],
|
|
||||||
"依法免税或不需要缴纳社会保险资金的投标人": "提供其依法免税或不需要缴纳社会保险资金的相关证明文件。"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"具备履行合同所必需的设备和专业技术能力的证明材料": [
|
|
||||||
"提供具备足够数量的设施设备的证明材料;",
|
|
||||||
"提供具备足够数量的技术人员的证明材料。"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"参加政府采购活动前 3年内在经营活动中没有重大违法记录的书面声明": [
|
|
||||||
"应严格按照附件格式提交“参加政府采购活动前三年内在经营活动中没有重大 违法记录的书面声明函”;",
|
|
||||||
"政府采购法第二十二条第一款第五项所称重大违法记录,是指供应商因违法经 营受到刑事处罚或者责令停产停业、吊销许可证或者执照、较大数额罚款等行政处罚;",
|
|
||||||
"按照财政部《关于规范政府采购行政处罚有关问题的通知》的规定,各级人民 政府财政部门依法对参加政府采购活动的供应商作出的禁止参加政府采购活动等行政 处罚决定在全国范围内生效。"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"具备法律、行政法规规定的其他条件的证明材料:"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"符合性审查": {
|
|
||||||
"描述": "评标委员会应当对符合资格的投标人的投标文件进行符合性审查,以确定其是否满足招标文件的实质性要求。",
|
|
||||||
"无效投标处理情形": [
|
|
||||||
"投标总报价超过项目(分包)预算金额或最高限价的",
|
|
||||||
"《投标书》、《法定代表人授权书》、《开标一览表》、《投标报价明细表》未提供或不符合招标文件要求的",
|
|
||||||
"工期(服务期限)、质保期不符合招标文件要求的",
|
|
||||||
"出现两个或两个以上不同报价的",
|
|
||||||
"出现两个或两个以上投标方案的(招标文件中要求提供备选方案的除外)",
|
|
||||||
"投标报价存在缺项、漏项的",
|
|
||||||
"投标有效期不足的",
|
|
||||||
"无法定代表人签字(签章)或签字人无法定代表人有效授权的",
|
|
||||||
"正本未按要求提供加盖公章及签字(签章)原件的",
|
|
||||||
"符合招标文件第二章“投标人须知”中 40条中规定情形,以分公司形式参与投标的,法定代表人授权书未由总公司法定代表人签字(签章)并加盖公章的",
|
|
||||||
"未按要求提供招标文件第二章“十、其他注意事项”中规定的书面声明的",
|
|
||||||
"所投货物是通过中国海关报关验放进入中国境内且产自关境外的(招标文件中注明已办理进口产品审核的除外)",
|
|
||||||
"依据财库[2019]9号文的规定,招标文件采购清单中注明“节能产品”的货物,未提供国家确定的认证机构出具的节能产品认证证书的",
|
|
||||||
"未提供所投货物(工程或服务)的具体参数值或功能表述,或完全原文复制招标文件的技术规格相关部分内容作为其投标文件的一部分的",
|
|
||||||
"不满足招标文件第三章“项目技术、服务和商务要求”中“★”号条款要求的",
|
|
||||||
"含有采购人不能接受的附加条件的",
|
|
||||||
"未按要求提供《符合性审查对照表》、《商务要求响应、偏离说明表》、《商务要求“★”号条款响应、偏离说明表》、《商务评议对照表》和《技术、服务要求响应、偏离说明表》、《技术、服务要求“★”号条款响应、偏离说明表》、《技术、服务评议对照表》的",
|
|
||||||
"法律、法规和招标文件规定的其他无效投标情形"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user