11.16
This commit is contained in:
parent
8a8985d9f4
commit
22a8b5676a
@ -1,125 +0,0 @@
|
|||||||
import PyPDF2
|
|
||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
from flask_app.general.clean_pdf import extract_common_header, clean_page_content
|
|
||||||
|
|
||||||
|
|
||||||
def extract_text_by_page(file_path):
|
|
||||||
common_header = extract_common_header(file_path)
|
|
||||||
# print(f"公共抬头:{common_header}")
|
|
||||||
# print("--------------------正文开始-------------------")
|
|
||||||
result = ""
|
|
||||||
with open(file_path, 'rb') as file:
|
|
||||||
reader = PyPDF2.PdfReader(file)
|
|
||||||
num_pages = len(reader.pages)
|
|
||||||
# print(f"Total pages: {num_pages}")
|
|
||||||
for page_num in range(num_pages):
|
|
||||||
page = reader.pages[page_num]
|
|
||||||
text = page.extract_text()
|
|
||||||
if text:
|
|
||||||
# print(f"--------第{page_num}页-----------")
|
|
||||||
cleaned_text = clean_page_content(text,common_header)
|
|
||||||
# print(cleaned_text)
|
|
||||||
result += cleaned_text
|
|
||||||
# print(f"Page {page_num + 1} Content:\n{cleaned_text}")
|
|
||||||
else:
|
|
||||||
print(f"Page {page_num + 1} is empty or text could not be extracted.")
|
|
||||||
return result
|
|
||||||
|
|
||||||
def db_call_with_title(file_path):
|
|
||||||
# 相关参数
|
|
||||||
url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
|
|
||||||
api_key = "ad0c363f-1f23-4b13-aba3-698a4f8c3eb8"
|
|
||||||
model_name = "ep-20241115114052-2clpd" # 豆包Pro 32k模型
|
|
||||||
|
|
||||||
# 取txt内容提问
|
|
||||||
# with open(txt_path, 'r', encoding='utf-8') as f:
|
|
||||||
# full_text = f.read()
|
|
||||||
# print(len(full_text))
|
|
||||||
|
|
||||||
# 取pdf内容提问
|
|
||||||
full_text_json = extract_text_json_by_page(file_path)
|
|
||||||
|
|
||||||
# 大模型提取目录
|
|
||||||
# query = f"""
|
|
||||||
# 任务:根据所提供的投标文件格式文件,将其中商务部分的目录准确提出。
|
|
||||||
# 要求:1.尽可能保证与原文内容一致,不要进行总结归纳。
|
|
||||||
# 2.如果文件中包含目录,其可能是虚假的目录,一切以正文内容为准。
|
|
||||||
# 3.所提供文件可能包含技术标或其他内容,要求仅提取商务标内容。
|
|
||||||
# 4.按所给出的格式输出,不要输出任何其他内容,目录保留正确的层级关系。
|
|
||||||
# 输出格式:{{
|
|
||||||
# "一级目录": {{
|
|
||||||
# "二级目录": {{
|
|
||||||
# "最内层目录": {{}}
|
|
||||||
# }}
|
|
||||||
# }}
|
|
||||||
# }}
|
|
||||||
# 文件内容:{full_text}
|
|
||||||
# """
|
|
||||||
|
|
||||||
# 大模型提取页码
|
|
||||||
query = f"""
|
|
||||||
任务:根据所提供的投标文件json格式文件,将其中商务部分的页码准确提出。
|
|
||||||
要求:1.所提供的json文件键为页码,值为当前页码的文本,充分理解后提取商务部分的内容页码。
|
|
||||||
2.如果文件中包含目录,其可能是虚假的目录,一切以正文内容为准。
|
|
||||||
3.所提供文件可能包含技术标或其他内容,要求仅提取商务标相关的页码。并且在最后将子目录的页码范围整合到"页码范围"中。
|
|
||||||
4.按所给出的格式输出,不要输出任何其他内容,目录保留正确的层级关系。
|
|
||||||
5.如果商务部分穿插如技术标的相关内容,在"商务部分"中的page_range中需要将这段跳过。
|
|
||||||
举例:假如12到15页为技术标部分,其他都是商务标时,按列表包含二元组的样式展示出来,如[(1,11),(16,33)]。
|
|
||||||
如果这种情况没有发生,则输出完整的页码范围,如[(4,20)]
|
|
||||||
输出格式:{{
|
|
||||||
"商务部分": {{
|
|
||||||
"一级目录": {{
|
|
||||||
start_page: 开始页码
|
|
||||||
end_page: 结束页码
|
|
||||||
children: {{
|
|
||||||
"二级目录": {{
|
|
||||||
start_page: 开始页码
|
|
||||||
end_page: 结束页码
|
|
||||||
children: {{
|
|
||||||
"最内层目录": {{
|
|
||||||
start_page: 开始页码
|
|
||||||
end_page: 结束页码
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
}}
|
|
||||||
"页码范围": [(4,33)]
|
|
||||||
}}
|
|
||||||
文件内容:{full_text_json}
|
|
||||||
"""
|
|
||||||
|
|
||||||
headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"Authorization": "Bearer " + api_key
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
"model": model_name,
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "system",
|
|
||||||
"content": "你是一个专业的标书制作人,现在需要你对传入的数据进行充分理解后,回答我的问题。"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": query
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.post(url, headers=headers, json=data)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
print(response.json()["choices"][0]["message"]["content"])
|
|
||||||
else:
|
|
||||||
print(f"请求失败,状态码:{response.status_code},错误信息:{response.text}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
txt_path = "D:/files/bid1/bid_format.txt"
|
|
||||||
pdf_path_1 = "D:/bid_generator/task_folder/9a447eb0-24b8-4f51-8164-d91a62edea25/tmp/bid_format.pdf"
|
|
||||||
pdf_path_2 = "D:/files/page_test/技术标穿插测试文件.pdf"
|
|
||||||
db_call_with_title(pdf_path_2)
|
|
152
flask_app/general/doubao.py
Normal file
152
flask_app/general/doubao.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
import PyPDF2
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
from flask_app.general.clean_pdf import extract_common_header, clean_page_content
|
||||||
|
|
||||||
|
|
||||||
|
def extract_text_by_page(file_path):
|
||||||
|
common_header = extract_common_header(file_path)
|
||||||
|
# print(f"公共抬头:{common_header}")
|
||||||
|
# print("--------------------正文开始-------------------")
|
||||||
|
result = ""
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
reader = PyPDF2.PdfReader(file)
|
||||||
|
num_pages = len(reader.pages)
|
||||||
|
# print(f"Total pages: {num_pages}")
|
||||||
|
for page_num in range(num_pages):
|
||||||
|
page = reader.pages[page_num]
|
||||||
|
text = page.extract_text()
|
||||||
|
if text:
|
||||||
|
# print(f"--------第{page_num}页-----------")
|
||||||
|
cleaned_text = clean_page_content(text,common_header)
|
||||||
|
# print(cleaned_text)
|
||||||
|
result += cleaned_text
|
||||||
|
# print(f"Page {page_num + 1} Content:\n{cleaned_text}")
|
||||||
|
else:
|
||||||
|
print(f"Page {page_num + 1} is empty or text could not be extracted.")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def read_txt_to_string(file_path):
|
||||||
|
"""
|
||||||
|
读取txt文件内容并返回一个包含所有内容的字符串,保持原有格式。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
- file_path (str): txt文件的路径
|
||||||
|
|
||||||
|
返回:
|
||||||
|
- str: 包含文件内容的字符串
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as file: # 确保使用适当的编码
|
||||||
|
content = file.read() # 使用 read() 保持文件格式
|
||||||
|
return content
|
||||||
|
except FileNotFoundError:
|
||||||
|
return "错误:文件未找到。"
|
||||||
|
except Exception as e:
|
||||||
|
return f"错误:读取文件时发生错误。详细信息:{e}"
|
||||||
|
def doubao_model(full_user_query):
|
||||||
|
# 相关参数
|
||||||
|
url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
|
||||||
|
api_key = "ad0c363f-1f23-4b13-aba3-698a4f8c3eb8"
|
||||||
|
model_name = "ep-20241115114052-2clpd" # 豆包Pro 32k模型
|
||||||
|
|
||||||
|
# 大模型提取页码
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": "Bearer " + api_key
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
"model": model_name,
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": full_user_query
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"temperature":0.5
|
||||||
|
}
|
||||||
|
response = requests.post(url, headers=headers, json=data)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
# print(response.json()["choices"][0]["message"]["content"])
|
||||||
|
return response.json()["choices"][0]["message"]["content"]
|
||||||
|
else:
|
||||||
|
print(f"请求失败,状态码:{response.status_code},错误信息:{response.text}")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_full_user_query(file_path, prompt_template):
|
||||||
|
"""
|
||||||
|
根据文件路径和提示词模板生成完整的user_query。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
- file_path (str): 需要解析的文件路径。
|
||||||
|
- prompt_template (str): 包含{full_text}占位符的提示词模板。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
- str: 完整的user_query。
|
||||||
|
"""
|
||||||
|
# 假设extract_text_by_page已经定义,用于提取文件内容
|
||||||
|
full_text = extract_text_by_page(file_path)
|
||||||
|
# full_text=read_txt_to_string(file_path)
|
||||||
|
# 格式化提示词,将提取的文件内容插入到模板中
|
||||||
|
user_query = prompt_template.format(full_text=full_text)
|
||||||
|
|
||||||
|
return user_query
|
||||||
|
|
||||||
|
#7.文件内容为markdown格式, 表格特殊情况处理:对于表格数据,可能存在原始pdf转换markdown时跨页导致同一个货物名称(或系统名称)分隔在上下两个单元格内,你需要通过上下文语义判断是否合并之后才是完整且正确的货物名称(或系统名称)。
|
||||||
|
if __name__ == "__main__":
|
||||||
|
txt_path = r"output.txt"
|
||||||
|
pdf_path_1 = "D:/bid_generator/task_folder/9a447eb0-24b8-4f51-8164-d91a62edea25/tmp/bid_format.pdf"
|
||||||
|
pdf_path_2 = r"output1.txt"
|
||||||
|
prompt_template = '''
|
||||||
|
任务:解析采购文件,提取采购需求,并以JSON格式返回。
|
||||||
|
|
||||||
|
要求与指南:
|
||||||
|
1. 精准定位:运用文档理解能力,找到文件中的采购需求部分。
|
||||||
|
2. 系统归属:若货物明确属于某个系统,则将其作为该系统的二级键。
|
||||||
|
3. 非清单形式处理:若未出现采购清单,则从表格或文字中摘取系统和货物信息。
|
||||||
|
4. 软件需求:对于软件应用需求,列出系统模块构成,并作为系统键值的一部分。
|
||||||
|
5. 系统功能:若文中提及系统功能,则在系统值中添加'系统功能'二级键,不展开具体内容。
|
||||||
|
6. 完整性:确保不遗漏系统内的货物,也不添加未提及的内容。
|
||||||
|
|
||||||
|
输出格式:
|
||||||
|
1.JSON格式,最外层键名为'采购需求'。
|
||||||
|
2.嵌套键名为系统或货物名称,与原文保持一致。
|
||||||
|
3.键值应为空对象({{}}),仅返回名称。
|
||||||
|
4.不包含'说明'、'规格'、'技术参数'等列内容。
|
||||||
|
5.层次关系用嵌套键值对表示。
|
||||||
|
6.最后一级键内值留空或填'未知'(如数量较多或未知内容)。
|
||||||
|
|
||||||
|
特殊情况处理:
|
||||||
|
同一层级下同名但采购要求不同的货物,以'货物名-编号'区分,编号从1递增。
|
||||||
|
|
||||||
|
示例输出结构:
|
||||||
|
{{
|
||||||
|
"采购需求": {{
|
||||||
|
"交换机-1": {{}},
|
||||||
|
"交换机-2": {{}},
|
||||||
|
"门禁管理系统": {{
|
||||||
|
// 可包含其他货物或模块
|
||||||
|
}},
|
||||||
|
"交通监控视频子系统": {{
|
||||||
|
"系统功能": {{}},
|
||||||
|
"高清视频抓拍像机": {{}},
|
||||||
|
"补光灯": {{}}
|
||||||
|
}},
|
||||||
|
"LED全彩显示屏": {{}}
|
||||||
|
// 其他系统和货物
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
文件内容(已包含):{full_text}
|
||||||
|
|
||||||
|
注意事项:
|
||||||
|
1.严格按照上述要求执行,确保输出准确性和规范性。
|
||||||
|
2.如有任何疑问或不确定内容,请保留原文描述,必要时使用'未知'标注。
|
||||||
|
'''
|
||||||
|
user_query=generate_full_user_query(pdf_path_2,prompt_template)
|
||||||
|
res=doubao_model(user_query)
|
||||||
|
print(res)
|
||||||
|
# print("--------------------")
|
||||||
|
# print(user_query)
|
73
flask_app/general/file2markdown.py
Normal file
73
flask_app/general/file2markdown.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
def get_file_content(filePath):
|
||||||
|
with open(filePath, 'rb') as fp:
|
||||||
|
return fp.read()
|
||||||
|
|
||||||
|
class TextinOcr(object):
|
||||||
|
def __init__(self, app_id, app_secret):
|
||||||
|
self._app_id = app_id
|
||||||
|
self._app_secret = app_secret
|
||||||
|
self.host = 'https://api.textin.com'
|
||||||
|
|
||||||
|
def recognize_pdf2md(self, image, options):
|
||||||
|
"""
|
||||||
|
pdf to markdown
|
||||||
|
:param options: request params
|
||||||
|
:param image: file bytes
|
||||||
|
:return: response
|
||||||
|
|
||||||
|
options = {
|
||||||
|
'pdf_pwd': None, #当pdf为加密文档时,需要提供密码。 备注:对前端封装该接口时,需要自行对密码进行安全防护
|
||||||
|
'dpi': 144, # 设置dpi为144
|
||||||
|
'page_start': 0, #当上传的是pdf时,page_start 表示从第几页开始转
|
||||||
|
'page_count': 1000, # 设置解析的页数为1000页
|
||||||
|
'apply_document_tree': 1, #是否生成标题,默认为1,生成标题
|
||||||
|
'markdown_details': 1,
|
||||||
|
'page_details': 0, # 不包含页面细节信息
|
||||||
|
'table_flavor': 'md', #按md语法输出表格
|
||||||
|
'get_image': 'none', #获取markdown里的图片,默认为none,不返回任何图像
|
||||||
|
'parse_mode': 'scan', # PDF解析模式,默认为scan模式,仅按文字识别方式处理。
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
url = self.host + '/ai/service/v1/pdf_to_markdown'
|
||||||
|
headers = {
|
||||||
|
'x-ti-app-id': self._app_id,
|
||||||
|
'x-ti-secret-code': self._app_secret
|
||||||
|
}
|
||||||
|
|
||||||
|
return requests.post(url, data=image, headers=headers, params=options)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 请登录后前往 “工作台-账号设置-开发者信息” 查看 app-id/app-secret
|
||||||
|
textin = TextinOcr('77c60b5b961381ba80f427966cdfe8ee', '31261fde2bb4ffed73f13ace24c495b5')
|
||||||
|
file_path=r'C:\Users\Administrator\Desktop\货物标\output1\磋商文件_procurement.pdf'
|
||||||
|
image = get_file_content(file_path)
|
||||||
|
|
||||||
|
resp = textin.recognize_pdf2md(image, {
|
||||||
|
'page_start': 0,
|
||||||
|
'page_count': 50, # 设置解析页数为50页
|
||||||
|
'table_flavor': 'md', #html 按html语法输出表格
|
||||||
|
'parse_mode': 'scan', # 设置解析模式为scan模式
|
||||||
|
'page_details': 0, # 不包含页面细节
|
||||||
|
'markdown_details': 1,
|
||||||
|
'apply_document_tree': 1,
|
||||||
|
'dpi': 144 # 分辨率设置为144 dpi
|
||||||
|
})
|
||||||
|
print("request time: ", resp.elapsed.total_seconds())
|
||||||
|
data = json.loads(resp.text)
|
||||||
|
if 'result' in data and 'markdown' in data['result']:
|
||||||
|
markdown_content = data['result']['markdown']
|
||||||
|
# 定义输出文件名
|
||||||
|
output_file = 'output1.txt'
|
||||||
|
try:
|
||||||
|
# 将 markdown 内容写入文件,使用 UTF-8 编码
|
||||||
|
with open(output_file, 'w', encoding='utf-8') as file:
|
||||||
|
file.write(markdown_content)
|
||||||
|
print(f"Markdown 内容已成功保存到 '{output_file}'")
|
||||||
|
except IOError as e:
|
||||||
|
print(f"写入文件时出错: {e}")
|
||||||
|
# with open('result.json', 'w', encoding='utf-8') as fw:
|
||||||
|
# json.dump(result, fw, indent=4, ensure_ascii=False)
|
@ -76,7 +76,8 @@ def generate_queries(truncate_file, required_keys):
|
|||||||
return queries
|
return queries
|
||||||
|
|
||||||
|
|
||||||
def get_business_requirements(truncate_file,file_id):
|
def get_business_requirements(procurement_path):
|
||||||
|
file_id=upload_file(procurement_path)
|
||||||
# required_keys = ["技术要求","商务要求", "服务要求", "其他要求"]
|
# required_keys = ["技术要求","商务要求", "服务要求", "其他要求"]
|
||||||
# queries = generate_queries(truncate_file, required_keys)
|
# queries = generate_queries(truncate_file, required_keys)
|
||||||
#一起问了,效率慢点,但内容准
|
#一起问了,效率慢点,但内容准
|
||||||
|
@ -7,7 +7,7 @@ from flask_app.general.多线程提问 import multi_threading
|
|||||||
from flask_app.general.通义千问long import qianwen_long, upload_file
|
from flask_app.general.通义千问long import qianwen_long, upload_file
|
||||||
from flask_app.general.json_utils import clean_json_string, combine_json_results
|
from flask_app.general.json_utils import clean_json_string, combine_json_results
|
||||||
from flask_app.货物标.截取pdf货物标版 import truncate_pdf_main
|
from flask_app.货物标.截取pdf货物标版 import truncate_pdf_main
|
||||||
|
from flask_app.general.doubao import doubao_model,generate_full_user_query
|
||||||
def generate_key_paths(data, parent_key=''):
|
def generate_key_paths(data, parent_key=''):
|
||||||
"""
|
"""
|
||||||
生成嵌套字典中的键路径,并提取最内层的键名。
|
生成嵌套字典中的键路径,并提取最内层的键名。
|
||||||
@ -160,47 +160,130 @@ def postprocess(data):
|
|||||||
# 递归处理顶层数据
|
# 递归处理顶层数据
|
||||||
return {key: convert_dict(val) if isinstance(val, dict) else val for key, val in data.items()}
|
return {key: convert_dict(val) if isinstance(val, dict) else val for key, val in data.items()}
|
||||||
|
|
||||||
def get_technical_requirements(file_id,invalid_path):
|
|
||||||
first_query="该文档中是否说明了采购需求,即需要采购哪些货物?如果有,请回答'是',否则,回答'否'"
|
|
||||||
judge_res=qianwen_long(file_id,first_query)
|
|
||||||
if '否' in judge_res:
|
|
||||||
file_id=upload_file(invalid_path)
|
|
||||||
print("调用invalid_path")
|
|
||||||
user_query1 = """
|
|
||||||
请你首先定位该采购文件中的采购清单或采购需求部分,请告诉我需要采购的货物,如果有采购清单,请直接根据清单上的货物(或系统)名称给出结果,注意不要返回'说明'或'规格'或'技术参数'列中的内容;若没有采购清单,你要从表格中或文中摘取需要采购的系统和货物,采购需求中可能包含层次关系,例如采购的某系统中可能包含几种货物,那么你需要用嵌套键值对表示这种关系,且不要遗漏该系统中包含的货物,你的输出请以json格式返回,最外层键名为'采购需求',嵌套键名为对应的系统名称或货物名称,需与原文保持一致,无需给出采购数量和单位。以下为需要考虑的特殊情况:如果采购清单中同一层级(或同一系统)下存在同名货物且它们的采购要求有所不同,请你以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,例如若采购清单中有两种型号的'交换机',那么你应返回两个键名,'交换机-1'和'交换机-2';如有未知内容,在对应键值处填'未知'。以下为考虑了特殊情况的示例输出:
|
|
||||||
{
|
|
||||||
"采购需求": {
|
|
||||||
"交换机-1":{},
|
|
||||||
"交换机-2":{},
|
|
||||||
"门禁管理系统": {},
|
|
||||||
"交通监控视频子系统": {
|
|
||||||
"高清视频抓拍像机":{},
|
|
||||||
"补光灯":{}
|
|
||||||
},
|
|
||||||
"LED全彩显示屏": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
# user_query1 = """
|
# user_query1 = """
|
||||||
# 请你首先定位该采购文件中的采购清单或采购需求部分,请告诉我该项目需要采购的系统或货物,要求回答全面不要遗漏,最细提取到具体的货物名称,而不是货物的功能需求。如果有采购清单,请直接根据清单上的货物(或系统)名称给出结果,注意不要返回'说明'或'规格'或'技术参数'列中的内容;若没有采购清单,你要从表格中或文中摘取需要采购的系统和货物。请以json格式返回结果,外层键名为采购的系统或货物名称,注意:采购需求中可能包含层次关系,例如采购的某系统中可能包含几种货物,那么你需要用嵌套键值对表示这种关系,此时内层键名为该系统所需的货物名,需与原文保持一致,无需给出采购数量和单位。以下为需要考虑的特殊情况:如果采购清单中同一层级(或同一系统)下存在同名货物且它们的采购要求有所不同,请你以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,例如若采购清单中有两种型号的'交换机',那么你应返回两个键名,'交换机-1'和'交换机-2';如果采购的某系统说明了该系统整体功能,那么在其内层键名中除了有该系统包含的货物,还应包含'系统功能',具体键名同原文中的描述;如有未知内容,在对应键值处填'未知'。以下为考虑了特殊情况的示例输出:
|
# 请你首先定位该采购文件中的采购清单或采购需求部分,请告诉我需要采购的货物,如果有采购清单,请直接根据清单上的货物(或系统)名称给出结果,注意不要返回'说明'或'规格'或'技术参数'列中的内容;若没有采购清单,你要从表格中或文中摘取需要采购的系统和货物,采购需求中可能包含层次关系,例如采购的某系统中可能包含几种货物,那么你需要用嵌套键值对表示这种关系,且不要遗漏该系统中包含的货物,你的输出请以json格式返回,最外层键名为'采购需求',嵌套键名为对应的系统名称或货物名称,需与原文保持一致,无需给出采购数量和单位。以下为需要考虑的特殊情况:如果采购清单中同一层级(或同一系统)下存在同名货物且它们的采购要求有所不同,请你以'货物名-编号'区分多种型号,编号为从 1 开始的自然数,依次递增,例如若采购清单中有两种型号的'交换机',那么你应返回两个键名,'交换机-1'和'交换机-2';如有未知内容,在对应键值处填'未知'。以下为考虑了特殊情况的示例输出:
|
||||||
# {
|
# {
|
||||||
|
# "采购需求": {
|
||||||
# "交换机-1":{},
|
# "交换机-1":{},
|
||||||
# "交换机-2":{},
|
# "交换机-2":{},
|
||||||
# "门禁管理系统": {},
|
# "门禁管理系统": {},
|
||||||
# "交通监控视频子系统": {
|
# "交通监控视频子系统": {
|
||||||
# "系统功能":{}
|
|
||||||
# "高清视频抓拍像机":{},
|
# "高清视频抓拍像机":{},
|
||||||
# "补光灯":{}
|
# "补光灯":{}
|
||||||
# },
|
# },
|
||||||
# "LED全彩显示屏": {}
|
# "LED全彩显示屏": {}
|
||||||
# }
|
# }
|
||||||
# """
|
# }
|
||||||
res = qianwen_long(file_id, user_query1)
|
# """
|
||||||
print(res)
|
|
||||||
cleaned_res = clean_json_string(res) #转字典
|
def get_technical_requirements(file_path,invalid_path):
|
||||||
|
file_id=upload_file(file_path)
|
||||||
|
first_query_template="该文件是否说明了采购需求,即需要采购哪些货物?如果有,请回答'是',否则,回答'否'"
|
||||||
|
# first_query=generate_full_user_query(file_path,first_query_template)
|
||||||
|
# judge_res=doubao_model(first_query)
|
||||||
|
judge_res=qianwen_long(file_id,first_query_template)
|
||||||
|
prompt_template1 = '''
|
||||||
|
任务:解析采购文件,提取采购需求,并以JSON格式返回。
|
||||||
|
|
||||||
|
要求与指南:
|
||||||
|
1. 精准定位:运用文档理解能力,找到文件中的采购需求部分。
|
||||||
|
2. 系统归属:若货物明确属于某个系统,则将其作为该系统的二级键。
|
||||||
|
3. 非清单形式处理:若未出现采购清单,则从表格或文字中摘取系统和货物信息。
|
||||||
|
4. 软件需求:对于软件应用需求,列出系统模块构成,并作为系统键值的一部分。
|
||||||
|
5. 系统功能:若文中提及系统功能,则在系统值中添加'系统功能'二级键,不展开具体内容。
|
||||||
|
6. 完整性:确保不遗漏系统内的货物,也不添加未提及的内容。
|
||||||
|
|
||||||
|
输出格式:
|
||||||
|
1.JSON格式,最外层键名为'采购需求'。
|
||||||
|
2.嵌套键名为系统或货物名称,与原文保持一致。
|
||||||
|
3.键值应为空对象({{}}),仅返回名称。
|
||||||
|
4.不包含'说明'、'规格'、'技术参数'等列内容。
|
||||||
|
5.层次关系用嵌套键值对表示。
|
||||||
|
6.最后一级键内值留空或填'未知'(如数量较多或未知内容)。
|
||||||
|
|
||||||
|
特殊情况处理:
|
||||||
|
同一层级下同名但采购要求不同的货物,以'货物名-编号'区分,编号从1递增。
|
||||||
|
|
||||||
|
示例输出结构:
|
||||||
|
{{
|
||||||
|
"采购需求": {{
|
||||||
|
"交换机-1": {{}},
|
||||||
|
"交换机-2": {{}},
|
||||||
|
"门禁管理系统": {{
|
||||||
|
// 可包含其他货物或模块
|
||||||
|
}},
|
||||||
|
"交通监控视频子系统": {{
|
||||||
|
"系统功能": {{}},
|
||||||
|
"高清视频抓拍像机": {{}},
|
||||||
|
"补光灯": {{}}
|
||||||
|
}},
|
||||||
|
"LED全彩显示屏": {{}}
|
||||||
|
// 其他系统和货物
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
注意事项:
|
||||||
|
1.严格按照上述要求执行,确保输出准确性和规范性。
|
||||||
|
2.如有任何疑问或不确定内容,请保留原文描述,必要时使用'未知'标注。
|
||||||
|
'''
|
||||||
|
prompt_template2 = '''
|
||||||
|
任务:解析采购文件,提取采购需求,并以JSON格式返回。
|
||||||
|
|
||||||
|
要求与指南:
|
||||||
|
1. 精准定位:运用文档理解能力,找到文件中的采购需求部分。
|
||||||
|
2. 系统归属:若货物明确属于某个系统,则将其作为该系统的二级键。
|
||||||
|
3. 非清单形式处理:若未出现采购清单,则从表格或文字中摘取系统和货物信息。
|
||||||
|
4. 软件需求:对于软件应用需求,列出系统模块构成,并作为系统键值的一部分。
|
||||||
|
5. 系统功能:若文中提及系统功能,则在系统值中添加'系统功能'二级键,不展开具体内容。
|
||||||
|
6. 完整性:确保不遗漏系统内的货物,也不添加未提及的内容。
|
||||||
|
|
||||||
|
输出格式:
|
||||||
|
1.JSON格式,最外层键名为'采购需求'。
|
||||||
|
2.嵌套键名为系统或货物名称,与原文保持一致。
|
||||||
|
3.键值应为空对象({{}}),仅返回名称。
|
||||||
|
4.不包含'说明'、'规格'、'技术参数'等列内容。
|
||||||
|
5.层次关系用嵌套键值对表示。
|
||||||
|
6.最后一级键内值留空或填'未知'(如数量较多或未知内容)。
|
||||||
|
|
||||||
|
特殊情况处理:
|
||||||
|
同一层级下同名但采购要求不同的货物,以'货物名-编号'区分,编号从1递增。
|
||||||
|
|
||||||
|
示例输出结构:
|
||||||
|
{{
|
||||||
|
"采购需求": {{
|
||||||
|
"交换机-1": {{}},
|
||||||
|
"交换机-2": {{}},
|
||||||
|
"门禁管理系统": {{
|
||||||
|
// 可包含其他货物或模块
|
||||||
|
}},
|
||||||
|
"交通监控视频子系统": {{
|
||||||
|
"系统功能": {{}},
|
||||||
|
"高清视频抓拍像机": {{}},
|
||||||
|
"补光灯": {{}}
|
||||||
|
}},
|
||||||
|
"LED全彩显示屏": {{}}
|
||||||
|
// 其他系统和货物
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
文件内容(已包含):{full_text}
|
||||||
|
|
||||||
|
注意事项:
|
||||||
|
1.严格按照上述要求执行,确保输出准确性和规范性。
|
||||||
|
2.如有任何疑问或不确定内容,请保留原文描述,必要时使用'未知'标注。
|
||||||
|
'''
|
||||||
|
if '否' in judge_res:
|
||||||
|
file_id=upload_file(invalid_path)
|
||||||
|
print("调用invalid_path")
|
||||||
|
model_res=qianwen_long(file_id,prompt_template1)
|
||||||
|
else:
|
||||||
|
user_query=generate_full_user_query(file_path,prompt_template2)
|
||||||
|
model_res=doubao_model(user_query)
|
||||||
|
print(model_res)
|
||||||
|
# res = qianwen_long(file_id, user_query1)
|
||||||
|
|
||||||
|
cleaned_res = clean_json_string(model_res) #转字典
|
||||||
keys_list,good_list,grouped_paths,no_keys_added= generate_key_paths(cleaned_res['采购需求']) # 提取需要采购的货物清单 key_list:交通监控视频子系统.高清视频抓拍像机 ...
|
keys_list,good_list,grouped_paths,no_keys_added= generate_key_paths(cleaned_res['采购需求']) # 提取需要采购的货物清单 key_list:交通监控视频子系统.高清视频抓拍像机 ...
|
||||||
# if '采购需求' in cleaned_res:
|
|
||||||
# cleaned_res['技术要求'] = cleaned_res.pop('采购需求')
|
|
||||||
if no_keys_added:
|
if no_keys_added:
|
||||||
final_res = postprocess(cleaned_res)
|
final_res = postprocess(cleaned_res)
|
||||||
else:
|
else:
|
||||||
@ -286,14 +369,14 @@ def test_all_files_in_folder(input_folder, output_folder):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# truncate_file="C:\\Users\\Administrator\\Desktop\\fsdownload\\469d2aee-9024-4993-896e-2ac7322d41b7\\ztbfile_procurement.docx"
|
# truncate_file="C:\\Users\\Administrator\\Desktop\\fsdownload\\469d2aee-9024-4993-896e-2ac7322d41b7\\ztbfile_procurement.docx"
|
||||||
truncate_file=r"C:\Users\Administrator\Desktop\货物标\output1\招标文件(107国道)_procurement.docx"
|
truncate_file=r"C:\Users\Administrator\Desktop\货物标\output1\招标文件(107国道)_procurement.pdf"
|
||||||
# invalid_path="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile.pdf"
|
# invalid_path="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile.pdf"
|
||||||
# truncate_file="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile_procurement.docx"
|
# truncate_file="D:\\flask_project\\flask_app\\static\\output\\output1\\e7dda5cb-10ba-47a8-b989-d2993d34bb89\\ztbfile_procurement.docx"
|
||||||
# output_folder="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\tmp"
|
# output_folder="C:\\Users\\Administrator\\Desktop\\货物标\\output1\\tmp"
|
||||||
# file_id = upload_file(truncate_file)
|
# file_id = upload_file(truncate_file)
|
||||||
invalid_path="C:\\Users\\Administrator\\Desktop\\fsdownload\\a110ed59-00e8-47ec-873a-bd4579a6e628\\ztbfile.pdf"
|
invalid_path="C:\\Users\\Administrator\\Desktop\\fsdownload\\a110ed59-00e8-47ec-873a-bd4579a6e628\\ztbfile.pdf"
|
||||||
file_id=upload_file(truncate_file)
|
# file_id=upload_file(truncate_file)
|
||||||
res=get_technical_requirements(file_id,invalid_path)
|
res=get_technical_requirements(truncate_file,invalid_path)
|
||||||
json_string = json.dumps(res, ensure_ascii=False, indent=4)
|
json_string = json.dumps(res, ensure_ascii=False, indent=4)
|
||||||
print(json_string)
|
print(json_string)
|
||||||
# # input_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1"
|
# # input_folder = "C:\\Users\\Administrator\\Desktop\\货物标\\output1"
|
||||||
|
@ -23,14 +23,14 @@ def fetch_procurement_reqs(procurement_path, procurement_docpath, invalid_path):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# 上传文件并获取 file_id
|
# 上传文件并获取 file_id
|
||||||
file_id = upload_file(procurement_docpath)
|
# file_id = upload_file(procurement_docpath)
|
||||||
|
|
||||||
# 使用 ThreadPoolExecutor 并行处理 get_technical_requirements 和 get_business_requirements
|
# 使用 ThreadPoolExecutor 并行处理 get_technical_requirements 和 get_business_requirements
|
||||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||||
# 提交任务给线程池
|
# 提交任务给线程池
|
||||||
future_technical = executor.submit(get_technical_requirements, file_id, invalid_path)
|
future_technical = executor.submit(get_technical_requirements, procurement_path, invalid_path)
|
||||||
time.sleep(0.5) # 保持原有的延时
|
time.sleep(0.5) # 保持原有的延时
|
||||||
future_business = executor.submit(get_business_requirements, procurement_path, file_id)
|
future_business = executor.submit(get_business_requirements, procurement_path)
|
||||||
|
|
||||||
# 获取并行任务的结果
|
# 获取并行任务的结果
|
||||||
technical_requirements = future_technical.result()
|
technical_requirements = future_technical.result()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user