diff --git a/flask_app/general/通用功能函数.py b/flask_app/general/通用功能函数.py index 921292f..f141879 100644 --- a/flask_app/general/通用功能函数.py +++ b/flask_app/general/通用功能函数.py @@ -83,6 +83,14 @@ def aggregate_basic_info(baseinfo_list,mode="engineering"): "商务要求", "其他要求" ] + # 定义采购要求的默认值 + DEFAULT_PROCUREMENT_REQS = { + "采购需求": {}, + "技术要求": [], + "商务要求": [], + "服务要求": [], + "其他要求": [] + } combined_data = {} relevant_keys_detected = set() @@ -117,7 +125,7 @@ def aggregate_basic_info(baseinfo_list,mode="engineering"): # 从未分类项目中移除已匹配的键 unclassified_items.pop(matched_key, None) else: - group_data[key] = "未提供" + group_data[key] = DEFAULT_PROCUREMENT_REQS.get(key, "未提供") else: # 在其他组中使用严格匹配 if key in combined_data: diff --git a/flask_app/routes/偏离表main.py b/flask_app/routes/偏离表main.py index 682955c..1c28196 100644 --- a/flask_app/routes/偏离表main.py +++ b/flask_app/routes/偏离表main.py @@ -1,6 +1,7 @@ import json import os import time +from copy import deepcopy from flask_app.general.doubao import doubao_model from flask_app.general.format_change import pdf2docx, docx2pdf,doc2docx @@ -157,17 +158,67 @@ def extract_business_deviation(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 + def update_keys_and_values(requirements_dict): + """ + 对输入的要求字典进行处理: + - 去除以特殊符号开头的键名中的符号。 + - 将该符号添加到对应值(字符串列表)中每个字符串的开头。 + + 参数: + - requirements_dict (dict): 包含服务要求、商务要求、其他要求的大字典。 + + 返回: + - dict: 更新后的要求字典。 + """ + # 定义特殊符号列表 + special_symbols = ('▲', '★', '●', '■', '◆', '☆', '△', '◇', '○', '□', '#') + + def process_dict(d, parent_symbol=''): + """ + 递归处理字典中的键和值,去除特殊符号并在值中添加符号前缀。 + + 参数: + - d (dict): 要处理的字典。 + - parent_symbol (str): 从父级传递下来的符号(如果有)。 + + 返回: + - dict: 处理后的字典。 + """ + updated = {} + for key, value in d.items(): + current_symbol = parent_symbol + new_key = key + # 检查键名是否以特殊符号开头 + if key and key[0] in special_symbols: + current_symbol = key[0] + new_key = key[1:].strip() # 去除符号并去除多余空格 + else: + # 保持父级符号(如果有) + current_symbol = parent_symbol + + # 处理值 + if isinstance(value, dict): + # 递归处理嵌套字典,传递当前符号 + new_value = process_dict(value, current_symbol) + elif isinstance(value, list): + if current_symbol: + # 为列表中的每个字符串添加符号前缀 + new_value = [f"{current_symbol}{item}" for item in value] + else: + new_value = value + else: + new_value = value # 保持原样 + + updated[new_key] = new_value + return updated + + # 深复制输入字典,避免修改原始数据 + requirements_copy = deepcopy(requirements_dict) + + # 递归处理整个字典 + updated_requirements = process_dict(requirements_copy) + + return updated_requirements # 定义辅助函数,应对'★3、服务要求'这种键名,保留'★' def find_matching_key(data, target_key): @@ -176,125 +227,196 @@ def extract_business_deviation(busi_requirements_dict): return k return None + def rename_outer_keys(updated_requirements): + """ + 重命名 updated_requirements 的顶层键,将其改为 '商务要求-d',其中 d 是从1开始的自然数。 + 忽略值为 [] 的键值对。 + + 参数: + - updated_requirements (dict): 需要重命名顶层键的字典。 + + 返回: + - dict: 重命名后的字典。 + """ + renamed = {} + counter = 1 # 计数器从1开始 + + for original_key, value in updated_requirements.items(): + # 检查是否需要忽略该键值对 + if isinstance(value, list) and not value: + continue # 忽略值为 [] 的键值对 + # 构造新的键名 + new_key = f"商务要求-{counter}" + renamed[new_key] = value + counter += 1 # 递增计数器 + + return renamed + + def process_query(query): + model_res = qianwen_plus(query) + return clean_json_string(model_res) + # 优化查找逻辑 target_keys = ["服务要求", "商务要求", "其他要求"] - requirements = {key: busi_requirements_dict.get(find_matching_key(busi_requirements_dict, key), "未提供") for key in - target_keys} + requirements_dict = { + matched_key: busi_requirements_dict[matched_key] + for key in target_keys + for matched_key in [find_matching_key(busi_requirements_dict, key)] + if matched_key is not None + } - # 解构变量 - service_requirement, business_requirement, other_requirement = ( - requirements["服务要求"], - requirements["商务要求"], - requirements["其他要求"] - ) - - # 检查是否所有要求都是“未提供” - if (is_unprovided(service_requirement) and - is_unprovided(business_requirement) and - is_unprovided(other_requirement)): + # 判断是否提取到了内容 + if all(value == [] for value in requirements_dict.values()): + # 如果所有值都是 "未提供",则表示未提取到内容 + print("未提取到任何内容") 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 = """请帮我从以下文本中摘取商务要求部分,并将信息重新组织,键名为'商务要求',键值为字符串列表,其中每个字符串为一条商务要求,保留三角▲、五角星★(若有),但是去除开头的序号(若有)。 - #角色 - 你是一个专业的招投标业务专家,擅长从招标文件中总结商务要求的部分,并逐条列出,作为编写商务要求偏离表的前置准备。 - - #要求与指南: + else: + updated_requirements = update_keys_and_values(requirements_dict) + print("商务要求已更新!") + renamed_requirements = rename_outer_keys(updated_requirements) + business_requirements_string = json.dumps(renamed_requirements, ensure_ascii=False, indent=4) + print(business_requirements_string) + prompt_template1 = """以下文本是项目采购需求的商务要求部分,请帮我将信息重新组织,键名为'商务要求',键值为字符串列表,其中每个字符串为一条商务要求,保留三角▲、五角星★(若有),但是去除开头的序号(若有)。 +**角色** +你是一个专业的招投标业务专家,擅长从招标文件中总结商务要求的部分,并逐条列出,作为编写商务要求偏离表的前置准备。 + +**要求与指南**: 1. 每条内容需要有实际的含义、要求,不能光有标题性质的表述如'售后服务期限(质保期)及要求'。 - 2. 你的回答内容需从所给文本中整理,尽量不改变原文的表达,请勿擅自添加三角▲、五角星★(除非以下要求与指南3.的特殊情况) - 3. 若输入文本中存在嵌套键值对格式,且键值本身语义完整且符合'商务要求',可直接将其添加至'商务要求'的键值中;若键值本身语义表达不完整,可将键值对用冒号':'拼接之后作为一条商务要求。 - 4. 对于以三角▲或五角星★开头的字符串: - a. 如果该字符串仅为标题性质的表述且不具备实际商务要求的含义,请根据语义关联性将其开头的三角▲或五角星★添加到紧随其后的若干(可为一)内容之后,形成完整的商务要求,并确保整个内容连贯。 + 2. 你的回答内容需从所给文本中整理,尽量不改变原文的表达(除非以下要求与指南3.的特殊情况),请勿擅自添加三角▲、五角星★。 + 3. 若输入文本中存在嵌套键值对格式,且键值本身语义完整且符合'商务要求',可直接将其添加至'商务要求'的键值中;若键值字符串本身语义表达不完整,可将键值对用冒号':'拼接之后作为一条商务要求,若键值字符串以★、▲或其他特殊符号开头,将符号移至拼接后的开头,例如'"★交货地点:采购人指定地点"'。 + 4. 对于以三角▲或五角星★或其他特殊符号开头的字符串: + a. 如果该字符串仅为标题性质的表述且不具备实际商务要求的含义,请根据语义关联性将其开头的三角▲或五角星★添加到紧随其后的若干(可为一)内容之后,形成完整的商务要求,并确保整个内容连贯。 注:默认在该字符串后面的一个字符串开头添加三角▲或五角星★,若有明确的序号或者语义表示了其后若干字符串之间的相关性,那么可在这些字符串开头都添加三角▲或五角星★,作为若干商务要求。 - b. 如果该字符串已经包含实际的商务要求,那么该内容作为一条完整的商务要求,保留开头的三角▲或五角星★。 - 示例输入: - ``` - "★ 提供高质量的售后服务,服务期限不少于两年。" - ``` + ``` + "★售后服务" + "提供高质量的售后服务,服务期限不少于两年。" + ``` - 示例输出: - ``` - "★ 提供高质量的售后服务,服务期限不少于两年。" - ``` - c. 无论哪种情况,都需确保不遗漏任何以三角▲或五角星★开头的重要信息。 + ``` + "★提供高质量的售后服务,服务期限不少于两年。" + ``` + b. 如果该字符串已经包含实际的商务要求,那么该内容作为一条完整的商务要求,保留开头的三角▲或五角星★。 + - 示例输入: + ``` + "★提供高质量的售后服务,服务期限不少于两年。" + ``` + - 示例输出: + ``` + "★提供高质量的售后服务,服务期限不少于两年。" + ``` + c. 无论哪种情况,都需确保不遗漏任何以三角▲或五角星★开头的重要信息。 5. 若无商务要求,键值为空列表,即[] + +**禁止内容**: +确保所有输出内容均基于提供的实际文本内容,不使用任何预设的示例作为回答。 - ### 示例输入如下: - {{ - "招标要求1": ["▲(1)整个平台运行运维服务,须安排人员驻场对平台进行运行维护,采用 4人轮流值班,依照 7×12小时对可视化督察巡控平台进行操作,确保平台稳定运行。","▲ (一) 投标人","1.投标人需要获得 ISO9001 质量管理体系认证 、ISO 14001 环境管理体系认证及 OHSAS18001 职业健康安全管理体系认证。","2.投标人具备网络运营商资格。"] - "招标要求2": {{ - "合同履行期限": ["★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。"], - "交货地点": ["采购人指定地点"], - "报价方式": ["(1)本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。","(2)因投标人自身原因造成漏报、少报皆由其自行承担责任,采购人不再补偿。"], - "其他要求": ["无。"] +**示例输入如下**: +{{ + "商务要求-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) + prompt_template2 = """以下文本是项目采购需求的商务要求部分。请从中提取以★、▲或其他特殊符号开头的要求项,它们一般是重要的商务要求,需要额外响应。返回结果应仅包含一个键名“重要商务要求”,其键值为字符串列表,每个字符串对应一个以★、▲或特殊符号开头的要求项,但是去除开头的序号(若有)。 + + **要求与指南**: + 1. 每个以★、▲或其他特殊符号开头的要求项应作为单独的字符串。 + 2. 每条内容需要有实际的含义、要求,不能光有标题性质的表述如'★售后服务期限(质保期)及要求';对于类似'技术要求中带★条款项不满足的视为无效投标'这种描述带星★或带三角▲或带特殊符号的响应情况的,它本身不属于具体的★、▲商务要求,因此不需要添加进字符串列表中。 + 3. 你的回答内容需从所给文本中提取,尽量不改变原文的表达(除非以下要求与指南3.的特殊情况),请勿擅自添加三角▲、五角星★,请勿返回普通的商务要求。 + 4. 若无重要商务要求(★、▲或其他特殊符号开头的商务要求项),键值为空列表,即[],无需额外返回说明性文字。 + 5. 若输入文本中存在嵌套键值对格式,且键值本身语义完整且符合'重要商务要求',可直接将其添加至'商务要求'的键值中;若键值字符串本身语义表达不完整,可将键值对用冒号':'拼接之后作为一条商务要求,若键值字符串以★、▲或其他特殊符号开头,将符号移至拼接后的开头,例如'"★交货地点:采购人指定地点"'。 + 6. 对于以三角▲或五角星★或其他特殊符号开头的字符串: + a. 如果该字符串仅为标题性质的表述且不具备实际商务要求的含义,请根据语义关联性将其开头的三角▲或五角星★添加到紧随其后的若干(可为一)内容之后,形成完整的商务要求,并确保整个内容连贯。 + 注:默认在该字符串后面的一个字符串开头添加三角▲或五角星★,若有明确的序号或者语义表示了其后若干字符串之间的相关性,那么可在这些字符串开头都添加三角▲或五角星★,作为若干商务要求。 + - 示例输入: + ``` + "★售后服务期限(质保期)及要求" + "提供高质量的售后服务,服务期限不少于两年。" + ``` + - 示例输出: + ``` + "★提供高质量的售后服务,服务期限不少于两年。" + ``` + b. 如果该字符串已经包含实际的商务要求,那么该内容作为一条完整的商务要求,保留开头的三角▲或五角星★。 + - 示例输入: + ``` + "★提供高质量的售后服务,服务期限不少于两年。" + ``` + - 示例输出: + ``` + "★提供高质量的售后服务,服务期限不少于两年。" + ``` + c. 无论哪种情况,都需确保不遗漏任何以三角▲或五角星★或其他特殊符号开头的重要信息。 + + **禁止内容**: + 确保所有输出内容均基于提供的实际文本内容,不使用任何预设的示例作为回答。 + + **示例输入如下**: + {{ + "商务要求-1": ["▲(1)整个平台运行运维服务,须安排人员驻场对平台进行运行维护,采用 4人轮流值班,依照 7×12小时对可视化督察巡控平台进行操作,确保平台稳定运行。","▲ (一) 投标人","1.投标人需要获得 ISO9001 质量管理体系认证 、ISO 14001 环境管理体系认证及 OHSAS18001 职业健康安全管理体系认证。","2.投标人具备网络运营商资格。"] + "商务要求-2": {{ + "合同履行期限": ["★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。"], + "交货地点": ["★采购人指定地点"], + "报价方式": ["(1)本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。","(2)因投标人自身原因造成漏报、少报皆由其自行承担责任,采购人不再补偿。"], + "其他要求": ["无。"] + }} + }} + **对应的参考输出如下**: + {{ + "重要商务要求":[ + "▲整个平台运行运维服务,须安排人员驻场对平台进行运行维护,采用 4人轮流值班,依照 7×12小时对可视化督察巡控平台进行操作,确保平台稳定运行。", + "▲投标人 获得 ISO9001 质量管理体系认证 、ISO 14001 环境管理体系认证及 OHSAS18001 职业健康安全管理体系认证。", + "▲投标人具备网络运营商资格" + "★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。", + "★交货地点:采购人指定地点" + ] }} - }} - ### 对应的参考输出如下: - {{ - "商务要求":[ - "▲整个平台运行运维服务,须安排人员驻场对平台进行运行维护,采用 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. 特殊情况处理: - -对于输入类似于'技术要求中带★条款项不满足的视为无效投标'这种描述带星★或带三角▲的响应情况的,它本身不是带星或带三角的要求,因此不需要添加进字符串列表中;仅需把本身是带★或带三角▲的要求添加进来。 + 文本内容:{full_text} + """ + user_query2 = prompt_template2.format(full_text=business_requirements_string) + queries = [user_query1, user_query2] + # 初始化结果列表,默认值为 None + results = [None] * len(queries) + # 使用 ThreadPoolExecutor 进行多线程处理 + with concurrent.futures.ThreadPoolExecutor() as executor: + # 提交所有查询任务,并记录对应的索引/ + futures = {executor.submit(process_query, query): idx for idx, query in enumerate(queries)} + # 遍历完成的任务 + for future in concurrent.futures.as_completed(futures): + idx = futures[future] + try: + result = future.result() + results[idx] = result + except Exception as e: + print(f"查询 {idx + 1} 处理时出错: {e}") + # 仅将失败的查询结果设为默认值 + results[idx] = default_return[idx] + # 分配结果到相应的变量,未处理的结果使用默认值 + business_req_deviation = results[0] if results[0] is not None else default_return[0] + business_star_req_deviation = results[1] if results[1] is not None else default_return[1] - ### 示例输入如下: - {{ - "商务要求": [ - "考虑设备兼容性、项目实施、交付及售后服务", - "★交货期(工期):合同签订之日起 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 + return business_req_deviation, business_star_req_deviation def get_tech_star_deviation(tech_string): if not tech_string: @@ -544,6 +666,36 @@ def get_tech_and_business_deviation(file_path,file_type,unique_id,output_folder, ) return tech_deviation,tech_star_deviation,business_deviation,business_star_deviation,zigefuhe_deviation,proof_materials + +prompt_template2_old = """以下文本是项目采购需求的商务要求部分。请从中提取以★、▲或其他特殊符号开头的要求项,它们一般是重要的商务要求,需要额外响应。返回结果应仅包含一个键名“商务要求带星”,其键值为字符串列表,每个字符串对应一个以★、▲或特殊符号开头的要求项。 +**要求与指南**: + 1. 每个以★、▲或特殊符号开头的要求项应作为单独的字符串。 + 2. 如果不存在符合条件的要求项,键值为空列表,即[],无需额外返回其他说明性描述。 + 3. 特殊情况处理: + -对于类似'技术要求中带★条款项不满足的视为无效投标'这种描述带星★或带三角▲或带特殊符号的响应情况的,它本身没有描述具体的★、▲商务要求,因此不需要添加进字符串列表中;仅提取实际的带★、▲或其他特殊符号的商务要求项。 + +**禁止内容**: + 确保所有输出内容均基于提供的实际文本内容,不使用任何预设的示例作为回答。 + +**示例输入如下**: +{{ + "商务要求": [ + "考虑设备兼容性、项目实施、交付及售后服务", + "★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。", + "▲本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。" + ] +}} +**对应的输出如下**: +{{ + "商务要求带星": [ + "★交货期(工期):合同签订之日起 15个日历天内完成,并通过项目验收。", + "▲本项目报价须为固定总价,包含但不限于:采购、实施、调试、试运行、验收、运维等所有完成本项目相关的一切费用。" + ] +}} + +文本内容:{full_text} + """ + if __name__ == "__main__": file_path=r"C:\Users\Administrator\Desktop\new招标文件\工程标\gcHBDL-2024-0017-001-招标文件.pdf" file_type=2 diff --git a/flask_app/货物标/技术参数要求提取后处理函数.py b/flask_app/货物标/技术参数要求提取后处理函数.py index f082b36..b7221ce 100644 --- a/flask_app/货物标/技术参数要求提取后处理函数.py +++ b/flask_app/货物标/技术参数要求提取后处理函数.py @@ -75,6 +75,7 @@ def postprocess_technical_table(data, good_list, special_keys=None, parent_key=' # 处理普通匹配键 # 检查是否以特殊符号开头 if clean_key.startswith(('▲', '★','●','■','◆','☆','△','◇','○','□','#')): + #提取符号并去除符号: symbol = clean_key[0] stripped_key = clean_key[1:] value_tuple = tuple(value) diff --git a/flask_app/货物标/提取采购需求main.py b/flask_app/货物标/提取采购需求main.py index 821e921..24cd490 100644 --- a/flask_app/货物标/提取采购需求main.py +++ b/flask_app/货物标/提取采购需求main.py @@ -18,10 +18,10 @@ def fetch_procurement_reqs(procurement_path, invalid_path): # 定义默认的 procurement_reqs 字典 DEFAULT_PROCUREMENT_REQS = { "采购需求": {}, - "技术要求": "", - "商务要求": "", - "服务要求": "", - "其他要求": "" + "技术要求": [], + "商务要求": [], + "服务要求": [], + "其他要求": [] } # 如果 procurement_docpath 是空字符串,直接返回包含空字符串的字典