11.20 修改bug

This commit is contained in:
zy123 2024-11-20 15:44:05 +08:00
parent 63476636b7
commit 6dd1e02290
14 changed files with 266 additions and 82 deletions

View File

@ -29,4 +29,4 @@ ENV ALIBABA_CLOUD_ACCESS_KEY_SECRET=88oyw7LniqV8i0SnOuSFS5lprfrPtw
EXPOSE 5000
# 在容器启动时运行你的应用
CMD ["python", "flask_app/main/start_up.py"]
CMD ["python", "flask_app/start_up.py"]

View File

@ -69,7 +69,7 @@ def extract_business_requirements(data):
counter += 1
business_requirements_string = json.dumps(new_data, ensure_ascii=False, indent=4)
print(business_requirements_string)
# print(business_requirements_string)
prompt_template1 = """请帮我从以下文本中摘取商务要求部分,并将信息重新组织,外键名为'商务要求',键值为字符串列表,其中每个字符串为一条商务要求,去除开头的序号(若有)。
#角色
你是一个专业的招投标业务专家擅长从招标文件中总结商务要求的部分并逐条列出作为编写商务要求偏离表的前置准备
@ -415,7 +415,7 @@ def outer_post_processing(combined_data, includes, good_list):
extracted_info = {}
# 初始化采购要求的技术要求
procurement_reqs = ""
tech_deviation = ""
zige_info=""
fuhe_info=""
@ -430,10 +430,10 @@ def outer_post_processing(combined_data, includes, good_list):
tech_requirements = get_nested(base_info, ["采购要求", "采购需求"], {})
if tech_requirements:
procurement_reqs = extract_matching_keys(tech_requirements, good_list)
tech_deviation = extract_matching_keys(tech_requirements, good_list)
else:
# 如果 '技术要求' 不存在或为空,可以根据需要设置默认值
procurement_reqs = "未提供"
tech_deviation = "未提供"
if "资格审查" in includes:
zige_review = combined_data.get("资格审查", {})
@ -452,9 +452,9 @@ def outer_post_processing(combined_data, includes, good_list):
}, ensure_ascii=False, indent=4)
except KeyError as e:
print(f"缺少关键字: {e}")
# tech_star_deviation=get_tech_star_deviation(json.dumps(procurement_reqs,ensure_ascii=False,indent=4))
# business_req_deviation = extract_business_requirements(get_nested(combined_data, ['基础信息'], {}))
# zige_deviation,fuhe_deviation=extract_zige_deviation_table(zige_info,fuhe_info)
tech_star_deviation=get_tech_star_deviation(json.dumps(tech_deviation,ensure_ascii=False,indent=4))
business_deviation,business_star_deviation = extract_business_requirements(get_nested(combined_data, ['基础信息'], {}))
zige_deviation,fuhe_deviation=extract_zige_deviation_table(zige_info,fuhe_info)
# 遍历原始字典的每一个键值对
for key, value in combined_data.items():
@ -473,7 +473,7 @@ def outer_post_processing(combined_data, includes, good_list):
if not processed_data["其他"]:
del processed_data["其他"]
return processed_data, extracted_info, procurement_reqs
return processed_data, extracted_info, tech_deviation,tech_star_deviation,business_deviation,business_star_deviation,zige_deviation,fuhe_deviation
if __name__ == "__main__":

View File

@ -130,13 +130,13 @@ def rag_assistant(knowledge_name):
#TODO:http格式有bug还没修改
def create_assistant(knowledge_name):
"""
Create an assistant using DashScope API via HTTP request based on the provided knowledge name.
Create an assistant using DashScope routes via HTTP request based on the provided knowledge name.
Parameters:
knowledge_name (str): The name of the knowledge base to associate with the assistant.
Returns:
dict: Response from the API containing assistant details.
dict: Response from the routes containing assistant details.
Raises:
ValueError: If the DASHSCOPE_API_KEY environment variable is not set.
@ -150,12 +150,12 @@ def create_assistant(knowledge_name):
print(f"Error retrieving pipeline ID for knowledge '{knowledge_name}': {e}")
return None
# Step 2: Fetch the API Key from Environment Variables
# Step 2: Fetch the routes Key from Environment Variables
api_key = os.getenv("DASHSCOPE_API_KEY")
if not api_key:
raise ValueError("DASHSCOPE_API_KEY environment variable is not set.")
# Step 3: Define the API Endpoint and Headers
# Step 3: Define the routes Endpoint and Headers
url = 'https://dashscope.aliyuncs.com/api/v1/assistants'
headers = {
"Content-Type": "application/json",
@ -258,7 +258,7 @@ def multi_threading(queries, knowledge_name="", file_id="", llm_type=1):
result_queue = queue.Queue()
max_retries = 2 # 设置最大重试次数
# 使用 ThreadPoolExecutor 管理线程
with concurrent.futures.ThreadPoolExecutor(max_workers=60) as executor:
with concurrent.futures.ThreadPoolExecutor(max_workers=30) as executor:
# 逐个提交任务每提交一个任务后休眠1秒
future_to_query = {}
for index, query in enumerate(queries):

View File

@ -39,17 +39,16 @@ def get_technical_requirements_main(file_path,file_type,unique_id,output_folder)
# file_id=upload_file(truncate_file)
final_res=get_technical_requirements(truncate_file,pdf_path)
# 安全地提取 "技术要求" 内部的字典内容
if isinstance(final_res, dict) and '技术要' in final_res and isinstance(final_res['技术要'], dict):
technical_requirements = final_res['技术要']
if isinstance(final_res, dict) and '采购需' in final_res and isinstance(final_res['采购需'], dict):
technical_requirements = final_res['采购需']
good_list = technical_requirements.pop('货物列表', []) # 如果 '货物列表' 不存在,返回 []
print(good_list)
logger.info("Collected good_list from the processing function: %s", good_list)
return extract_matching_keys(technical_requirements,good_list)
else:
return final_res
if __name__ == "__main__":
file_path="C:\\Users\\Administrator\\Desktop\\货物标\\zbfiles\\包头市公安支队机动车查验监管系统招标文201907.pdf"
file_path=r"C:\Users\Administrator\Desktop\货物标\zbfiles\2-招标文件(广水市教育局封闭管理).pdf"
file_type=2
output_folder = "C:\\Users\\Administrator\\Desktop\\fsdownload\\45f650ce-e519-457b-9ad6-5840e2ede539\\tmp"
output_folder = r"C:\Users\Administrator\Desktop\fsdownload\39b0c3b4-1807-456c-8330-c5c7d1b7a2ca\tmp"
res=get_technical_requirements_main(file_path,file_type,"123",output_folder)
print(json.dumps(res,ensure_ascii=False,indent=4))

View File

@ -81,7 +81,7 @@ def qianwen_long_text(file_id, user_query):
return completion.choices[0].message.content
def qianwen_long_stream(file_id, user_query):
print("调用 qianwen-long text...")
print("调用 qianwen-long stream...")
"""
使用之前上传的文件根据用户查询生成响应并实时显示流式输出
"""
@ -93,7 +93,7 @@ def qianwen_long_stream(file_id, user_query):
# 生成基于文件ID的响应
completion = client.chat.completions.create(
model="qwen-long",
temperature=0.5,
temperature=0.4,
messages=[
{
'role': 'system',

View File

@ -28,7 +28,7 @@ def delete_index(client: bailian20231229Client, workspace_id: str, index_id: str
headers = {}
try:
response = client.delete_index_with_options(workspace_id, delete_index_request, headers, runtime)
print("API Response:", response)
print("routes Response:", response)
except Exception as error:
print(error.message)
print(error.data.get("Recommend"))
@ -42,7 +42,7 @@ async def delete_index_async(client: bailian20231229Client, workspace_id: str, i
headers = {}
try:
response = await client.delete_index_with_options_async(workspace_id, delete_index_request, headers, runtime)
print("API Response:", response)
print("routes Response:", response)
except Exception as error:
print(error.message)
print(error.data.get("Recommend"))

View File

@ -22,7 +22,7 @@ def query():
id='docmind-20241008-24363df30d274863894f037dbb7244e8'
)
try:
# 复制代码运行请自行打印 API 的返回值
# 复制代码运行请自行打印 routes 的返回值
response = client.query_doc_parser_status(request)
# API返回值格式层级为 body -> data -> 具体属性。可根据业务需要打印相应的结果。获取属性值均以小写开头
# 获取返回结果。建议先把response.body.data转成json然后再从json里面取具体需要的值。

View File

@ -29,7 +29,7 @@ def submit_file():
)
runtime = util_models.RuntimeOptions()
try:
# 复制代码运行请自行打印 API 的返回值
# 复制代码运行请自行打印 routes 的返回值
response = client.submit_doc_parser_job_advance(request, runtime)
# API返回值格式层级为 body -> data -> 具体属性。可根据业务需要打印相应的结果。如下示例为打印返回的业务id格式
# 获取属性值均以小写开头,

View File

@ -24,7 +24,7 @@ def query():
layout_num=0
)
try:
# 复制代码运行请自行打印 API 的返回值
# 复制代码运行请自行打印 routes 的返回值
response = client.get_doc_parser_result(request)
# API返回值格式层级为 body -> data -> 具体属性。可根据业务需要打印相应的结果。获取属性值均以小写开头
# 获取返回结果。建议先把response.body.data转成json然后再从json里面取具体需要的值。

View File

@ -4,7 +4,7 @@ import os
def convert_pdf_to_word(file_path, output_dir, output_format='docx'):
"""
Converts a PDF file to a Word document using a specified API.
Converts a PDF file to a Word document using a specified routes.
:param file_path: Path to the PDF file to convert.
:param output_dir: Directory to save the converted Word document.

View File

@ -403,17 +403,70 @@ def process_and_stream(file_url, zb_type):
output_json_path = os.path.join(output_folder, 'final_result.json')
extracted_info_path = os.path.join(output_folder, 'extracted_result.json')
includes = ["基础信息", "资格审查", "商务评分", "技术评分", "无效标与废标项", "投标文件要求", "开评定标流程"]
final_result, extracted_info, procurement_reqs = outer_post_processing(combined_data, includes, good_list)
final_result, extracted_info,tech_deviation,tech_star_deviation,business_deviation,business_star_deviation,zige_deviation,fuhe_deviation = outer_post_processing(combined_data, includes, good_list)
logger.info(
f"Procurement requirements extracted: {json.dumps(procurement_reqs, ensure_ascii=False, indent=4)}") # 添加日志记录
f"技术偏离表: {json.dumps(tech_deviation, ensure_ascii=False, indent=4)}"
) # 添加日志记录
logger.info(
f"技术偏离表带星: {json.dumps(tech_star_deviation, ensure_ascii=False, indent=4)}"
) # 添加日志记录
logger.info(
f"商务偏离表: {json.dumps(business_deviation, ensure_ascii=False, indent=4)}"
) # 添加日志记录
logger.info(
f"商务偏离表带星: {json.dumps(business_star_deviation, ensure_ascii=False, indent=4)}"
) # 添加日志记录
logger.info(
f"资格检查偏离表: {json.dumps(zige_deviation, ensure_ascii=False, indent=4)}"
) # 添加日志记录
logger.info(
f"符合性检查偏离表: {json.dumps(fuhe_deviation, ensure_ascii=False, indent=4)}"
) # 添加日志记录
# 采购需求
procurement_reqs_response = {
tech_deviation_response = {
'message': 'procurement_reqs',
'filename': os.path.basename(downloaded_filepath),
'data': json.dumps(procurement_reqs, ensure_ascii=False)
'data': json.dumps(tech_deviation, ensure_ascii=False)
}
yield f"data: {json.dumps(procurement_reqs_response, ensure_ascii=False)}\n\n"
tech_deviation_star_response = {
'message': 'jishu_star_deviation',
'filename': filename,
'data': json.dumps(tech_star_deviation, ensure_ascii=False)
}
zige_deviation_response = {
'message': 'zige_deviation',
'filename': filename,
'data': json.dumps(zige_deviation, ensure_ascii=False)
}
fuhe_deviation_response = {
'message': 'fuhe_deviation',
'filename': filename,
'data': json.dumps(fuhe_deviation, ensure_ascii=False)
}
shangwu_deviation_response = {
'message': 'shangwu_deviation',
'filename': filename,
'data': json.dumps(business_deviation, ensure_ascii=False)
}
shangwu_star_deviation_response = {
'message': 'shangwu_star_deviation',
'filename': filename,
'data': json.dumps(business_star_deviation, ensure_ascii=False)
}
yield f"data: {json.dumps(tech_deviation_response, ensure_ascii=False)}\n\n"
yield f"data: {json.dumps(tech_deviation_star_response, ensure_ascii=False)}\n\n"
yield f"data: {json.dumps(zige_deviation_response, ensure_ascii=False)}\n\n"
yield f"data: {json.dumps(fuhe_deviation_response, ensure_ascii=False)}\n\n"
yield f"data: {json.dumps(shangwu_deviation_response, ensure_ascii=False)}\n\n"
yield f"data: {json.dumps(shangwu_star_deviation_response, ensure_ascii=False)}\n\n"
try:
with open(extracted_info_path, 'w', encoding='utf-8') as json_file:
@ -579,12 +632,11 @@ def test_process_and_stream():
"数量": "500立方米",
"规格": "C30"
}
procurement_reqs_response = {
tech_deviation_response = {
'message': 'procurement_reqs',
'filename': filename,
'data': json.dumps(procurement_reqs, ensure_ascii=False)
}
yield f"data: {json.dumps(procurement_reqs_response, ensure_ascii=False)}\n\n"
zige_deviation_table = {
"资格性检查": ["具有独立承担民事责任的能力;", "具有良好的商业信誉和健全的财务会计制度;",
@ -641,11 +693,14 @@ def test_process_and_stream():
'filename': filename,
'data': json.dumps(jishu_star_deviation_table, ensure_ascii=False)
}
yield f"data:{json.dumps(zige_deviation_response, ensure_ascii=False)}\n\n"
yield f"data:{json.dumps(fuhe_deviation_response, ensure_ascii=False)}\n\n"
yield f"data:{json.dumps(shangwu_deviation_response, ensure_ascii=False)}\n\n"
yield f"data:{json.dumps(shangwu_star_deviation_response, ensure_ascii=False)}\n\n"
yield f"data:{json.dumps(jishu_star_deviation_response, ensure_ascii=False)}\n\n"
yield f"data: {json.dumps(tech_deviation_response, ensure_ascii=False)}\n\n"
# 发送完整的大字典
complete_response = {

View File

@ -10,55 +10,83 @@ from flask_app.货物标.截取pdf货物标版 import extract_common_header, cle
#正则表达式判断原文中是否有商务、服务、其他要求
def find_exists(truncate_file, required_keys):
if not truncate_file:
return ["技术要求","商务要求", "服务要求", "其他要求"]
common_header = extract_common_header(truncate_file)
return ["技术要求", "商务要求", "服务要求", "其他要求"]
common_header = extract_common_header(truncate_file) # 假设该函数已定义
pdf_document = PdfReader(truncate_file)
text = ""
# 定义正则模式
begin_pattern = re.compile(
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(?:服务|项目|商务|技术).*?要求|'
r'^第[一二三四五六七八九十百千]+(?:章|部分).*?(?:采购|技术标准).*|'
r'^[一二三四五六七八九十百千]+、\s*采购清单', re.MULTILINE)
r'(?:^第[一二三四五六七八九十百千]+(?:章|部分)\s*' # 匹配“第X章”或“第X部分”
r'[\u4e00-\u9fff、()]*?' # 匹配允许的字符
r'(?:(?:服务|项目|商务|技术)[\u4e00-\u9fff、()]*?要求|' # 匹配“服务”、“项目”、“商务”或“技术”后跟“要求”
r'(?:采购|需求)[\u4e00-\u9fff、()]*?)' # 匹配“采购”或“需求”
r'\s*$|' # 匹配行尾
r'^第[一二三四五六七八九十百千]+(?:章|部分)(?!.*说明).*?' # 匹配“第X章”后带“采购内容”等排除“说明”
r'(?:采购内容|采购要求|需求).*|' # 匹配“采购内容”或“采购要求”关键词
r'^[一二三四五六七八九十百千]+、\s*采购清单)' # 匹配“一、采购清单”
r'\s*$', # 匹配行尾
re.MULTILINE
)
end_pattern = re.compile(
r'^第[一二三四五六七八九十百千]+(?:章|部分)\s*[\u4e00-\u9fff]+', re.MULTILINE)
r'第[一二三四五六七八九1-9]+(?:章|部分)\s*[\u4e00-\u9fff、()]+\s*$', re.MULTILINE)
# 遍历所有页面,拼接全文
text = ""
for page in pdf_document.pages:
page_text = page.extract_text() or ""
cleaned_text = clean_page_content(page_text, common_header)
text += cleaned_text + '\n'
text += cleaned_text + "\n"
# 匹配起始位置
start_match = re.search(begin_pattern, text)
if not start_match:
print("未找到开始模式")
return []
start_index = start_match.end()
end_match = re.search(end_pattern, text[start_index:])
# 匹配结束位置
end_match = re.search(end_pattern, text[start_index:])
if end_match:
end_index = start_index + end_match.start()
relevant_text = text[start_index:end_index]
else:
relevant_text = text[start_index:]
relevant_text=re.sub(r'\s+', '', relevant_text) #删除换行符 空格
# print(relevant_text)
# Custom logic for "服务要求"
# 保留换行,避免结构丢失
relevant_text = re.sub(r'\s+', ' ', relevant_text)
# print(f"提取的内容范围:\n{relevant_text}")
# 匹配所需的要求
matched_requirements = []
punctuation = r"[,。?!、;:,.?!]*"
for req in required_keys:
if re.search(re.escape(req), relevant_text):
if req == "服务要求":
# required_keys 中的元素本身已包含 \s*,直接作为正则模式
if re.search(req, relevant_text):
if req == "\s*务\s*要\s*求":
# 提取所有包含"服务要求"的行
lines = [line for line in relevant_text.split('\n') if req in line]
lines = [line for line in relevant_text.split('\n') if re.search(req, line)]
# 检查是否存在'技术'紧跟在'服务要求'前面(中间只有标点,标点是可选的)
pattern = r'技术\s*' + punctuation + re.escape(req)
# 如果存在'技术'紧跟'服务要求'并且中间仅有标点(可选),则不添加该要求
if not any(re.search(pattern, line) for line in lines):
pattern = "\s*术" + punctuation + req
if any(re.search(pattern, line) for line in lines):
# 如果存在'技术'紧跟'服务要求',添加"技术、服务要求"
if "\s*术\s*、\s*服\s*务\s*要\s*求" not in matched_requirements:
matched_requirements.append("\s*术\s*、\s*服\s*务\s*要\s*求")
else:
# 如果不存在'技术'紧跟'服务要求',正常添加"服务要求"
matched_requirements.append(req)
else:
matched_requirements.append(req)
return matched_requirements
# 去除 \s*,仅返回原始关键词
clean_requirements = [re.sub(r'\\s\*', '', req) for req in matched_requirements]
# 判断互斥关系:如果有"技术、服务要求",删除"技术要求"和"服务要求"
if "技术、服务要求" in clean_requirements:
clean_requirements = [req for req in clean_requirements if req not in ["技术要求", "服务要求"]]
return clean_requirements
def generate_queries(truncate_file, required_keys):
key_list = find_exists(truncate_file, required_keys)
@ -74,24 +102,116 @@ def generate_queries(truncate_file, required_keys):
# print(query_base)
return queries
def generate_user_query_template(required_keys):
import textwrap
import json
# 定义所有可能的键
all_possible_keys = ["技术要求", "服务要求", "商务要求", "其他要求", "技术、服务要求"]
# 定义每个键对应的示例内容
example_content1 = {
"技术要求": ["相关技术要求以及服务要求1", "相关技术要求以及服务要求2"],
"服务要求": ["服务要求1", "服务要求2"],
"商务要求": {
"★产品质保期": ["所投 LED 整屏不低于 3 年,健身器材整套不低于 2 年"],
"售后服务方案": ["包含产品配送、安装保障方案"]
},
"其他要求": {
"子因素名1": ["关于项目采购的其他要求1...", "关于项目采购的其他要求2..."],
"子因素名2": ["关于项目采购的其他要求3...", "关于项目采购的其他要求4..."]
},
"技术、服务要求": ["相关技术、服务要求内容1", "相关技术、服务要求内容2"]
}
example_content2 = {
"技术要求": {
"子因素名1": ["相关技术要求1", "相关技术要求2"],
"子因素名2": ["相关技术要求3"]
},
"服务要求": {
"子因素名1": ["相关服务要求1", "相关服务要求2"],
"子因素名2": ["相关服务要求3", "相关服务要求4"]
},
"商务要求": ["所投 LED 整屏不低于 3 年,健身器材整套不低于 2 年", "包含产品配送、安装保障方案"],
"其他要求": ["关于项目采购的其他要求1..."],
"技术、服务要求": {
"子因素名1": ["相关技术、服务要求内容1"],
"子因素名2": ["相关技术、服务要求内容2", "相关技术、服务要求内容3"]
}
}
# 将 required_keys 转换为集合以便于操作
keys = set(required_keys)
# 处理互斥关系:如果 "技术要求" 和 "服务要求" 同时存在,则移除 "技术、服务要求"
if "技术要求" in keys and "服务要求" in keys:
keys.discard("技术、服务要求")
# 如果 "技术、服务要求" 存在,则移除 "技术要求" 和 "服务要求"
elif "技术、服务要求" in keys:
keys.discard("技术要求")
keys.discard("服务要求")
# 确保 keys 中只包含允许的键
keys = keys.intersection(all_possible_keys)
# 按照预定义的顺序排序键,以保持一致性
sorted_keys = [key for key in all_possible_keys if key in keys]
# 如果没有任何键被选中,返回一个默认的模板或抛出异常
if not sorted_keys:
raise ValueError("required_keys 中没有有效的键。")
# 生成提示部分,根据 sorted_keys 动态构建
keys_str = ''.join(sorted_keys)
outer_keys_str = ', '.join([f"'{key}'" for key in sorted_keys])
# 使用三引号定义多行字符串,便于编辑和维护
prompt_instruction = textwrap.dedent(f"""请你根据该货物类招标文件中的采购要求部分内容,请告诉我该项目采购的{keys_str}分别是什么请以json格式返回结果默认情况下外层键名是{outer_keys_str},键值为字符串列表,每个字符串表示具体的一条要求,内容需要与原文保持一致,不可擅自总结删减。
要求与指南
1. 默认情况无需嵌套键值为字符串列表若存在嵌套结构嵌套键名是原文中该要求下相应子标题最多一层嵌套
2. JSON 的结构要求
- 外层键名为 {outer_keys_str} 中的各项
- 每个外层键对应的值可以是
a. 一个对象字典其键为子因素名值为字符串列表
b. 一个字符串列表表示具体的一条条要求若只有一条要求也用字符串列表表示
- 最多只允许一层嵌套
3. 请优先定位正文部分的大标题'xx要求'在其之后提取'xx要求'相关内容由于要求的位置比较集中请尽量避免在全文各处寻找
4. 在提取技术要求或技术服务要求时若有你无需从采购清单或表格中提取货物名以及参数要求你仅需定位到原文中相应位置正文部分而非表格中并提取正文内容通常一类要求写在一块大标题下否则键值为空列表
5. 若无相关要求键值为[]
""")
# 过滤 example_content1 和 example_content2 以仅包含 sorted_keys
def filter_content(example_content, keys):
return {k: v for k, v in example_content.items() if k in keys}
filtered_example_content1 = filter_content(example_content1, sorted_keys)
filtered_example_content2 = filter_content(example_content2, sorted_keys)
# 将过滤后的示例转换为格式化的 JSON 字符串
json_example1_str = json.dumps(filtered_example_content1, indent=4, ensure_ascii=False)
json_example2_str = json.dumps(filtered_example_content2, indent=4, ensure_ascii=False)
# 完整的用户查询模板,包含两份示例输出
user_query_template = f"""
{prompt_instruction}
以下为示例输出仅供格式参考
示例 1
{json_example1_str}
示例 2
{json_example2_str}
"""
return user_query_template
def get_business_requirements(procurement_path):
file_id=upload_file(procurement_path)
# required_keys = ["技术要求","商务要求", "服务要求", "其他要求"]
# queries = generate_queries(truncate_file, required_keys)
#一起问了,效率慢点,但内容准
user_query="""
请你根据该货物类招标文件中的采购要求部分内容请告诉我文档中技术要求服务要求商务要求其他要求分别是什么注意事项在提取技术要求和服务要求的时候你无需从采购清单或表格中提取货物名以及参数要求你仅需定位到原文中相应位置正文部分而非表格中并提取原文内容通常一类要求写在一块大标题下请以json格式返回结果可以用嵌套键值对的形式组织回答默认情况下外层键名是'技术要求''服务要求''商务要求''其他要求'嵌套键名是原文中的相应子标题或者是你对相关子要求的总结而键值需要与原文保持一致不可擅自总结删减
以下是你需要考虑的特殊情况如果原文中技术要求与服务要求在一块那么你应该用外键'技术、服务要求'替换默认外键'技术要求''服务要求'若相关要求不存在对应的键值设为'未知'以下为示例输出仅供格式参考
{
"技术、服务要求":"相关技术要求以及服务要求",
"商务要求":{
"★产品质保期":"所投 LED 整屏不低于 3 年,健身器材整套不低于 2 年",
"售后服务方案":"包含产品配送、安装保障方案"
},
"其他要求""未知"
}"""
required_keys = ["\s*术\s*要\s*求","\s*务\s*要\s*求", "\s*务\s*要\s*求", "\s*他\s*要\s*求"]
contained_keys=find_exists(procurement_path,required_keys)
print(contained_keys)
# queries = generate_queries(truncate_file, contained_keys)
user_query=generate_user_query_template(contained_keys)
business_requirements=qianwen_long_stream(file_id,user_query)
# Combine and fill missing keys with default values
final_res = clean_json_string(business_requirements)
@ -101,7 +221,7 @@ def get_business_requirements(procurement_path):
#TODO:改为先判断,再摘取
if __name__ == "__main__":
# truncate_file = "C:\\Users\\Administrator\\Desktop\\fsdownload\\e4be098d-b378-4126-9c32-a742b237b3b1\\ztbfile_procurement.docx"
truncate_file="D:\\flask_project\\flask_app\\static\\output\\output1\\55dc56f0-f7fe-4734-95a3-867df3456d49\\招招招标文件一中多媒体报告厅教学设备_procurement.docx"
file_id = upload_file(truncate_file)
truncate_file=r"C:\Users\Administrator\Desktop\货物标\output1\2-招标文件广水市教育局封闭管理_procurement.pdf"
# file_id = upload_file(truncate_file)
res=get_business_requirements(truncate_file)
print(json.dumps(res, ensure_ascii=False, indent=4))

View File

@ -354,11 +354,12 @@ def get_technical_requirements(file_path,invalid_path):
ffinal_res = postprocess(cleaned_res)
else:
# user_query_template = "请你根据该货物标中采购要求部分的内容,请你给出\"{}\"的技术参数或采购要求请以json格式返回结果外层键名为\"{}\", 键值对中的键是你对该要求的总结,而值需要完全与原文保持一致,不可擅自总结删减。"
user_query_template = """请根据以下货物标中采购要求部分的内容,为\"{}\"生成技术参数(或采购要求)。请以 JSON 格式返回结果,外层键名为\"{}\"最内层键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求的字符串,内容需与原文一致,即若技术参数前存在序号也要保留,但不可擅自增添或删减。
user_query_template = """请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。请以 JSON 格式返回结果,键名为\"{}\"键值为一个列表,列表中包含若干描述\"{}\"的技术参数或采购要求的字符串,内容需与原文一致,即若技术参数前存在序号也要保留,但不可擅自增添或删减。
要求与指南
1. 如果该货物没有相关采购要求或技术参数要求键值应为空列表
2. 如果存在嵌套结构且原文为Markdown 的表格语法'摄像机|有效像素|≥900W像素' 请不要返回该Markdown语法而是使用冒号':'将相关信息拼接在一起生成一条完整且清晰的技术参数或采购要求描述作为列表中的一个字符串"摄像机有效像素≥900W像素"
3. 字符串中的内容为具体的技术参数要求或采购要求请不要返回诸如'1高清录像功能'这种标题性质且不能体现要求的内容
4. 你的键值应该全面对于同一个单元格内的数据尽量全面不要遗漏
### 示例输出1如下
{{
@ -368,23 +369,23 @@ def get_technical_requirements(file_path,invalid_path):
]
}}
### 示例输出2如下
### 示例输出2如下(包含嵌套结构)
{{
"摄像机": [
"摄像机有效像素≥900W像素",
"摄像机最低照度彩色≤0.001lx",
"协议:API 接口开放:具备;支持标准 ONVIF 协议与第三方厂家设备进行互联;支持 GB/T28181应提供 SDK"
"协议:routes 接口开放:具备;支持标准 ONVIF 协议与第三方厂家设备进行互联;支持 GB/T28181应提供 SDK"
]
}}
"""
user_query_template_two="""请根据以下货物标中采购要求部分的内容,为\"{}\"生成技术参数(或采购要求)。由于该货物存在多种不同的采购要求或技术参数,请逐一列出,并以 JSON 格式返回结果。请以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,即第一个键名为\"{}-1\", 键值为一个列表,列表中包含若干描述\"{}\"的技术参数(或采购要求)的字符串,需与原文完全一致,即若技术参数前存在序号也要保留,但不可擅自增添或删减。
user_query_template_two="""请根据货物标中采购要求部分的内容,告诉我\"{}\"的技术参数或采购要求是什么。由于该货物存在多种不同的采购要求或技术参数,请逐一列出,并以 JSON 格式返回结果。请以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,即第一个键名为\"{}-1\", 键值为一个列表,列表中包含若干描述\"{}\"的技术参数(或采购要求)的字符串,需与原文完全一致,即若技术参数前存在序号也要保留,但不可擅自增添或删减。
请注意以下特殊情况
要求与指南
1. 如果该货物没有相关采购要求或技术参数要求键值应为空列表
2. 如果存在嵌套结构且原文为Markdown 的表格语法'摄像机|有效像素|≥900W像素' 请不要返回该Markdown语法而是使用冒号':'将相关信息拼接在一起生成一条完整且清晰的技术参数或采购要求描述作为列表中的一个字符串"摄像机有效像素≥900W像素"
3. 字符串中的内容为具体的技术参数要求或采购要求请不要返回诸如'1高清录像功能'这种标题性质且不能体现要求的内容
### 示例输出,参考1如下
### 示例输出1如下
{{
"交换机-1": [
"1、支持固化千兆电口≥8 个固化千兆光口≥2 个,桌面型设备;",
@ -396,12 +397,12 @@ def get_technical_requirements(file_path,invalid_path):
]
}}
### 示例输出,参考2如下包含嵌套结构
### 示例输出2如下包含嵌套结构
{{
"摄像机-1": [
"摄像机有效像素≥900W像素",
"摄像机最低照度彩色≤0.001lx",
"协议:API 接口开放:具备;支持标准 ONVIF 协议与第三方厂家设备进行互联;支持 GB/T28181应提供 SDK"
"协议:routes 接口开放:具备;支持标准 ONVIF 协议与第三方厂家设备进行互联;支持 GB/T28181应提供 SDK"
],
"摄像机-2": [
"支持夜视", "支持云存储"
@ -431,6 +432,7 @@ def get_technical_requirements(file_path,invalid_path):
# 打印结果
for question, response in results:
technical_requirements.append(response)
# print(response)
technical_requirements_combined_res = combine_json_results(technical_requirements)
"""根据所有键是否已添加处理技术要求"""
@ -440,7 +442,7 @@ def get_technical_requirements(file_path,invalid_path):
# final_res = postprocess(cleaned_res)
ffinal_res["货物列表"] = good_list
# 输出最终的 JSON 字符串
return {"采购需求": ffinal_res}
return {"采购需求":ffinal_res}
def test_all_files_in_folder(input_folder, output_folder):
# 确保输出文件夹存在

View File

@ -111,11 +111,19 @@ def postprocess(data):
# 递归处理顶层数据
return {key: convert_dict(val) if isinstance(val, dict) else val for key, val in data.items()}
def all_postprocess(data):
temp=restructure_data(data)
processed_data = {}
for key, value_list in temp.items():
processed_data[key] = remove_common_prefixes(value_list)
temp = restructure_data(data)
def recursive_process(item):
if isinstance(item, dict):
return {k: recursive_process(v) for k, v in item.items()}
elif isinstance(item, list):
return remove_common_prefixes(item)
else:
return item
processed_data = recursive_process(temp)
return processed_data
def detect_depth(data):
"""