zbparse/flask_app/main/基础信息整合快速版.py
2024-10-19 12:53:25 +08:00

250 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import threading
import time
from flask_app.main.json_utils import clean_json_string, nest_json_under_key,rename_outer_key
from flask_app.main.投标人须知正文提取指定内容 import extract_from_notice
from flask_app.main.判断是否分包等 import judge_whether_main, read_questions_from_judge, merge_json_to_list
from flask_app.main.多线程提问 import read_questions_from_file, multi_threading
from flask_app.main.通义千问long import upload_file
def aggregate_basic_info_engineering(baseinfo_list):
"""
将基础信息列表中的数据进行合并和分类。
参数:
- baseinfo_list (list): 包含多个基础信息的列表。
返回:
- dict: 合并和分类后的基础信息字典。
"""
key_groups = {
"招标人/代理信息": ["招标人", "招标人联系方式", "招标代理机构", "招标代理机构联系方式"],
"项目信息": ["项目名称", "招标编号", "项目概况", "招标范围", "招标控制价", "投标竞争下浮率"],
"关键时间/内容": [
"投标文件递交截止日期",
"投标文件递交方式",
"开标时间",
"开标地点",
"投标人要求澄清招标文件的截止时间",
"投标有效期",
"评标结果公示媒介"
],
"保证金相关": ["质量保证金", "退还投标保证金"],
"其他信息": [
"重新招标、不再招标和终止招标",
"投标费用承担",
"招标代理服务费",
"是否退还投标文件",
]
}
combined_data = {}
relevant_keys_detected = set()
# 合并所有基础信息并收集相关键
for baseinfo in baseinfo_list:
combined_data.update(baseinfo)
relevant_keys_detected.update(baseinfo.keys())
# 动态调整键组
dynamic_key_handling(key_groups, relevant_keys_detected)
# 创建一个副本以存储未分类的项目
unclassified_items = {k: v for k, v in combined_data.items() if k not in [item for sublist in key_groups.values() for item in sublist]}
# 按键组分类并嵌套
for group_name, keys in key_groups.items():
group_data = {key: combined_data.get(key, "未提供") for key in keys}
combined_data[group_name] = group_data
# 从 unclassified_items 中移除已分类的键
for key in keys:
unclassified_items.pop(key, None)
# 将剩余未分类的键值对添加到 "其他信息" 组
combined_data["其他信息"].update(unclassified_items)
# 移除顶层的未分类键值对
for key in list(combined_data.keys()):
if key not in key_groups:
del combined_data[key]
return combined_data
def dynamic_key_handling(key_groups, detected_keys):
# 检查和调整键组配置
for key in detected_keys:
# 处理“保证金相关”组,插到"质量保证金"前
if "保证金" in key:
group = key_groups["保证金相关"]
insert_before = "质量保证金"
if insert_before in group:
index = group.index(insert_before)
if key not in group: # 避免重复插入
group.insert(index, key)
else:
group.append(key) # 如果没有找到特定键,则追加到末尾
elif "联合体" in key:
key_groups["项目信息"].append(key)
elif "分包" in key:
key_groups["项目信息"].append(key)
elif "踏勘现场" in key:
key_groups["其他信息"].append(key)
elif "投标预备会" in key:
key_groups["其他信息"].append(key)
elif "偏离" in key:
key_groups["其他信息"].append(key)
def judge_consortium_bidding(baseinfo_list):
updated_list = []
accept_bidding = False
for baseinfo in baseinfo_list:
# 检查 "是否接受联合体投标" 键是否存在且其值为 "是"
if "是否接受联合体投标" in baseinfo and baseinfo["是否接受联合体投标"] == "":
accept_bidding = True
# 从字典中移除特定键值对
baseinfo.pop("是否接受联合体投标", None)
# # 将修改后的 json 数据转换回 JSON 字符串(如果需要)
# updated_info = json.dumps(json_data)
updated_list.append(baseinfo)
# 更新原始列表,如果你想保留修改
baseinfo_list[:] = updated_list
return accept_bidding
def generate_query(baseinfo_list):
questions_list = []
for item in baseinfo_list:
# print(json.dumps(item, ensure_ascii=False, indent=4))
for key, value in item.items():
if value == "未知" or (isinstance(value, dict) and all(v == "未知" for v in value.values())):
question = (
f"根据该招标文件中的信息,{key}的内容是怎样的?"
f"请按json格式给我提供信息键名是'{key}'"
f"若存在未知信息,在对应的键值中填'未知'"
)
questions_list.append(question)
return questions_list
def update_baseinfo_lists(baseinfo_list1, baseinfo_list2):
# 创建一个字典,用于存储 baseinfo_list1 中的所有键值对
combined_dict = {}
for item in baseinfo_list1:
combined_dict.update(item)
# 使用 baseinfo_list2 中的信息更新 combined_dict
for item in baseinfo_list2:
for key, value in item.items():
if key in combined_dict:
combined_dict[key] = value
# 重新构建 baseinfo_list1保持原有的结构
updated_list = []
for item in baseinfo_list1:
updated_item = {}
for key in item:
updated_item[key] = combined_dict[key]
updated_list.append(updated_item)
return updated_list
def process_judge_questions(judge_file_path, chosen_numbers, truncate0, baseinfo_list1):
judge_questions = read_questions_from_judge(judge_file_path, chosen_numbers)
judge_consortium = judge_consortium_bidding(baseinfo_list1)
if judge_consortium:
judge_consortium_question = (
"该招标文件对于联合体投标的要求是怎样的请按json格式给我提供信息"
"外层键名为'联合体投标要求',其中有一个嵌套键值对为:\"是否接受联合体投标\":\"\""
)
judge_questions.append(judge_consortium_question)
file_id3 = upload_file(truncate0)
res2 = multi_threading(judge_questions, "", file_id3, 2)
if not res2:
print("基础信息整合: multi_threading error!")
else:
for question, response in res2:
baseinfo_list1.append(clean_json_string(response))
def process_questions_list(questions_list, truncate2):
if questions_list:
file_id = upload_file(truncate2)
baseinfo_results = multi_threading(questions_list, "", file_id, 2)
return [clean_json_string(res) for _, res in baseinfo_results] if baseinfo_results else []
else:
return []
def combine_basic_info(merged_baseinfo_path,truncate0,truncate2, clause_path):
"""
综合和处理基础信息,生成最终的基础信息字典。
参数:
- knowledge_name (str): 知识名称。
- truncate0 (str): 文件路径。
- output_folder (str): 输出文件夹路径。
- clause_path (str): 条款路径。
返回:
- dict: 综合后的基础信息。
"""
# baseinfo_prompt_file_path='flask_app/static/提示词/基本信息工程标qianwen-long.txt'
file_id1 = upload_file(merged_baseinfo_path)
baseinfo_prompt_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\基本信息工程标qianwen-long.txt'
questions = read_questions_from_file(baseinfo_prompt_file_path)
# 判断是否分包、是否需要递交投标保证金等
more_query = "请你根据招标文件信息,回答以下问题:是否组织踏勘现场?是否召开投标预备会?是否允许偏离?是否退还投标文件?是否允许分包? 是否需要递交投标保证金是否需要提交履约保证金履约担保是否有招标代理服务费请按json格式给我提供信息键名分别为'是否组织踏勘现场','是否召开投标预备会','是否允许偏离','是否退还投标文件',是否允许分包','是否递交投标保证金','是否提交履约保证金','是否有招标代理服务费',键值仅限于'','','未知',若存在矛盾信息,请回答'未知'"
questions.append(more_query)
baseinfo_results = multi_threading(questions, "", file_id1, 2)
# 清理 JSON 字符串
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())
baseinfo_list1.append(merged)
questions_list=generate_query(baseinfo_list1)
# judge_file_path = 'flask_app/static/提示词/是否相关问题qianwen-long.txt'
judge_file_path = 'D:\\flask_project\\flask_app\\static\\提示词\\是否相关问题qianwen-long.txt'
# 创建两个线程
thread1 = threading.Thread(target=process_judge_questions,
args=(judge_file_path, chosen_numbers, truncate0, baseinfo_list1))
thread2 = threading.Thread(target=process_questions_list, args=(questions_list, truncate2))
# 启动线程
thread1.start()
thread2.start()
# 等待两个线程完成
thread1.join()
thread2.join()
# 处理结果
# baseinfo_list1 已经在 process_judge_questions 中被更新
baseinfo_list2 = process_questions_list(questions_list, truncate2)
updated_list=update_baseinfo_lists(baseinfo_list1,baseinfo_list2)
rebidding_situation = extract_from_notice(clause_path, 3) # "重新招标, 不再招标和终止招标"需从投标人须知正文提取
update_json = rename_outer_key(rebidding_situation, "重新招标、不再招标和终止招标")
updated_list.append(update_json)
aggregated_baseinfo = aggregate_basic_info_engineering(updated_list) # 现在是一个字典
return {"基础信息": aggregated_baseinfo}
#TODO:先不带投标人须知正文,如果是未知,再直接问正文,
if __name__ == "__main__":
start_time=time.time()
merged_baseinfo_path="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output\\zbtest2_merged_baseinfo.pdf"
# output_folder="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output"
truncate0="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output\\zbtest2_tobidders_notice_table.pdf"
truncate2="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output\\zbtest2_tobidders_notice.pdf"
clause_path="C:\\Users\\Administrator\\Desktop\\招标文件\\special_output\\clause1.json"
res=combine_basic_info(merged_baseinfo_path,truncate0,truncate2,clause_path)
print(json.dumps(res,ensure_ascii=False,indent=4))
end_time=time.time()
print("elapsed_time:"+str(end_time-start_time))