549 lines
27 KiB
Python
549 lines
27 KiB
Python
import json
|
||
import os
|
||
import time
|
||
|
||
from flask_app.general.doubao import doubao_model
|
||
from flask_app.general.format_change import pdf2docx, docx2pdf,doc2docx
|
||
from flask_app.general.json_utils import clean_json_string
|
||
from flask_app.general.merge_pdfs import merge_pdfs
|
||
from flask_app.general.通义千问long import qianwen_plus
|
||
from flask_app.general.通用功能函数 import get_global_logger
|
||
from flask_app.general.截取pdf_main import truncate_pdf_multiple
|
||
from flask_app.货物标.提取采购需求main import fetch_procurement_reqs
|
||
from flask_app.货物标.技术参数要求提取后处理函数 import extract_matching_keys
|
||
from flask_app.货物标.资格审查main import combine_qualification_review
|
||
from flask_app.general.商务技术评分提取 import combine_evaluation_standards
|
||
import concurrent.futures
|
||
|
||
logger = None
|
||
def get_nested(dic, keys, default=None):
|
||
for key in keys:
|
||
if isinstance(dic, dict):
|
||
dic = dic.get(key, default)
|
||
else:
|
||
return default
|
||
return dic
|
||
|
||
def prepare_for_zige_info(zige_review):
|
||
try:
|
||
zige_info = ""
|
||
fuhe_info = ""
|
||
zigefuhe_info = ""
|
||
# 检查是否存在"资格性和符合性审查"
|
||
if "资格性和符合性审查" in zige_review:
|
||
# 情况3:只有"申请人资格要求"和"资格性和符合性审查"
|
||
if zige_review.get("申请人资格要求", {}) or zige_review.get("资格性和符合性审查", {}):
|
||
zigefuhe_info = json.dumps({
|
||
"申请人资格要求": zige_review.get("申请人资格要求", {}),
|
||
"符合性审查": zige_review.get("资格性和符合性审查", {})
|
||
}, ensure_ascii=False, indent=4)
|
||
else:
|
||
# 情况1和2:存在分开的资格审查和符合性审查
|
||
if zige_review.get("申请人资格要求", {}) or zige_review.get("资格性审查", {}):
|
||
zige_info = json.dumps({
|
||
"申请人资格要求": zige_review.get("申请人资格要求", {}),
|
||
"资格性审查": zige_review.get("资格性审查", {})
|
||
}, ensure_ascii=False, indent=4)
|
||
|
||
# 检查符合性审查的键值是否为空
|
||
fuhe_key = "符合性审查" if "符合性审查" in zige_review else "符合性审查(以下情况不得出现)"
|
||
if zige_review.get(fuhe_key, {}):
|
||
fuhe_info = json.dumps({
|
||
"符合性审查": zige_review.get(fuhe_key, {})
|
||
}, ensure_ascii=False, indent=4)
|
||
|
||
return zige_info, fuhe_info, zigefuhe_info
|
||
except KeyError as e:
|
||
print(f"缺少关键字: {e}")
|
||
# 异常时直接返回空字符串
|
||
return "", "", ""
|
||
def extract_zige_deviation_table(zige_info, fuhe_info, zigefuhe_info):
|
||
prompt_template1 = """
|
||
任务:给出一份文本,根据文本提取资格性检查的具体评审标准。
|
||
输出要求:
|
||
1.以json格式返回结果,不要输出其他内容。
|
||
2.键名为"资格性检查",键值为字符串列表,每个字符串为一条评审标准,评审标准不分先后,不要有序号标注。
|
||
要求与指南:
|
||
1. 评审标准是具体的内容,不要返回诸如'本项目的特定资格要求:'这种标题性质且不能体现具体评审标准的内容。
|
||
2. 若文本中存在相同或相似的表述,仅需取其中一个作为键值中的一条即可。
|
||
|
||
文本内容:{full_text}
|
||
"""
|
||
|
||
prompt_template2 = """
|
||
任务:给出一份文本,根据文本提取符合性检查的具体评审标准。
|
||
输出要求:
|
||
1.以json格式返回结果,不要输出其他内容。
|
||
2.键名为"符合性检查",键值为字符串列表,每个字符串为一条评审标准,评审标准不分先后,不要有序号标注。
|
||
3.仔细检查你所选取的标准,若发现这些标准实际上是在描述不允许出现的符合性审查情况,则将外键替换为'符合性检查(以下情况不得出现)',并将这些标准写入其中。
|
||
要求与指南:
|
||
1. 评审标准应该是具体的内容,不要返回诸如'本项目的特定符合性要求:'这种标题性质且不能体现具体评审标准的内容。
|
||
2. 若文本中存在相同或相似的表述,仅需取其中一个作为键值中的一条即可。
|
||
输出示例1:
|
||
{{
|
||
"符合性检查": [
|
||
"因素1",
|
||
"因素2",
|
||
...
|
||
]
|
||
}}
|
||
输出示例2:
|
||
{{
|
||
"符合性检查(以下情况不得出现)": [
|
||
"因素1",
|
||
"因素2",
|
||
...
|
||
]
|
||
}}
|
||
|
||
文本内容:{full_text}
|
||
"""
|
||
prompt_template3 = """
|
||
任务:给出一份文本,根据文本提取资格性检查和符合性检查的具体评审标准。
|
||
输出要求:
|
||
1.以json格式返回结果,不要输出其他内容。
|
||
2.键名为"资格性和符合性检查",键值为字符串列表,每个字符串为一条评审标准,评审标准不分先后,不要有序号标注。
|
||
要求与指南:
|
||
1. 评审标准应该是具体的内容,不要返回诸如'本项目的特定符合性要求:'这种标题性质且不能体现具体评审标准的内容。
|
||
2. 若文本中存在相同或相似的表述,仅需取其中一个作为键值中的一条即可。
|
||
|
||
文本内容:{full_text}
|
||
"""
|
||
|
||
def get_model_response(query):
|
||
return qianwen_plus(query)
|
||
|
||
result = {"资格审查": {}}
|
||
|
||
if zigefuhe_info:
|
||
# 如果zigefuhe_info非空,使用prompt_template3
|
||
user_query3 = prompt_template3.format(full_text=zigefuhe_info)
|
||
model_res3 = get_model_response(user_query3)
|
||
zigefuhe_deviation = clean_json_string(model_res3)
|
||
result["资格审查"] = zigefuhe_deviation
|
||
else:
|
||
zige_deviation = {}
|
||
fuhe_deviation = {}
|
||
# 提交 zige_info 和 fuhe_info 的模型调用
|
||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||
futures = {}
|
||
if zige_info != "":
|
||
user_query1 = prompt_template1.format(full_text=zige_info)
|
||
futures["zige"] = executor.submit(get_model_response, user_query1)
|
||
if fuhe_info != "":
|
||
user_query2 = prompt_template2.format(full_text=fuhe_info)
|
||
futures["fuhe"] = executor.submit(get_model_response, user_query2)
|
||
# 获取结果
|
||
for key, future in futures.items():
|
||
try:
|
||
model_res = future.result()
|
||
if key == "zige":
|
||
zige_deviation = clean_json_string(model_res)
|
||
elif key == "fuhe":
|
||
fuhe_deviation = clean_json_string(model_res)
|
||
except Exception as e:
|
||
print(f"Error processing {key}: {e}")
|
||
# 合并结果
|
||
result["资格审查"] = {
|
||
"资格性检查": zige_deviation.get("资格性检查", zige_deviation),
|
||
"符合性检查": fuhe_deviation.get("符合性检查", fuhe_deviation),
|
||
}
|
||
return result
|
||
def extract_business_deviation(busi_requirements_dict):
|
||
# 默认返回值
|
||
default_return = ({"商务要求": []}, {"商务要求带星": []})
|
||
|
||
if not busi_requirements_dict:
|
||
# 如果字典为空,返回默认字典
|
||
return default_return
|
||
|
||
# 定义一个辅助函数来检查字段是否为“未提供”
|
||
def is_unprovided(field):
|
||
if isinstance(field, str):
|
||
return field == "未提供"
|
||
elif isinstance(field, list):
|
||
# 对于列表,检查所有元素是否都是“未提供”
|
||
return all(item == "未提供" for item in field)
|
||
elif isinstance(field, dict):
|
||
# 对于字典,递归检查所有值是否都是“未提供”
|
||
return all(is_unprovided(v) for v in field.values())
|
||
return False
|
||
|
||
# 获取各个要求的值,默认为“未提供”以处理缺失的键
|
||
service_requirement = busi_requirements_dict.get("服务要求", "未提供")
|
||
business_requirement = busi_requirements_dict.get("商务要求", "未提供")
|
||
other_requirement = busi_requirements_dict.get("其他要求", "未提供")
|
||
|
||
# 检查是否所有要求都是“未提供”
|
||
if (is_unprovided(service_requirement) and
|
||
is_unprovided(business_requirement) and
|
||
is_unprovided(other_requirement)):
|
||
return default_return
|
||
new_data = {}
|
||
counter = 1
|
||
if "服务要求" in busi_requirements_dict:
|
||
new_data[f"招标要求{counter}"] = busi_requirements_dict["服务要求"]
|
||
counter += 1
|
||
|
||
# Extract "商务要求"
|
||
if "商务要求" in busi_requirements_dict:
|
||
new_data[f"招标要求{counter}"] = busi_requirements_dict["商务要求"]
|
||
counter += 1
|
||
|
||
# Extract "其他要求"
|
||
if "其他要求" in busi_requirements_dict:
|
||
new_data[f"招标要求{counter}"] = busi_requirements_dict["其他要求"]
|
||
counter += 1
|
||
|
||
business_requirements_string = json.dumps(new_data, ensure_ascii=False, indent=4)
|
||
# print(business_requirements_string)
|
||
prompt_template1 = """请帮我从以下文本中摘取商务要求部分,并将信息重新组织,键名为'商务要求',键值为字符串列表,其中每个字符串为一条商务要求,保留三角▲、五角星★(若有),但是去除开头的序号(若有)。
|
||
#角色
|
||
你是一个专业的招投标业务专家,擅长从招标文件中总结商务要求的部分,并逐条列出,作为编写商务要求偏离表的前置准备。
|
||
|
||
#要求与指南:
|
||
1. 每条内容需要有实际的含义、要求,不能光有标题性质的表述如'售后服务期限(质保期)及要求'。
|
||
2. 你的回答内容需从所给文本中整理,尽量不改变原文的表达,请勿擅自添加三角▲、五角星★(除非以下要求与指南3.的特殊情况)
|
||
3. 若输入文本中存在嵌套键值对格式,且键值本身语义完整且符合'商务要求',可直接将其添加至'商务要求'的键值中;若键值本身语义表达不完整,可将键值对用冒号':'拼接之后作为一条商务要求。
|
||
4. 对于以三角▲或五角星★开头的字符串:
|
||
a. 如果该字符串仅为标题性质的表述且不具备实际商务要求的含义,请根据语义关联性将其开头的三角▲或五角星★添加到紧随其后的若干(可为一)内容之后,形成完整的商务要求,并确保整个内容连贯。
|
||
注:默认在该字符串后面的一个字符串开头添加三角▲或五角星★,若有明确的序号或者语义表示了其后若干字符串之间的相关性,那么可在这些字符串开头都添加三角▲或五角星★,作为若干商务要求。
|
||
b. 如果该字符串已经包含实际的商务要求,那么该内容作为一条完整的商务要求,保留开头的三角▲或五角星★。
|
||
- 示例输入:
|
||
```
|
||
"★ 提供高质量的售后服务,服务期限不少于两年。"
|
||
```
|
||
- 示例输出:
|
||
```
|
||
"★ 提供高质量的售后服务,服务期限不少于两年。"
|
||
```
|
||
c. 无论哪种情况,都需确保不遗漏任何以三角▲或五角星★开头的重要信息。
|
||
5. 若无商务要求,键值为空列表,即[]
|
||
|
||
### 示例输入如下:
|
||
{{
|
||
"招标要求1": ["▲(1)整个平台运行运维服务,须安排人员驻场对平台进行运行维护,采用 4人轮流值班,依照 7×12小时对可视化督察巡控平台进行操作,确保平台稳定运行。","▲ (一) 投标人","1.投标人需要获得 ISO9001 质量管理体系认证 、ISO 14001 环境管理体系认证及 OHSAS18001 职业健康安全管理体系认证。","2.投标人具备网络运营商资格。"]
|
||
"招标要求2": {{
|
||
"合同履行期限": ["★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。"],
|
||
"交货地点": ["采购人指定地点"],
|
||
"报价方式": ["(1)本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。","(2)因投标人自身原因造成漏报、少报皆由其自行承担责任,采购人不再补偿。"],
|
||
"其他要求": ["无。"]
|
||
}}
|
||
}}
|
||
### 对应的参考输出如下:
|
||
{{
|
||
"商务要求":[
|
||
"▲整个平台运行运维服务,须安排人员驻场对平台进行运行维护,采用 4人轮流值班,依照 7×12小时对可视化督察巡控平台进行操作,确保平台稳定运行。",
|
||
"▲投标人 获得 ISO9001 质量管理体系认证 、ISO 14001 环境管理体系认证及 OHSAS18001 职业健康安全管理体系认证。",
|
||
"▲投标人具备网络运营商资格"
|
||
"★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。",
|
||
"交货地点:采购人指定地点",
|
||
"本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。",
|
||
"因投标人自身原因造成漏报、少报皆由其自行承担责任,采购人不再补偿。"
|
||
]
|
||
}}
|
||
|
||
文本内容:{full_text}
|
||
"""
|
||
user_query1 = prompt_template1.format(full_text=business_requirements_string)
|
||
model_res1 = qianwen_plus(user_query1)
|
||
# print(model_res)
|
||
business_req_deviation = clean_json_string(model_res1)
|
||
prompt_template2 = """以下文本是项目采购需求的商务要求部分,请你帮我从键值列表中各字符串中提取带星★或带三角▲的要求项。返回结果仅包括一个键名'商务要求带星'及其键值,为字符串列表,其中每个字符串为带星★或带三角▲的要求项。
|
||
要求与指南:
|
||
1. 每个星★或三角▲要求占据一个字符串。
|
||
2. 若没有带星★或带三角▲的要求项,键值为空列表,即[],无需返回其他说明性描述。
|
||
3. 特殊情况处理:
|
||
-对于输入类似于'技术要求中带★条款项不满足的视为无效投标'这种描述带星★或带三角▲的响应情况的,它本身不是带星或带三角的要求,因此不需要添加进字符串列表中;仅需把本身是带★或带三角▲的要求添加进来。
|
||
|
||
### 示例输入如下:
|
||
{{
|
||
"商务要求": [
|
||
"考虑设备兼容性、项目实施、交付及售后服务",
|
||
"★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。",
|
||
"▲本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。"
|
||
]
|
||
}}
|
||
### 对应的输出如下:
|
||
{{
|
||
"商务要求带星": [
|
||
"★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。",
|
||
"▲本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。"
|
||
]
|
||
}}
|
||
|
||
文本内容:{full_text}
|
||
"""
|
||
user_query2 = prompt_template2.format(full_text=model_res1)
|
||
# print(user_query2)
|
||
model_res2 = qianwen_plus(user_query2)
|
||
business_star_req_deviation = clean_json_string(model_res2)
|
||
|
||
return business_req_deviation, business_star_req_deviation
|
||
|
||
def get_tech_star_deviation(tech_string):
|
||
if not tech_string:
|
||
return {}
|
||
prompt_template = """以下输入文本包含采购货物的技术参数要求或采购要求。请从每个键对应的字符串列表中提取带有星★或三角▲的要求项。返回结果仅为符合要求的 JSON 格式对象,每个键名保持不变,键值为包含对应货物、系统或功能模块的带星或带三角要求项的字符串列表。
|
||
要求与指南:
|
||
1. 如果某个货物、系统或功能模块下没有带星★或带三角▲的要求项,则不返回该键值对。
|
||
2. 每个带星★或带三角▲的要求项应作为单独的字符串。
|
||
3. 如果输入文本中所有设备、系统或功能模块中都没有带星★或带三角▲的要求项,则直接返回空字典 `{{}}`,无需返回其他说明性描述。
|
||
|
||
### 示例输入1如下:
|
||
{{
|
||
"控制键盘": [
|
||
"普通要求xx",
|
||
"★带星要求xx"
|
||
]
|
||
"摄像机"[
|
||
"★带星要求xx",
|
||
"▲带三角要求xx",
|
||
"普通要求xx"
|
||
]
|
||
"交换机":[
|
||
"普通要求xx",
|
||
"普通要求xxx"
|
||
]
|
||
}}
|
||
### 对应的输出如下:
|
||
{{
|
||
"摄像机控制键盘": [
|
||
"★带星要求xx"
|
||
]
|
||
"摄像机"[
|
||
"★带星要求xx",
|
||
"▲带三角要求xx"
|
||
]
|
||
}}
|
||
|
||
### 示例输入2如下:
|
||
{{
|
||
"控制键盘": [
|
||
"普通要求xx",
|
||
"普通要求xxx"
|
||
]
|
||
"摄像机"[
|
||
"普通要求xx"
|
||
]
|
||
}}
|
||
### 对应的输出如下:
|
||
{{}}
|
||
|
||
输入文本内容:{full_text}
|
||
"""
|
||
user_query = prompt_template.format(full_text=tech_string)
|
||
# print(user_query)
|
||
model_res = qianwen_plus(user_query)
|
||
# print(model_res)
|
||
tech_star_deviation = clean_json_string(model_res)
|
||
filtered_dict = {key: value for key, value in tech_star_deviation.items() if value} #过滤键值为空列表,二重保险。
|
||
return filtered_dict
|
||
|
||
def get_proof_materials(all_data_info):
|
||
prompt_template = """以下文本是从招标文件中摘取的资格审查、采购需求、商务条款、技术评分相关内容。请根据这些内容,提取并列出投标人需要提交的证明材料。
|
||
格式要求:
|
||
请以 JSON 格式返回结果:
|
||
- 键名为 '证明材料'。
|
||
- 键值为字符串列表,其中每个字符串表示投标人需要提交的一份材料。
|
||
|
||
要求与指南:
|
||
1. 仅提取与投标人需要提交的材料相关的信息,忽略无关内容。
|
||
2. 返回的内容尽量与文本一致。
|
||
3. 不需要包含重复项,每份材料只需列出一次。
|
||
4. 在提取“采购需求”部分的材料时,应明确对应的设备或货物名称,并通过冒号“:”连接,例如:
|
||
- "发射器:内部机构实用新型专利证书及外观专利证书"
|
||
- "发射器:外壳需有正规厂家世标认证"
|
||
示例输出,仅供格式参考:
|
||
{{
|
||
"证明材料":[
|
||
"具有独立承担民事责任的能力;",
|
||
"具有良好的商业信誉和健全的财务会计制度;",
|
||
"发射器:内部机构实用新型专利证书及外观专利证书",
|
||
"发射器:外壳需有正规厂家世标认证"
|
||
]
|
||
}}
|
||
|
||
输入文本:{full_text}
|
||
"""
|
||
user_query=prompt_template.format(full_text=all_data_info)
|
||
# print(user_query)
|
||
model_res=qianwen_plus(user_query)
|
||
proof_materials = clean_json_string(model_res)
|
||
return proof_materials
|
||
|
||
def process_functions_in_parallel(tech_deviation_info, busi_requirements_dict, zige_info, fuhe_info, zigefuhe_info,all_data_info):
|
||
# 准备输入参数
|
||
# 定义任务和对应参数
|
||
tasks = [
|
||
("tech_star_deviation", get_tech_star_deviation, (tech_deviation_info,)),
|
||
("business_deviation_and_star", extract_business_deviation, (busi_requirements_dict,)),
|
||
("zigefuhe_deviation", extract_zige_deviation_table, (zige_info, fuhe_info, zigefuhe_info)),
|
||
("proof_materials", get_proof_materials, (all_data_info,))
|
||
]
|
||
|
||
results = {}
|
||
|
||
# 执行多线程任务
|
||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||
future_to_task = {executor.submit(func, *args): name for name, func, args in tasks}
|
||
time.sleep(0.5)
|
||
for future in concurrent.futures.as_completed(future_to_task):
|
||
name = future_to_task[future]
|
||
try:
|
||
result = future.result()
|
||
# 处理返回值(如果任务返回多个值,需要解包)
|
||
if name == "business_deviation_and_star":
|
||
results["business_deviation"], results["business_star_deviation"] = result
|
||
else:
|
||
results[name] = result
|
||
except Exception as e:
|
||
print(f"Task {name} failed with exception: {e}")
|
||
results[name] = None
|
||
|
||
# 返回结果
|
||
return (
|
||
results.get("tech_star_deviation"),
|
||
results.get("business_deviation"),
|
||
results.get("business_star_deviation"),
|
||
results.get("zigefuhe_deviation"),
|
||
results.get("proof_materials")
|
||
)
|
||
def get_tech_and_business_deviation(file_path,file_type,unique_id,output_folder,zb_type=2):
|
||
global logger
|
||
logger = get_global_logger(unique_id)
|
||
# 第一步:根据文件类型进行转换
|
||
if file_type == 1: # docx
|
||
docx_path=file_path
|
||
pdf_path = docx2pdf(file_path) # 将docx转换为pdf以供后续处理
|
||
elif file_type == 2: # pdf
|
||
# docx_path=pdf2docx(file_path)
|
||
docx_path=""
|
||
pdf_path = file_path
|
||
elif file_type == 3: # doc
|
||
docx_path=doc2docx(file_path)
|
||
pdf_path = docx2pdf(file_path)
|
||
else:
|
||
logger.error("Unsupported file type provided. Preprocessing halted.")
|
||
return None
|
||
# 第二步:根据zb_type确定选择项和类别,并截取PDF
|
||
if zb_type == 2:
|
||
selections = [1, 2, 3, 5]
|
||
category = 'goods' # 商品类
|
||
else:
|
||
selections = [1, 2, 3]
|
||
category = 'engineering' # 工程类
|
||
try:
|
||
files = truncate_pdf_multiple(pdf_path, output_folder, logger, category, selections)
|
||
except Exception as e:
|
||
logger.error(f"PDF截取过程中出错: {e}")
|
||
return None
|
||
# 根据zb_type分配路径
|
||
notice_path = files[0] if len(files) > 0 else ""
|
||
evaluation_path = files[1] if len(files) > 1 else ""
|
||
qualification_path = files[2] if len(files) > 2 else ""
|
||
procurement_path = files[3] if zb_type == 2 and len(files) > 3 else ""
|
||
invalid_path = files[-2]
|
||
|
||
# invalid_path=docx_path
|
||
invalid_path = docx_path if docx_path else invalid_path
|
||
if zb_type == 2 and not procurement_path:
|
||
procurement_path = invalid_path
|
||
if not evaluation_path:
|
||
evaluation_path=invalid_path
|
||
if not notice_path:
|
||
notice_path=invalid_path
|
||
if zb_type != 2:
|
||
try:
|
||
qualification_path = merge_pdfs(
|
||
[qualification_path, evaluation_path],
|
||
os.path.join(output_folder, "merged_qualification.pdf")
|
||
)
|
||
except Exception as e:
|
||
logger.error(f"PDF合并过程中出错: {e}")
|
||
qualification_path = ""
|
||
tech_deviation={}
|
||
|
||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||
# 使用字典存储future对象
|
||
futures = {}
|
||
|
||
# 根据zb_type条件提交fetch_procurement_reqs任务
|
||
if zb_type == 2:
|
||
futures['procurement'] = executor.submit(fetch_procurement_reqs, procurement_path, invalid_path)
|
||
else:
|
||
# 当zb_type != 2时,设置默认空值
|
||
futures['procurement'] = concurrent.futures.Future()
|
||
futures['procurement'].set_result({}) # 设为默认空字典
|
||
|
||
# 提交combine_qualification_review任务
|
||
futures['review'] = executor.submit(combine_qualification_review, invalid_path, qualification_path, notice_path)
|
||
|
||
# 提交combine_evaluation_standards任务
|
||
futures['evaluation'] = executor.submit(combine_evaluation_standards, evaluation_path, invalid_path, zb_type)
|
||
|
||
# 获取并处理任务结果
|
||
try:
|
||
procurement_reqs = futures['procurement'].result()
|
||
except Exception as e:
|
||
logger.error(f'fetch_procurement_reqs 出现异常: {e}')
|
||
procurement_reqs = {} # 根据需要处理
|
||
|
||
try:
|
||
review_standards_res = futures['review'].result()
|
||
except Exception as e:
|
||
logger.error(f'combine_qualification_review 出现异常: {e}')
|
||
review_standards_res = {} # 根据需要处理
|
||
|
||
try:
|
||
evaluation_res = futures['evaluation'].result()
|
||
except Exception as e:
|
||
logger.error(f'combine_evaluation_standards 出现异常: {e}')
|
||
evaluation_res = {
|
||
"技术评分": {},
|
||
"商务评分": {}
|
||
}
|
||
evaluation_info=json.dumps(evaluation_res, ensure_ascii=False, indent=4)
|
||
# technical_standards = {"技术评分": evaluation_res.get("技术评分", {})} #技术评议表
|
||
# commercial_standards = {"商务评分": evaluation_res.get("商务评分", {})} #商务评议表
|
||
tech_requirements = get_nested(procurement_reqs, ["采购需求"], {})
|
||
busi_requirements = {k: v for k, v in procurement_reqs.items() if k != "采购需求"}
|
||
busi_requirements_info=json.dumps(busi_requirements,ensure_ascii=False,indent=4)
|
||
if tech_requirements:
|
||
good_list = tech_requirements.pop('货物列表', []) # 如果 '货物列表' 不存在,返回 []
|
||
logger.info("Collected good_list from the processing function: %s", good_list)
|
||
tech_deviation = extract_matching_keys(tech_requirements, good_list)
|
||
tech_deviation_info = json.dumps(tech_deviation, ensure_ascii=False, indent=4)
|
||
else:
|
||
tech_deviation_info=""
|
||
zige_info, fuhe_info, zigefuhe_info = prepare_for_zige_info(review_standards_res.get("资格审查", {}))
|
||
|
||
all_data_info = '\n'.join([zige_info, fuhe_info, zigefuhe_info, tech_deviation_info,busi_requirements_info, evaluation_info])
|
||
tech_star_deviation, business_deviation, business_star_deviation, zigefuhe_deviation, proof_materials= process_functions_in_parallel(
|
||
tech_deviation_info=tech_deviation_info,
|
||
busi_requirements_dict=busi_requirements,
|
||
zige_info=zige_info,
|
||
fuhe_info=fuhe_info,
|
||
zigefuhe_info=zigefuhe_info,
|
||
all_data_info=all_data_info
|
||
)
|
||
return tech_deviation,tech_star_deviation,business_deviation,business_star_deviation,zigefuhe_deviation,proof_materials
|
||
|
||
if __name__ == "__main__":
|
||
file_path=r"C:\Users\Administrator\Desktop\new招标文件\工程标\gcHBDL-2024-0017-001-招标文件.pdf"
|
||
file_type=2
|
||
output_folder = r"C:\Users\Administrator\Desktop\new招标文件\工程标\tmp"
|
||
tech_deviation,tech_star_deviation,business_deviation,business_star_deviation,zigefuhe_deviation,proof_materials=get_tech_and_business_deviation(file_path,file_type,"123",output_folder,1)
|
||
print("技术偏离表")
|
||
print(json.dumps(tech_deviation,ensure_ascii=False,indent=4))
|
||
print("技术带星")
|
||
print(json.dumps(tech_star_deviation,ensure_ascii=False,indent=4))
|
||
print("商务偏离表")
|
||
print(json.dumps(business_deviation, ensure_ascii=False, indent=4))
|
||
print("商务带星")
|
||
print(json.dumps(business_star_deviation, ensure_ascii=False, indent=4))
|
||
print("资格审查")
|
||
print(json.dumps(zigefuhe_deviation, ensure_ascii=False, indent=4))
|
||
print("证明材料")
|
||
print(json.dumps(proof_materials,ensure_ascii=False,indent=4))
|