1.7 商务要求标题带星保留+评分项手动计算总分
This commit is contained in:
parent
615c8d6898
commit
4d5dc9ea4e
@ -4,10 +4,10 @@ import re
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from flask_app.general.doubao import get_total_tokens, read_txt_to_string, doubao_model
|
||||
from flask_app.general.doubao import read_txt_to_string
|
||||
from flask_app.general.file2markdown import convert_file_to_markdown
|
||||
from flask_app.general.format_change import get_pdf_page_count, pdf2docx
|
||||
from flask_app.general.json_utils import clean_json_string, extract_content_from_json
|
||||
from flask_app.general.json_utils import extract_content_from_json
|
||||
from flask_app.general.model_continue_query import process_continue_answers
|
||||
from flask_app.general.通义千问long import upload_file, qianwen_long, qianwen_plus
|
||||
|
||||
@ -23,51 +23,49 @@ def remove_unknown_scores(data):
|
||||
return [remove_unknown_scores(item) for item in data]
|
||||
else:
|
||||
return data
|
||||
def combine_technical_and_business(data, target_values):
|
||||
# target_values = ['技术', '设计', '实施']
|
||||
def combine_technical_and_business(data):
|
||||
data = remove_unknown_scores(data)
|
||||
extracted_data = {} # 根级别存储所有数据
|
||||
technical_found = False
|
||||
business_found = False
|
||||
extracted_data = {
|
||||
'技术评分': {
|
||||
'技术评分': {} # 初始化技术评分
|
||||
},
|
||||
'商务评分': {
|
||||
'商务评分': {}, # 初始化商务评分
|
||||
'投标报价评分': {} # 初始化投标报价评分
|
||||
# '其他评分' 将在需要时动态添加
|
||||
}
|
||||
}
|
||||
|
||||
def extract_nested(data, parent_key='', is_technical=False, is_business=False):
|
||||
nonlocal technical_found, business_found
|
||||
def extract_nested(data):
|
||||
if isinstance(data, dict):
|
||||
for key, value in data.items():
|
||||
current_key = f"{parent_key}.{key}" if parent_key else key
|
||||
|
||||
# 检查是否为技术标的内容
|
||||
if any(target in key for target in target_values):
|
||||
if not is_technical:
|
||||
if '技术评分' not in extracted_data:
|
||||
extracted_data['技术评分'] = {} # 初始化 '技术评分' 字典
|
||||
extracted_data['技术评分'][key] = value
|
||||
technical_found = True
|
||||
# 区分 '技术评分'
|
||||
if key == '技术评分':
|
||||
total_score=compute_total_score({key:value})
|
||||
extracted_data['技术评分']['技术评分'] = value
|
||||
# 匹配到后,不再递归处理其子项
|
||||
continue
|
||||
|
||||
# 默认其他所有内容都归为商务标
|
||||
# 区分 '商务评分'
|
||||
elif key == '商务评分':
|
||||
extracted_data['商务评分']['商务评分'] = value
|
||||
# 匹配到后,不再递归处理其子项
|
||||
continue
|
||||
|
||||
# 区分 '投标报价评分'
|
||||
elif key == '投标报价评分':
|
||||
extracted_data['商务评分']['投标报价评分'] = value
|
||||
# 匹配到后,不再递归处理其子项
|
||||
continue
|
||||
|
||||
# 其他键名归为 '其他评分'
|
||||
else:
|
||||
if not is_business:
|
||||
if '商务评分' not in extracted_data:
|
||||
extracted_data['商务评分'] = {} # 确保它是字典
|
||||
extracted_data['商务评分'][key] = value
|
||||
business_found = True
|
||||
if '其他评分' not in extracted_data['商务评分']:
|
||||
extracted_data['商务评分']['其他评分'] = {}
|
||||
extracted_data['商务评分']['其他评分'][key] = value
|
||||
continue
|
||||
|
||||
if isinstance(value, dict) or isinstance(value, list):
|
||||
extract_nested(value, current_key, is_technical, is_business)
|
||||
|
||||
elif isinstance(data, list):
|
||||
for index, item in enumerate(data):
|
||||
extract_nested(item, f"{parent_key}[{index}]", is_technical, is_business)
|
||||
|
||||
extract_nested(data)
|
||||
|
||||
if not technical_found:
|
||||
extracted_data['技术评分'] = ''
|
||||
if not business_found:
|
||||
extracted_data['商务评分'] = ''
|
||||
|
||||
return extracted_data
|
||||
|
||||
# 防止外键只有一个'一包'的情况
|
||||
@ -83,6 +81,72 @@ def process_data_based_on_key(data):
|
||||
# 如果条件不满足,则返回原始字典
|
||||
return data
|
||||
|
||||
def compute_total_score(data):
|
||||
"""
|
||||
计算传入字典的总分。
|
||||
|
||||
规则:
|
||||
- 输入字典只有一个外层键。
|
||||
- 遍历该外层键的所有子键:
|
||||
- 如果子键名中包含 '(XX分)' 或 '(XX分)',提取 XX 并累加到总分中,不再处理其子项。
|
||||
- 如果子键名中不包含这样的分数,遍历其子项,查找键名为 '评分' 的键,提取分数并累加。
|
||||
- '评分' 的值可以是 'XX分' 或整数。
|
||||
- 如果没有找到 '评分' 键,则该项分数为 0。
|
||||
"""
|
||||
total = 0
|
||||
|
||||
# 确保输入数据为字典且只有一个外层键
|
||||
if not isinstance(data, dict) or len(data) != 1:
|
||||
raise ValueError("输入数据必须是一个只有一个外层键的字典。")
|
||||
|
||||
# 获取唯一的外层键和值
|
||||
outer_key, outer_value = next(iter(data.items()))
|
||||
|
||||
# 更新后的正则表达式,匹配中英文括号中的分数,如 '(24分)' 或 '(24分)'
|
||||
score_pattern = re.compile(r'[((](\d+)分[))]')
|
||||
|
||||
def process_node(node):
|
||||
nonlocal total
|
||||
if isinstance(node, dict):
|
||||
for key, value in node.items():
|
||||
# 检查键名中是否包含 '(XX分)' 或 '(XX分)'
|
||||
match = score_pattern.search(key)
|
||||
if match:
|
||||
score = int(match.group(1))
|
||||
total += score
|
||||
# 匹配到后,不再递归处理其子项
|
||||
continue
|
||||
elif key == '评分':
|
||||
if isinstance(value, str):
|
||||
# 提取 '评分' 键的值中的数字,如 '20分'
|
||||
match_score = re.match(r'(\d+)分', value)
|
||||
if match_score:
|
||||
score = int(match_score.group(1))
|
||||
total += score
|
||||
else:
|
||||
# 如果 '评分' 值不符合格式,默认加 0
|
||||
total += 0
|
||||
elif isinstance(value, int):
|
||||
# 如果 '评分' 键的值是整数,直接累加
|
||||
total += value
|
||||
else:
|
||||
# 如果 '评分' 键的值既不是字符串也不是整数,默认加 0
|
||||
total += 0
|
||||
else:
|
||||
# 如果键名不包含分数,递归处理其子项
|
||||
process_node(value)
|
||||
elif isinstance(node, list):
|
||||
for item in node:
|
||||
process_node(item)
|
||||
else:
|
||||
# 如果是其他类型的数据,忽略
|
||||
pass
|
||||
|
||||
# 开始递归处理外层键的值
|
||||
process_node(outer_value)
|
||||
|
||||
return total
|
||||
|
||||
def reorganize_data(input_dict, include=None):
|
||||
"""
|
||||
重组输入字典,将“技术评分”和“商务评分”提升为最外层键,
|
||||
@ -167,7 +231,6 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
格式要求:
|
||||
1.总体结构:
|
||||
-JSON 的最外层包含三个键:技术评分、商务评分 和 投标报价评分。
|
||||
-最外层三个键名后需附加括号,括号中注明该大项评分的总分,如'技术评分(18分)',若无具体评分,则无需添加该括号。
|
||||
-每个大项(如技术评分、商务评分)下包含具体的评分项,评分项按以下规则表示。
|
||||
2.评分项表示规则:
|
||||
-层级嵌套规则:
|
||||
@ -179,7 +242,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
-字典个数:
|
||||
默认为1个字典,若某评分因素包括多个评分标准(多个表格单元格),可以用多个并列字典表示。
|
||||
-字典结构如下:
|
||||
评分:该评分标准的总分(如 8分);不能是一个范围数字(如0-8分);若为定性指标(如“合格制”),可标明相应的定性指标;无评分时可删去'评分'键值对。
|
||||
评分:该评分标准的总分(如 8分),字符串类型;不能是一个范围数字(如0-8分);若为定性指标(如“合格制”),可标明相应的定性指标;无评分时可删去'评分'键值对。
|
||||
要求:说明评分标准或要求。
|
||||
-禁止情况:
|
||||
禁止将同个单元格内的内容拆分至多个字典中;禁止遗漏单元格内任何信息,包括注的内容。
|
||||
@ -208,7 +271,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
以下为示例输出,仅供格式参考:
|
||||
{
|
||||
"一包": {
|
||||
"技术评分(26分)": {
|
||||
"技术评分": {
|
||||
"实施方案(16分)":{
|
||||
"总体实施方案":[
|
||||
{
|
||||
@ -231,7 +294,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
],
|
||||
"备注": "技术标采用暗标形式,暗标不得出现投标人名称、人员姓名。"
|
||||
},
|
||||
"商务评分(9分)": {
|
||||
"商务评分": {
|
||||
"主要监理岗位的职责": [
|
||||
{
|
||||
"评分": "4分",
|
||||
@ -267,7 +330,6 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
格式要求:
|
||||
1.总体结构:
|
||||
-JSON 的最外层包含三个键:'技术评分'、'商务评分' 和 '投标报价评分'。
|
||||
-最外层三个键名后需附加括号,括号中注明该大项评分的总分,如'技术评分(18分)',若无具体评分,则无需添加该括号。
|
||||
-每个大项(如技术评分、商务评分)下包含具体的评分项,评分项按以下规则表示。
|
||||
2.评分项表示规则:
|
||||
-层级嵌套规则:
|
||||
@ -279,7 +341,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
-字典个数:
|
||||
默认为1个字典,若某评分因素包括多个评分标准(多个表格单元格),可以用多个并列字典表示。
|
||||
-字典结构如下:
|
||||
评分:该评分标准的总分(如 8分);不能是一个范围数字(如0-8分);若为定性指标(如“合格制”),可标明相应的定性指标;无评分时可删去'评分'键值对。
|
||||
评分:该评分标准的总分(如 8分),字符串类型;不能是一个范围数字(如0-8分);若为定性指标(如“合格制”),可标明相应的定性指标;无评分时可删去'评分'键值对。
|
||||
要求:说明评分标准或要求。
|
||||
-禁止情况:
|
||||
禁止将同个单元格内的内容拆分至多个字典中;禁止遗漏单元格内任何信息,包括注的内容。
|
||||
@ -308,7 +370,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
以下为示例输出,仅供格式参考:
|
||||
{
|
||||
"一包": {
|
||||
"技术评分(18分)": {
|
||||
"技术评分": {
|
||||
"产品技术响应(8分)":{
|
||||
"常规参数符合":[
|
||||
{
|
||||
@ -331,7 +393,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
],
|
||||
"备注": "注:若不满足“与公安部、省公安厅、随州市公安局高清视频会议系统无缝对接互联互通”的要求,则本项技术部分不得分。"
|
||||
},
|
||||
"商务评分(9分)": {
|
||||
"商务评分": {
|
||||
"主要监理岗位的职责": [
|
||||
{
|
||||
"评分": "4分",
|
||||
@ -390,9 +452,7 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
temp_final.update(continued_results)
|
||||
result_data = process_data_based_on_key(temp_final) # 处理不知名外键的情况
|
||||
include = ['一包', '二包', '三包', '四包', '五包']
|
||||
target_values = ['技术', '设计', '实施']
|
||||
updated_jsons = {}
|
||||
|
||||
# 检查是否有外层键匹配 include 列表
|
||||
if any(key for key in result_data if
|
||||
any(included in key for included in include)): # 检查result_data中的任何键是否包含include列表中的任意一个项。
|
||||
@ -400,11 +460,10 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
for key in result_data:
|
||||
if any(item in key for item in include):
|
||||
inner_dict = result_data[key]
|
||||
updated_jsons[key] = combine_technical_and_business(inner_dict,
|
||||
target_values) # 对于分包,单独对分包内的'技术评分''商务评分'作处理
|
||||
updated_jsons[key] = combine_technical_and_business(inner_dict) # 对于分包,单独对分包内的'技术评分''商务评分'作处理
|
||||
else:
|
||||
# 没有匹配的项,对整个字典运行
|
||||
updated_jsons = combine_technical_and_business(result_data, target_values)
|
||||
updated_jsons = combine_technical_and_business(result_data)
|
||||
final_res = reorganize_data(updated_jsons, include) # 重新组织字典,尤其是分包的情况
|
||||
return final_res
|
||||
|
||||
@ -450,16 +509,19 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
|
||||
|
||||
#目前评分这块如果表格过长,会有问题,可以考虑textin+doubao,小于20页用text,>20页转word->qianwen-long
|
||||
#TODO:代码计算总分,商务评分修改
|
||||
#TODO:废标项,增加对表格的提取+排除重复项
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time=time.time()
|
||||
# truncate_file=r"C:\Users\Administrator\Desktop\招标文件-采购类\tmp2\2024-新疆-塔城地区公安局食药环分局快检实验室项目_evaluation_method.pdf"
|
||||
evaluation_method_path = r'C:\Users\Administrator\Desktop\招标文件\招标04_evaluation_method.pdf'
|
||||
invalid_path=r'C:\Users\Administrator\Desktop\文件解析问题\文件解析问题\1414cb9c-7bf4-401c-8761-2acde151b9c2\ztbfile.docx'
|
||||
evaluation_method_path = r'D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\invalid_del.docx'
|
||||
invalid_path=r'D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\invalid_del.docx'
|
||||
# truncate_file = "C:\\Users\\Administrator\\Desktop\\货物标\\output2\\2-招标文件(统计局智能终端二次招标)_evaluation_method.pdf"
|
||||
# truncate_file="C:\\Users\\Administrator\\Desktop\\货物标\\output2\\广水市妇幼招标文件最新(W改)_evaluation_method.pdf"
|
||||
# truncate_file = "C:\\Users\\Administrator\\Desktop\\fsdownload\\2d481945-1f82-45a5-8e56-7fafea4a7793\\ztbfile_evaluation_method.pdf"
|
||||
# truncate_file="C:\\Users\\Administrator\\Desktop\\fsdownload\\ztbfile_evaluation_method.pdf"
|
||||
res = combine_evaluation_standards(evaluation_method_path,invalid_path,1)
|
||||
res = combine_evaluation_standards(evaluation_method_path,invalid_path,2)
|
||||
print(json.dumps(res, ensure_ascii=False, indent=4))
|
||||
end_time=time.time()
|
||||
print("elapsed time:"+str(end_time-start_time))
|
@ -151,11 +151,11 @@ def get_invalid_file(file_path, output_folder, common_header,begin_page):
|
||||
regex.MULTILINE
|
||||
),
|
||||
regex.compile(
|
||||
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(?:响应|投标).*?格式.*',
|
||||
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(?:响应|投标|应答).*?格式.*',
|
||||
regex.MULTILINE
|
||||
),
|
||||
regex.compile(
|
||||
r"\s*(投标文件|响应文件|响应性文件)(?:的)?格式\s*",
|
||||
r"\s*(投标文件|响应文件|响应性文件|应答文件)(?:的)?格式\s*",
|
||||
regex.MULTILINE
|
||||
)
|
||||
]
|
||||
|
@ -4,7 +4,8 @@ import re
|
||||
import regex
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from flask_app.general.doubao import doubao_model, generate_full_user_query
|
||||
from flask_app.general.doubao import generate_full_user_query
|
||||
from flask_app.general.通义千问long import qianwen_plus
|
||||
from flask_app.general.通用功能函数 import process_string_list
|
||||
from collections import OrderedDict
|
||||
from docx import Document
|
||||
@ -206,9 +207,6 @@ def preprocess_paragraphs(paragraphs):
|
||||
continue
|
||||
else:
|
||||
if flag:
|
||||
# 当前段落不以数字序号开头,且 flag 为 True
|
||||
if "供应商公章" in current_text:
|
||||
print("yes")
|
||||
if not list_item_pattern.match(current_text):
|
||||
if processed:
|
||||
# **新增逻辑开始**
|
||||
@ -220,8 +218,8 @@ def preprocess_paragraphs(paragraphs):
|
||||
pattern_numeric_header_fallback.match(next_non_empty_text)
|
||||
)
|
||||
|
||||
if is_next_numbered:
|
||||
# 只有在下一个段落以数字序号开头时,才将当前段落追加到上一个段落
|
||||
if is_next_numbered and len(processed[-1]) > 30:
|
||||
# 只有在下一个段落以数字序号开头且上一个段落长度大于30时,才将当前段落追加到上一个段落
|
||||
processed[-1] = processed[-1] + ' ' + current_text
|
||||
else:
|
||||
# 否则,不追加,而是作为新的段落添加
|
||||
@ -747,7 +745,7 @@ def handle_query(file_path, user_query, output_file, result_key, keywords):
|
||||
|
||||
# 生成用户查询
|
||||
user_query = generate_full_user_query(output_file, user_query)
|
||||
model_ans = doubao_model(user_query) # 豆包模型返回结果
|
||||
model_ans = qianwen_plus(user_query) # 豆包模型返回结果
|
||||
# file_id = upload_file(output_file)
|
||||
# model_ans = qianwen_long(file_id, user_query)
|
||||
num_list = process_string_list(model_ans) # 处理模型返回的序号
|
||||
@ -806,7 +804,7 @@ def combine_find_invalid(invalid_docpath, output_dir):
|
||||
要求与指南:
|
||||
文本中可能存在无关的信息,请准确筛选符合条件的信息,并将符合条件的信息的序号返回。
|
||||
输出格式:
|
||||
以 [x, x, x] 的形式返回,x 为符合条件的信息的序号。
|
||||
以 [x, x, x] 的形式返回,x 为符合条件的信息的序号,为自然数。
|
||||
如果文本中没有符合条件的信息,请返回 []。
|
||||
特殊情况:
|
||||
如果某序号的内容明显分为几部分且一部分内容符合筛选条件,但其他部分明显是无关内容,请返回符合部分的字符串内容代替序号。
|
||||
@ -825,7 +823,7 @@ def combine_find_invalid(invalid_docpath, output_dir):
|
||||
要求与指南:
|
||||
文本中可能存在无关的信息,请准确筛选符合条件的信息,并将符合条件的信息的序号返回。
|
||||
输出格式:
|
||||
返回结果以 [x, x, x] 的形式,其中 x 为符合条件的信息的序号。
|
||||
返回结果以 [x, x, x] 的形式,其中 x 为符合条件的信息的序号,为自然数。
|
||||
如果文本中没有任何符合条件的废标情况,请返回 []。
|
||||
示例输出,仅供格式参考:
|
||||
[1,3,4,6]
|
||||
@ -835,16 +833,21 @@ def combine_find_invalid(invalid_docpath, output_dir):
|
||||
"废标项"
|
||||
),
|
||||
(
|
||||
r'不\s*得(?!\s*分)|禁\s*止\s*投\s*标',
|
||||
"""以下是从招标文件中摘取的内容,文本中序号分明,文本内的条款以'...............'分割。每条条款规定了各方不得存在的情形。请根据以下要求进行筛选:
|
||||
r'不\s*得(?!\s*(分|力))|禁\s*止\s*投\s*标',
|
||||
"""以下是从招标文件中摘取的内容,文本中序号分明,文本内的条款以'...............'分割。条款规定了各方不得存在的情形。请根据以下要求进行筛选:
|
||||
**投标相关主体与非投标相关主体的定义**:
|
||||
投标相关主体:包括但不限于“投标人”、“中标人”、“供应商”、“联合体投标各方”、“响应人”、“应答人”或其他描述投标方的词语。
|
||||
非投标相关主体:包括但不限于“招标人”、“采购人”、“评标委员会”或其他描述非投标方的词语。
|
||||
**筛选要求**:
|
||||
1. **仅包含**明确描述投标主体禁止情形的条款,不包含笼统或未具体说明情形的条款。若条款内容诸如'投标人不得存在的其他关联情形'这样笼统的内容,而未说明具体的情形,则无需添加这条条款。
|
||||
2. **仅筛选**出主语为“投标人”、“中标人”、“供应商”、“联合体投标各方”或其他投标相关主体的条款,**或**描述的情形针对投标相关主体的条款。
|
||||
3. **排除**主语为“招标人”、“采购人”、“评标委员会”或其他非投标相关主体的条款。
|
||||
4. **特殊情况**:如果条款中包含“磋商小组”,且在语境中“磋商小组”指代或包含“投标方”,则应将其考虑在内;否则,排除该条款。
|
||||
1. **仅筛选**明确描述投标相关主体禁止情形或不得存在的情形的条款,不包含笼统或未具体说明情形的条款。例如:
|
||||
若条款内容包含'投标人不得存在的其他关联情形'这样的笼统描述,而未说明具体的情形,则无需添加该条款。
|
||||
2. **排除**仅描述非投标相关主体行为限制或禁止情形的条款,例如“招标人不得泄露信息”或“评标委员会不得收受贿赂”,则无需返回。
|
||||
3. 若条款同时描述了对投标相关主体与非投标相关主体的行为限制、禁止情形,也需返回。
|
||||
4. **特殊情况**:如果条款中包含“磋商小组”、”各方“等既能指代投标相关主体又能指代非投标相关主体的词汇:
|
||||
若在语境中其指代或包含投标相关主体,则应将其考虑在内;否则,排除该条款。
|
||||
|
||||
**输出格式**:
|
||||
返回结果以 [x, x, x] 的形式,其中 x 为符合条件的条款的序号。
|
||||
返回结果以 [x, x, x] 的形式,其中 x 为符合条件的条款的序号,为自然数。
|
||||
如果没有符合条件的条款,返回 `[]`。
|
||||
**示例**:
|
||||
- **符合条件**:
|
||||
@ -903,10 +906,10 @@ if __name__ == '__main__':
|
||||
# doc_path = r'C:\Users\Administrator\Desktop\new招标文件\tmp\2024-贵州-贵州省罗甸县 2024 年度广州市协作资金龙坪镇、边阳镇产业路硬化建设项目.docx'
|
||||
pdf_path = r'C:\Users\Administrator\Desktop\货物\test\磋商采购文件-恩施市森林火灾风险普查样品检测服务_invalid.pdf'
|
||||
|
||||
output_dir = r"C:\Users\Administrator\Desktop\货物\test"
|
||||
output_dir = r"D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\tmp"
|
||||
# invalid_added = insert_mark(pdf_path)
|
||||
# invalid_added_docx = pdf2docx(invalid_added)
|
||||
invalid_added_docx=r'C:\Users\Administrator\Desktop\货物\test\invalid_added.docx'
|
||||
invalid_added_docx=r'D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\invalid_added.docx'
|
||||
results = combine_find_invalid(invalid_added_docx, output_dir)
|
||||
end_time = time.time()
|
||||
print("Results:", json.dumps(results, ensure_ascii=False, indent=4))
|
||||
|
@ -86,8 +86,7 @@ def combine_evaluation_standards(evaluation_method):
|
||||
|
||||
evaluation_res = qianwen_long(file_id, user_query_2)
|
||||
# print(evaluation_res)
|
||||
target_values1 = ['技术标','技术部分','设计', '实施',"技术评分"]
|
||||
update_json = combine_technical_and_business(clean_json_string(evaluation_res), target_values1)
|
||||
update_json = combine_technical_and_business(clean_json_string(evaluation_res))
|
||||
return update_json #商务标技术标整合
|
||||
if __name__ == "__main__":
|
||||
# evaluation_method="C:\\Users\\Administrator\\Desktop\\招标文件\\output2\\zbtest3_evaluation_method.pdf"
|
@ -13,7 +13,7 @@ from flask_app.工程标.投标人须知正文提取指定内容工程标 import
|
||||
import concurrent.futures
|
||||
from flask_app.old_version.基础信息整合_old import combine_basic_info
|
||||
from flask_app.old_version.资格审查模块old_old import combine_review_standards
|
||||
from flask_app.old_version.商务评分技术评分整合 import combine_evaluation_standards
|
||||
from flask_app.old_version.商务评分技术评分整合old_version import combine_evaluation_standards
|
||||
from flask_app.general.format_change import pdf2docx, docx2pdf
|
||||
from flask_app.general.docx截取docx import copy_docx
|
||||
|
||||
|
@ -12,7 +12,7 @@ from flask_app.工程标.投标人须知正文提取指定内容工程标 import
|
||||
import concurrent.futures
|
||||
from flask_app.工程标.基础信息整合工程标 import combine_basic_info
|
||||
from flask_app.工程标.资格审查模块 import combine_review_standards
|
||||
from flask_app.old_version.商务评分技术评分整合 import combine_evaluation_standards
|
||||
from flask_app.old_version.商务评分技术评分整合old_version import combine_evaluation_standards
|
||||
from flask_app.general.format_change import pdf2docx, docx2pdf,doc2docx
|
||||
from flask_app.general.docx截取docx import copy_docx
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
# -*- encoding:utf-8 -*-
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from flask_app.general.商务技术评分提取 import combine_technical_and_business, parse_json_with_duplicates, \
|
||||
from flask_app.general.json_utils import clean_json_string
|
||||
from flask_app.general.商务技术评分提取 import combine_technical_and_business, \
|
||||
process_data_based_on_key, reorganize_data
|
||||
from flask_app.general.通义千问long import upload_file, qianwen_long
|
||||
|
||||
@ -98,10 +96,9 @@ def combine_evaluation_standards(truncate_file):
|
||||
evaluation_res = qianwen_long(file_id, user_query) #有些重复的键名,只有qianwen_long_text能保留
|
||||
# print(evaluation_res)
|
||||
# 清理和处理响应
|
||||
cleaned_evaluation_res = parse_json_with_duplicates(evaluation_res) #处理重复键名的情况
|
||||
cleaned_evaluation_res = clean_json_string(evaluation_res) #处理重复键名的情况
|
||||
result_data = process_data_based_on_key(cleaned_evaluation_res) #处理不知名外键的情况
|
||||
include = ['一包', '二包', '三包', '四包', '五包']
|
||||
target_values = ['技术', '设计', '实施']
|
||||
updated_jsons = {}
|
||||
|
||||
# 检查是否有外层键匹配 include 列表
|
||||
@ -110,10 +107,10 @@ def combine_evaluation_standards(truncate_file):
|
||||
for key in result_data:
|
||||
if any(item in key for item in include):
|
||||
inner_dict = result_data[key]
|
||||
updated_jsons[key] = combine_technical_and_business(inner_dict, target_values) #对于分包,单独对分包内的'技术评分''商务评分'作处理
|
||||
updated_jsons[key] = combine_technical_and_business(inner_dict) #对于分包,单独对分包内的'技术评分''商务评分'作处理
|
||||
else:
|
||||
# 没有匹配的项,对整个字典运行
|
||||
updated_jsons = combine_technical_and_business(result_data, target_values)
|
||||
updated_jsons = combine_technical_and_business(result_data)
|
||||
final_res=reorganize_data(updated_jsons,include) #重新组织字典,尤其是分包的情况
|
||||
return final_res
|
||||
else:
|
@ -275,7 +275,7 @@ def extract_business_deviation(busi_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)
|
||||
# print(business_requirements_string)
|
||||
prompt_template1 = """以下文本是项目采购需求的商务要求部分,请帮我将信息重新组织,键名为'商务要求',键值为字符串列表,其中每个字符串为一条商务要求,保留三角▲、五角星★(若有),但是去除开头的序号(若有)。
|
||||
**角色**
|
||||
你是一个专业的招投标业务专家,擅长从招标文件中总结商务要求的部分,并逐条列出,作为编写商务要求偏离表的前置准备。
|
||||
@ -283,7 +283,7 @@ def extract_business_deviation(busi_requirements_dict):
|
||||
**要求与指南**:
|
||||
1. 每条内容需要有实际的含义、要求,不能光有标题性质的表述如'售后服务期限(质保期)及要求'。
|
||||
2. 你的回答内容需从所给文本中整理,尽量不改变原文的表达(除非以下要求与指南3.的特殊情况),请勿擅自添加三角▲、五角星★。
|
||||
3. 若输入文本中存在嵌套键值对格式,且键值本身语义完整且符合'商务要求',可直接将其添加至'商务要求'的键值中;若键值字符串本身语义表达不完整,可将键值对用冒号':'拼接之后作为一条商务要求,若键值字符串以★、▲或其他特殊符号开头,将符号移至拼接后的开头,例如'"★交货地点:采购人指定地点"'。
|
||||
3. 若输入文本中存在嵌套键值对格式,且键值本身语义完整且符合'商务要求',可直接将其添加至'商务要求'的键值中;若键值字符串本身语义表达不完整、不明确,可将键值对用冒号':'拼接之后作为一条商务要求,若键值字符串以★、▲或其他特殊符号开头,将符号移至拼接后的开头,例如'"★交货地点:采购人指定地点"'。
|
||||
4. 对于以三角▲或五角星★或其他特殊符号开头的字符串:
|
||||
a. 如果该字符串仅为标题性质的表述且不具备实际商务要求的含义,请根据语义关联性将其开头的三角▲或五角星★添加到紧随其后的若干(可为一)内容之后,形成完整的商务要求,并确保整个内容连贯。
|
||||
注:默认在该字符串后面的一个字符串开头添加三角▲或五角星★,若有明确的序号或者语义表示了其后若干字符串之间的相关性,那么可在这些字符串开头都添加三角▲或五角星★,作为若干商务要求。
|
||||
|
@ -360,9 +360,9 @@ def truncate_pdf_main_engineering(input_path, output_folder, selection, logger,
|
||||
is_secondary_match = (idx == 2)
|
||||
begin_page = last_begin_index if last_begin_index != 0 else {
|
||||
1: 0, # 公告
|
||||
2: 10, # 评标
|
||||
2: 5, # 评标
|
||||
3: 5, # 资格
|
||||
4: 3, # 前附表
|
||||
4: 1, # 前附表
|
||||
5: 0 # 无效标
|
||||
}.get(selection, 0)
|
||||
|
||||
@ -443,12 +443,12 @@ if __name__ == "__main__":
|
||||
logger = get_global_logger("123")
|
||||
start_time = time.time()
|
||||
# input_path = r"C:\Users\Administrator\Desktop\new招标文件\工程标"
|
||||
pdf_path = r"C:\Users\Administrator\Desktop\工程\test\2022-广东-鹏华基金管理有限公司深圳深业上城办公室装修项目.pdf"
|
||||
pdf_path=r"D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\ztbfile.pdf"
|
||||
|
||||
# pdf_path = r"C:\Users\Administrator\Desktop\招标文件\招标02.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"
|
||||
selection = 5 # 例如:1 - 招标公告, 2 - 评标办法, 3 -资格审查条件 4-投标人须知前附表+正文 5-无效标
|
||||
output_folder = r"D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\tmp"
|
||||
selection = 4 # 例如:1 - 招标公告, 2 - 评标办法, 3 -资格审查条件 4-投标人须知前附表+正文 5-无效标
|
||||
generated_files = truncate_pdf_main_engineering(pdf_path, output_folder, selection, logger)
|
||||
print(generated_files)
|
||||
# print("生成的文件:", generated_files)
|
||||
|
@ -294,7 +294,7 @@ def generate_prompt(judge_res, full_text=None):
|
||||
base_prompt = '''
|
||||
任务:你负责解析采购文件,提取采购需求,并以JSON格式返回,不要遗漏该项目需要采购的货物、设备或系统。
|
||||
|
||||
输出格式:
|
||||
**输出格式**:
|
||||
1.JSON格式,外层键名为需要采购的货物、设备或系统名称(一级键)。
|
||||
2.层次关系用嵌套键值对表示:
|
||||
-采购活动可能将目标划分为多个系统或货物。若文档通过大标题或表格层次或序号标明这种归属关系,请在JSON中以嵌套形式表示:
|
||||
@ -310,14 +310,17 @@ def generate_prompt(judge_res, full_text=None):
|
||||
-若同一层级下存在名称相同但采购要求(如型号、参数、功能)不同的货物,请在名称后添加编号以作区分,防止出现重复键名;默认情况下,无需在名称后添加编号,只有在名称相同时才需要添加编号。编号规则:'名称-编号',编号从1递增。例子:若同层级下存在两种名称相同但不同型号或参数的'交换机',那么键名分别是'交换机-1'和'交换机-2'。如果名称不同(如路由器和交换机),则无需编号。
|
||||
4.最内层键值应为空列表[]。
|
||||
|
||||
要求与指南:
|
||||
**特殊情况**:
|
||||
-如果文件中未明确说明需要采购的货物、设备或系统,请直接返回空字典 {{}}。不要生成任何无关内容。
|
||||
|
||||
**要求与指南**:
|
||||
1. 精准定位:请运用文档理解能力,定位文件中的采购需求部分。
|
||||
-若有采购清单,请直接根据采购清单上的货物(或系统)名称给出结果,若没有采购清单,则从表格或文本中摘取采购信息。
|
||||
-注意采购目标通常在诸如'名称'列,且每个目标占据一个单元格,你无需提取诸如'说明'、'规格'、'参数'、'描述'等其他列的内容,即你不需要给出详细的采购要求,更不要将这些单元格内的描述拆分作为其的子键,你仅返回采购的货物或系统或模块名称;
|
||||
2. 采购目标:采购种类通常有硬件(如设备、货物)和软件(如系统软件、应用APP),一次采购活动可以同时包含这两种类型。
|
||||
3. 软件类采购:对于软件系统或应用采购,若有多个系统且序号分明,请不要遗漏;若明确列出系统模块,提取模块名称并作为系统的子键,无需在模块下再细分功能。
|
||||
4. 完整性:
|
||||
-若采购的货物或系统或模块名称前存在三角▲,△、五角★,☆,注意是名称前而非具体的技术参数或采购要求前,在返回名称时请保留前面的▲,△或★,☆符号,如'★高清摄像机'。
|
||||
-若采购的货物或系统或模块名称前存在三角▲,△、五角★,☆或其他特殊符号,注意是名称前而非具体的技术参数或采购要求前,在返回名称时请保留前面的▲,△或★,☆符号,如'★高清摄像机'。
|
||||
-确保系统内的所有货物设备均被按层次提取,对于有明确清单且按序号划分的采购需求,请勿遗漏每一个序号所代表的货物或设备或系统,也不要添加未提及的内容。
|
||||
-若某货物(或系统、模块)在“主要设备功能指标”或类似标题下有详细参数说明,但未在前面清单或表格中诸如'名称'的列中列出,也需将该货物名添加到结果中。
|
||||
|
||||
@ -350,6 +353,8 @@ def generate_prompt(judge_res, full_text=None):
|
||||
"XX管理系统":[],
|
||||
//其他系统
|
||||
}}
|
||||
示例输出3,无明确的采购需求:
|
||||
{{}}
|
||||
'''
|
||||
if '否' not in judge_res and full_text:
|
||||
# 添加文件内容部分
|
||||
@ -486,7 +491,7 @@ def get_technical_requirements(invalid_path,processed_filepath,model_type=1):
|
||||
judge_res = doubao_model(judge_query)
|
||||
if '否' in judge_res or model_type == 2:
|
||||
model_type = 2 # 使用qianwen-long+invalid_path
|
||||
print("no!调用invalid_path")
|
||||
print("processed_filepath中无采购需求!调用invalid_path")
|
||||
if invalid_path.lower().endswith('.pdf'): # 确保上传的是docx upload中一定是docx,但是get_deviation中可能上传的是pdf
|
||||
invalid_path = pdf2docx(invalid_path)
|
||||
file_id = upload_file(invalid_path)
|
||||
@ -499,11 +504,14 @@ def get_technical_requirements(invalid_path,processed_filepath,model_type=1):
|
||||
print(model_res)
|
||||
|
||||
cleaned_res = clean_json_string(model_res) #转字典
|
||||
if not cleaned_res:
|
||||
print("本项目没有采购需求!!!")
|
||||
return {"采购需求": {}}
|
||||
preprocessed_data=preprocess_data(cleaned_res) #确保最内层为[]
|
||||
processed_data=truncate_system_keys(preprocessed_data) #限制深度
|
||||
key_paths, grouped_paths, good_list, data_copy= generate_key_paths(processed_data) # 提取需要采购的货物清单 key_list:交通监控视频子系统.高清视频抓拍像机 ... grouped_paths是同一系统下同时有'交换机-1'和'交换机-2',提取'交换机' ,输出eg:{'交通标志.标志牌铝板', '交通信号灯.交换机'}
|
||||
modified_data=rename_keys(data_copy)
|
||||
user_query_template = """请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。请以 JSON 格式返回结果,键名为\"{}\",键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求或功能说明的字符串,请按原文内容回答,保留三角▲、五角★和序号,不可擅自增删内容,尤其是不可擅自添加序号。
|
||||
user_query_template = """请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。请以 JSON 格式返回结果,键名为\"{}\",键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求或功能说明的字符串,请按原文内容回答,保留三角▲、五角★或其他特殊符号(若有)和序号(若有),不可擅自增删内容,尤其是不可擅自添加序号。
|
||||
**重要限制**:
|
||||
- **仅提取技术参数或采购要求,不包括任何商务要求**。商务要求通常涉及供应商资格、报价条款、交货时间、质保等内容,是整体的要求;而技术参数或采购要求则具体描述产品的技术规格、功能、性能指标等。
|
||||
- **商务要求的关键词示例**(仅供参考,不限于此):报价、交货、合同、资质、认证、服务、保修期等。如果内容包含上述关键词,请仔细甄别是否属于商务要求。
|
||||
@ -538,7 +546,7 @@ def get_technical_requirements(invalid_path,processed_filepath,model_type=1):
|
||||
|
||||
{}
|
||||
"""
|
||||
user_query_template_two="""请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。由于该货物存在 {} 种不同的采购要求或技术参数,请逐一列出,并以 JSON 格式返回结果。请以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,即第一个键名为\"{}-1\";键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求或功能说明的字符串,请按原文内容回答,保留三角▲、五角★和序号(若有),不可擅自增删内容,尤其是不可擅自添加序号。
|
||||
user_query_template_two="""请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。由于该货物存在 {} 种不同的采购要求或技术参数,请逐一列出,并以 JSON 格式返回结果。请以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,即第一个键名为\"{}-1\";键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求或功能说明的字符串,请按原文内容回答,保留三角▲、五角★或其他特殊符号(若有)和序号(若有),不可擅自增删内容,尤其是不可擅自添加序号。
|
||||
|
||||
要求与指南:
|
||||
1. 你的键值应该全面,不要遗漏。
|
||||
@ -660,11 +668,11 @@ if __name__ == "__main__":
|
||||
# invalid_path="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile.pdf"
|
||||
# file_id = upload_file(truncate_file)
|
||||
truncate_file=r'C:\Users\Administrator\Desktop\new招标文件\output5\广水市公安局音视频监控系统设备采购项目_procurement.pdf'
|
||||
invalid_path=r"D:\flask_project\flask_app\static\output\output1\000aac0d-4aa4-4bc3-a9f9-76ff82ec2470\invalid_added.docx"
|
||||
invalid_path=r"D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\invalid_del.docx"
|
||||
# file_id=upload_file(truncate_file)
|
||||
# processed_filepath = convert_file_to_markdown(truncate_file)
|
||||
processed_filepath=r"C:\Users\Administrator\Desktop\文件解析问题\文件解析问题\baada43d-24f6-459d-8a81-219d130f20da\extract1.txt"
|
||||
res=get_technical_requirements(invalid_path,processed_filepath)
|
||||
processed_filepath=r"D:\flask_project\flask_app\static\output\output1\f91db70d-8d96-44a5-b840-27d2f1ecbe95\extract1.txt"
|
||||
res=get_technical_requirements(invalid_path,processed_filepath,1)
|
||||
json_string = json.dumps(res, ensure_ascii=False, indent=4)
|
||||
print(json_string)
|
||||
# # input_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user