12.20 豆包大模型bug解决
This commit is contained in:
parent
5dcbaa5eb5
commit
de254d3c29
@ -205,9 +205,56 @@ def count_tokens(text):
|
||||
tokens = re.findall(token_pattern, text)
|
||||
return len(tokens)# 返回 tokens 数量和匹配的 token 列表
|
||||
|
||||
|
||||
import requests
|
||||
import os
|
||||
|
||||
|
||||
def get_total_tokens(text):
|
||||
"""
|
||||
调用 API 计算给定文本的总 Token 数量。
|
||||
|
||||
参数:
|
||||
- text (str): 需要计算 Token 的文本。
|
||||
- model (str): 使用的模型名称,默认值为 "ep-20241119121710-425g6"。
|
||||
|
||||
返回:
|
||||
- int: 文本的 total_tokens 数量。
|
||||
"""
|
||||
# API 请求 URL
|
||||
url = "https://ark.cn-beijing.volces.com/api/v3/tokenization"
|
||||
|
||||
# 获取 API 密钥
|
||||
doubao_api_key = os.getenv("DOUBAO_API_KEY")
|
||||
if not doubao_api_key:
|
||||
raise ValueError("DOUBAO_API_KEY 环境变量未设置")
|
||||
|
||||
# 请求头
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + doubao_api_key
|
||||
}
|
||||
model = "ep-20241119121710-425g6"
|
||||
# 请求体
|
||||
payload = {
|
||||
"model": model,
|
||||
"text": [text] # API 文档中要求 text 是一个列表
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
response.raise_for_status()
|
||||
response_data = response.json()
|
||||
total_tokens=response_data["data"][0]["total_tokens"]
|
||||
return total_tokens
|
||||
except Exception as e:
|
||||
print(f"获取 Token 数量失败:{e}")
|
||||
return 0
|
||||
|
||||
|
||||
@sleep_and_retry
|
||||
@limits(calls=10, period=1) # 每秒最多调用10次
|
||||
def doubao_model(full_user_query):
|
||||
def doubao_model(full_user_query, need_extra=False):
|
||||
print("call doubao...")
|
||||
# 相关参数
|
||||
url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
|
||||
@ -220,8 +267,8 @@ def doubao_model(full_user_query):
|
||||
}
|
||||
|
||||
# 判断用户查询字符串的长度
|
||||
token_count = count_tokens(full_user_query)
|
||||
if token_count > 35000:
|
||||
token_count = get_total_tokens(full_user_query)
|
||||
if token_count > 31500:
|
||||
selected_model = models["pro_128k"] # 如果长度超过32k,直接使用128k模型
|
||||
else:
|
||||
selected_model = models["pro_32k"] # 默认使用32k模型
|
||||
@ -252,13 +299,28 @@ def doubao_model(full_user_query):
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=data) # 设置超时时间为10秒
|
||||
response.raise_for_status() # 如果响应状态码不是200,将引发HTTPError
|
||||
# 返回模型的回复内容
|
||||
return response.json()["choices"][0]["message"]["content"]
|
||||
|
||||
# 获取响应 JSON
|
||||
response_json = response.json()
|
||||
|
||||
# 获取返回内容
|
||||
content = response_json["choices"][0]["message"]["content"]
|
||||
|
||||
# 获取 completion_tokens
|
||||
completion_tokens = response_json["usage"].get("completion_tokens", 0)
|
||||
|
||||
# 根据 need_extra 返回不同的结果
|
||||
if need_extra:
|
||||
return content, completion_tokens
|
||||
else:
|
||||
return content
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
# 获取状态码并处理不同的重试逻辑
|
||||
status_code = response.status_code if response is not None else None
|
||||
print(f"请求失败,状态码: {status_code}")
|
||||
print("请求失败,完整的响应内容如下:")
|
||||
if response is not None:
|
||||
print(response.text) # 打印原始的响应内容,可能是 JSON 格式,也可能是其他格式
|
||||
|
||||
# 如果是 429 错误
|
||||
@ -283,8 +345,12 @@ def doubao_model(full_user_query):
|
||||
|
||||
# 如果到这里,说明所有尝试都失败了
|
||||
print(f"请求失败,已达到最大重试次数。")
|
||||
if need_extra:
|
||||
return None, 0
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def generate_full_user_query(file_path, prompt_template):
|
||||
"""
|
||||
根据文件路径和提示词模板生成完整的user_query。
|
||||
@ -357,8 +423,9 @@ if __name__ == "__main__":
|
||||
# processed_filepath = convert_pdf_to_markdown(pdf_path_2) # 转markdown格式
|
||||
# processed_filepath = pdf2txt(pdf_path_2) #纯文本提取
|
||||
# user_query=generate_full_user_query(processed_filepath,prompt_template)
|
||||
user_query="一年有多少天?"
|
||||
res=doubao_model(user_query)
|
||||
# user_query="一年有多少天?"
|
||||
# res=doubao_model(user_query)
|
||||
res=get_total_tokens("hh我是天才")
|
||||
print(res)
|
||||
# print("--------------------")
|
||||
# print(user_query)
|
@ -101,7 +101,7 @@ def replace_latex_expressions(json_str):
|
||||
return fixed_str
|
||||
|
||||
|
||||
def extract_content_from_json(string, length_threshold=5000):
|
||||
def extract_content_from_json(string):
|
||||
"""
|
||||
输入字符串,尝试解析 JSON 数据:
|
||||
1. 如果成功解析,返回字典。
|
||||
@ -115,8 +115,6 @@ def extract_content_from_json(string, length_threshold=5000):
|
||||
match = re.search(r'\{[\s\S]*\}', string)
|
||||
if not match:
|
||||
print("未找到有效的 JSON 内容。")
|
||||
if len(string) > length_threshold:
|
||||
return string # 返回原始字符串
|
||||
return {} # 返回空字典
|
||||
|
||||
original_json = match.group(0)
|
||||
@ -157,15 +155,9 @@ def extract_content_from_json(string, length_threshold=5000):
|
||||
|
||||
# 如果所有方法都失败,检查字符串长度
|
||||
print("所有修复方法均失败。")
|
||||
if len(string) > length_threshold:
|
||||
print("字符串长度超过阈值,返回原始字符串。")
|
||||
return string # 返回原始字符串
|
||||
else:
|
||||
print("字符串长度不超过阈值,返回空字典。")
|
||||
return {} # 返回空字典
|
||||
|
||||
def clean_json_string(json_string):
|
||||
# print(json_string)
|
||||
"""清理JSON字符串,移除多余的反引号并解析为字典"""
|
||||
return extract_content_from_json(json_string)
|
||||
|
||||
|
@ -82,11 +82,6 @@ def continue_answer(original_query, original_answer, model_type=1, file_id=None)
|
||||
# 尝试解析为 JSON
|
||||
try:
|
||||
json_data = clean_json_string(full_answer)
|
||||
if not isinstance(json_data, dict):
|
||||
print(f"警告: clean_json_string 返回的类型为 {type(json_data)},预期为 dict。")
|
||||
print(json_data)
|
||||
return {}
|
||||
print("JSON 拼接成功且有效!")
|
||||
return json_data
|
||||
except json.JSONDecodeError as e:
|
||||
print("JSON 拼接失败,错误信息如下:")
|
||||
@ -101,7 +96,7 @@ def process_continue_answers(questions_to_continue, model_type, file_id):
|
||||
- questions_to_continue (list of tuples): 需要继续回答的问题,每个元素是 (original_query, parsed_answer)。
|
||||
- model_type (int): 指定使用的模型类型。
|
||||
- file_id (str): 可选的文件 ID,默认为 None。
|
||||
|
||||
- model_type
|
||||
返回:
|
||||
- dict: 继续回答后的结果合并。
|
||||
"""
|
||||
|
@ -3,6 +3,8 @@ import re
|
||||
import time
|
||||
from collections import defaultdict
|
||||
|
||||
from flask_app.general.doubao import get_total_tokens
|
||||
from flask_app.general.model_continue_query import process_continue_answers
|
||||
from flask_app.general.通义千问long import upload_file, qianwen_long
|
||||
|
||||
|
||||
@ -136,7 +138,7 @@ def parse_json_with_duplicates(raw_string):
|
||||
return []
|
||||
|
||||
"""输入字符串,提取 { 和 } 之间的内容,并将其解析为字典"""
|
||||
if not raw_string.strip():
|
||||
if not raw_string or not raw_string.strip():
|
||||
return {}
|
||||
match = re.search(r'\{[\s\S]*\}', raw_string)
|
||||
if match:
|
||||
@ -147,8 +149,8 @@ def parse_json_with_duplicates(raw_string):
|
||||
print(f"json_utils: extract_content_from_json: JSON decode error: {e}")
|
||||
return {}
|
||||
else:
|
||||
print("json_utils: extract_content_from_json: No valid JSON content found.")
|
||||
return {}
|
||||
print("未找到有效的 JSON 内容。")
|
||||
return {} # 返回空字典
|
||||
|
||||
# 防止外键只有一个'一包'的情况
|
||||
def process_data_based_on_key(data):
|
||||
@ -375,11 +377,23 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
)
|
||||
# 执行第二个查询
|
||||
user_query = user_query_1 if zb_type == 1 else user_query_2
|
||||
evaluation_res = qianwen_long(file_id, user_query) # 有些重复的键名,只有qianwen_long_text能保留
|
||||
questions_to_continue = []
|
||||
temp_final={}
|
||||
evaluation_res = qianwen_long(file_id, user_query,2,1,True) # 有些重复的键名,只有qianwen_long_text能保留
|
||||
message = evaluation_res[0]
|
||||
total_tokens = evaluation_res[1]
|
||||
# print(evaluation_res)
|
||||
# 清理和处理响应
|
||||
cleaned_evaluation_res = parse_json_with_duplicates(evaluation_res) # 处理重复键名的情况
|
||||
result_data = process_data_based_on_key(cleaned_evaluation_res) # 处理不知名外键的情况
|
||||
cleaned_evaluation_res = parse_json_with_duplicates(message) # 处理重复键名的情况
|
||||
# print(json.dumps(cleaned_evaluation_res,ensure_ascii=False,indent=4))
|
||||
if not cleaned_evaluation_res and total_tokens > 5900:
|
||||
questions_to_continue.append((user_query, evaluation_res))
|
||||
else:
|
||||
temp_final.update(cleaned_evaluation_res)
|
||||
if questions_to_continue:
|
||||
continued_results = process_continue_answers(questions_to_continue, 0, file_id)
|
||||
temp_final.update(continued_results)
|
||||
result_data = process_data_based_on_key(temp_final) # 处理不知名外键的情况
|
||||
include = ['一包', '二包', '三包', '四包', '五包']
|
||||
target_values = ['技术', '设计', '实施']
|
||||
updated_jsons = {}
|
||||
@ -423,8 +437,8 @@ def combine_evaluation_standards(evaluation_method_path,invalid_path,zb_type):
|
||||
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\fsdownload\aba81749-5986-4492-8b4b-16db9c69a09d\ztbfile_evaluation_method.pdf'
|
||||
invalid_path=r'C:\Users\Administrator\Desktop\fsdownload\91399aa4-1ee8-447d-a05b-03cd8d15ced5\ztbfile_invalid.pdf'
|
||||
evaluation_method_path = r'C:\Users\Administrator\Desktop\文件解析问题\文件解析问题\be901ea0-adc9-47b8-9ada-5c3bc0dd9434\ztbfile_evaluation_method.pdf'
|
||||
invalid_path=r'C:\Users\Administrator\Desktop\文件解析问题\文件解析问题\be901ea0-adc9-47b8-9ada-5c3bc0dd9434\ztbfile.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"
|
||||
|
@ -237,7 +237,7 @@ def pure_assistant():
|
||||
)
|
||||
return assistant
|
||||
|
||||
def llm_call(question, knowledge_name,file_id, result_queue, ans_index, llm_type):
|
||||
def llm_call(question, knowledge_name,file_id, result_queue, ans_index, llm_type,need_extra=False):
|
||||
"""
|
||||
调用不同的 LLM 模型并将结果放入结果队列。
|
||||
"""
|
||||
@ -251,14 +251,14 @@ def llm_call(question, knowledge_name,file_id, result_queue, ans_index, llm_type
|
||||
elif llm_type==2:
|
||||
print(f"qianwen_long! question:{question}")
|
||||
# qianwen_res,usage = qianwen_long(file_id,question) #有bug
|
||||
qianwen_res = qianwen_long(file_id, question)
|
||||
qianwen_res = qianwen_long(file_id, question,2,1,need_extra)
|
||||
if not qianwen_res:
|
||||
result_queue.put((ans_index, None)) # 如果为空字符串,直接返回 None
|
||||
else:
|
||||
result_queue.put((ans_index, (question, qianwen_res)))
|
||||
elif llm_type==3:
|
||||
# print(f"doubao! question:{question}")
|
||||
doubao_res=doubao_model(question)
|
||||
doubao_res=doubao_model(question,need_extra)
|
||||
if not doubao_res:
|
||||
result_queue.put((ans_index, None)) # 如果为空字符串,直接返回 None
|
||||
else:
|
||||
@ -271,14 +271,14 @@ def llm_call(question, knowledge_name,file_id, result_queue, ans_index, llm_type
|
||||
print(f"LLM 调用失败,查询索引 {ans_index},错误:{e}")
|
||||
result_queue.put((ans_index, None)) # 使用 None 作为失败的占位符
|
||||
|
||||
def multi_threading(queries, knowledge_name="", file_id="", llm_type=1):
|
||||
def multi_threading(queries, knowledge_name="", file_id="", llm_type=1,need_extra=False):
|
||||
if not queries:
|
||||
return []
|
||||
print("多线程提问:starting multi_threading...")
|
||||
result_queue = queue.Queue()
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=60) as executor:
|
||||
future_to_index = {
|
||||
executor.submit(llm_call, query, knowledge_name, file_id, result_queue, index, llm_type): index
|
||||
executor.submit(llm_call, query, knowledge_name, file_id, result_queue, index, llm_type,need_extra): index
|
||||
for index, query in enumerate(queries)
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import re
|
||||
from functools import cmp_to_key
|
||||
|
||||
from flask_app.general.json_utils import clean_json_string
|
||||
from flask_app.general.model_continue_query import process_continue_answers
|
||||
from flask_app.general.通义千问long import upload_file, qianwen_long_stream
|
||||
|
||||
|
||||
@ -459,9 +460,18 @@ def get_requirements_with_gpt(merged_baseinfo_path, selection):
|
||||
return {"error": f"无效的 selection 值: {selection}. 请选择 1、2 或 3。"}
|
||||
# 调用大模型并处理响应
|
||||
try:
|
||||
res = qianwen_long_stream(file_id, user_query,2)
|
||||
cleaned_res = clean_json_string(res)
|
||||
return cleaned_res
|
||||
questions_to_continue = []
|
||||
qianwen_res = qianwen_long_stream(file_id, user_query,2,1,True)
|
||||
message = qianwen_res[0]
|
||||
parsed = clean_json_string(message)
|
||||
total_tokens = qianwen_res[1]
|
||||
if not parsed and total_tokens >5900:
|
||||
questions_to_continue.append((user_query, message))
|
||||
if questions_to_continue:
|
||||
continued_results = process_continue_answers(questions_to_continue, 0, file_id)
|
||||
return continued_results
|
||||
else:
|
||||
return parsed
|
||||
except Exception as e:
|
||||
return {"error": "调用大模型失败"}
|
||||
|
||||
|
@ -79,9 +79,8 @@ def extract_error_details(error_message):
|
||||
|
||||
return error_code, error_code_string
|
||||
@shared_rate_limit
|
||||
def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0):
|
||||
def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0, need_extra=False):
|
||||
logger = logging.getLogger('model_log') # 通过日志名字获取记录器
|
||||
# logger.info(f"Received query: {user_query}")
|
||||
"""
|
||||
基于上传的文件 ID 和用户查询生成响应,并在失败时自动重试。
|
||||
参数:
|
||||
@ -89,14 +88,12 @@ def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0):
|
||||
- user_query: 用户查询
|
||||
- max_retries: 最大重试次数(默认 2 次)
|
||||
- backoff_factor: 指数退避的基础等待时间(默认 1.0 秒)
|
||||
- need_extra: 是否需要返回额外数据(默认 False)
|
||||
"""
|
||||
# print("call qianwen_long...")
|
||||
|
||||
client = OpenAI(
|
||||
api_key=os.getenv("DASHSCOPE_API_KEY"),
|
||||
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||
)
|
||||
|
||||
for attempt in range(1, max_retries + 2): # +1 是为了包括初始调用
|
||||
try:
|
||||
# 调用 API
|
||||
@ -115,7 +112,11 @@ def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0):
|
||||
],
|
||||
stream=False
|
||||
)
|
||||
token_usage = completion.usage.completion_tokens
|
||||
# 如果调用成功,返回响应内容
|
||||
if need_extra:
|
||||
return completion.choices[0].message.content, token_usage
|
||||
else:
|
||||
return completion.choices[0].message.content
|
||||
|
||||
except Exception as exc:
|
||||
@ -123,7 +124,7 @@ def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0):
|
||||
error_code, error_code_string = extract_error_details(str(exc))
|
||||
logger.error(f"第 {attempt} 次尝试失败,查询:'{user_query}',错误:{exc}", exc_info=True)
|
||||
|
||||
if error_code == 429: #超qps/qpm
|
||||
if error_code == 429: # 超 qps/qpm
|
||||
if attempt <= max_retries:
|
||||
sleep_time = backoff_factor * (2 ** (attempt - 1)) # 指数退避
|
||||
logger.warning(f"错误代码为 429,将在 {sleep_time} 秒后重试...")
|
||||
@ -131,11 +132,22 @@ def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0):
|
||||
else:
|
||||
print(f"查询 '{user_query}' 的所有 {max_retries + 1} 次尝试均失败(429 错误)。")
|
||||
break
|
||||
elif error_code == 400 and error_code_string in ['data_inspection_failed', 'ResponseTimeout','DataInspectionFailed','response_timeout','request_timeout',"RequestTimeOut"]:
|
||||
elif error_code == 400 and error_code_string in [
|
||||
'data_inspection_failed', 'ResponseTimeout', 'DataInspectionFailed',
|
||||
'response_timeout', 'request_timeout', "RequestTimeOut"
|
||||
]:
|
||||
logger.warning(f"错误代码为 400 - {error_code_string},将调用 qianwen_long_stream 执行一次...")
|
||||
try:
|
||||
# 超时就调用 qianwen_long_stream
|
||||
return qianwen_long_stream(file_id, user_query, max_retries=0) # 禁用内部重试
|
||||
stream_result = qianwen_long_stream(file_id, user_query, max_retries=0) # 禁用内部重试
|
||||
if need_extra:
|
||||
if isinstance(stream_result, tuple) and len(stream_result) == 2:
|
||||
return stream_result[0], stream_result[1] # 返回内容和默认的 token_usage=0
|
||||
else:
|
||||
logger.error(f"qianwen_long_stream 返回值不符合预期(需要元组)。返回值: {stream_result}")
|
||||
return "", 0 # 处理异常返回
|
||||
else:
|
||||
return stream_result # need_extra=False,直接返回内容
|
||||
except Exception as stream_exc:
|
||||
logger.error(f"调用 qianwen_long_stream 时出错:{stream_exc}", exc_info=True)
|
||||
break # 跳出循环,不再重试
|
||||
@ -144,12 +156,15 @@ def qianwen_long(file_id, user_query, max_retries=2, backoff_factor=1.0):
|
||||
logger.error(f"遇到非 429 或非 'data_inspection_failed' 的 400 错误(错误代码:{error_code}),不进行重试。")
|
||||
break
|
||||
|
||||
# 在所有重试失败的情况下返回
|
||||
if need_extra:
|
||||
return "", 0 # 返回默认值和 token_usage = 0
|
||||
else:
|
||||
return ""
|
||||
|
||||
@shared_rate_limit
|
||||
def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1.0):
|
||||
def qianwen_long_stream(file_id, user_query, max_retries=2, backoff_factor=1.0, need_extra=False):
|
||||
logger = logging.getLogger('model_log') # 通过日志名字获取记录器
|
||||
# logger.info(f"Received query: {user_query}")
|
||||
"""
|
||||
使用之前上传的文件,根据用户查询生成响应,并实时显示流式输出。
|
||||
参数:
|
||||
@ -157,8 +172,10 @@ def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1
|
||||
- user_query: 用户查询
|
||||
- max_retries: 最大重试次数(默认 2 次)
|
||||
- backoff_factor: 指数退避的基础等待时间(默认 1.0 秒)
|
||||
- need_extra: 是否需要返回额外数据(默认 False)
|
||||
返回:
|
||||
- Optional[str]: 成功时返回响应内容,失败时返回空字符串
|
||||
- 当 need_extra=False 时: 返回响应内容 (str)
|
||||
- 当 need_extra=True 时: 返回 (响应内容, token_usage)
|
||||
"""
|
||||
print("调用 qianwen-long stream...")
|
||||
|
||||
@ -166,14 +183,13 @@ def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1
|
||||
api_key=os.getenv("DASHSCOPE_API_KEY"),
|
||||
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||
)
|
||||
|
||||
for attempt in range(1, max_retries + 2): # +1 是为了包括初始调用
|
||||
try:
|
||||
completion_tokens = 0 # 初始化 completion_tokens 为 0
|
||||
# 生成基于文件ID的响应
|
||||
completion = client.chat.completions.create(
|
||||
model="qwen-long",
|
||||
temperature=0.4,
|
||||
max_tokens=5000,
|
||||
messages=[
|
||||
{
|
||||
'role': 'system',
|
||||
@ -184,16 +200,21 @@ def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1
|
||||
'content': user_query
|
||||
}
|
||||
],
|
||||
stream=True # 启用流式响应
|
||||
stream=True, # 启用流式响应
|
||||
stream_options={"include_usage": True}
|
||||
)
|
||||
|
||||
full_response = "" # 用于存储完整的响应内容
|
||||
|
||||
for chunk in completion:
|
||||
print(chunk)
|
||||
if hasattr(chunk, 'to_dict'):
|
||||
chunk_data = chunk.to_dict()
|
||||
else:
|
||||
chunk_data = json.loads(chunk.model_dump_json())
|
||||
usage = chunk_data.get('usage')
|
||||
if usage is not None:
|
||||
completion_tokens = usage.get('completion_tokens', 0)
|
||||
choices = chunk_data.get('choices', [])
|
||||
if not choices:
|
||||
continue
|
||||
@ -202,11 +223,15 @@ def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1
|
||||
content = delta.get('content', '')
|
||||
if content:
|
||||
full_response += content
|
||||
# print(content, end='', flush=True) # 实时打印内容
|
||||
# 实时打印内容(可以取消注释下面一行以实时输出)
|
||||
# print(content, end='', flush=True)
|
||||
if choice.get('finish_reason'):
|
||||
break
|
||||
|
||||
return full_response # 返回完整的响应内容
|
||||
if need_extra:
|
||||
return full_response, completion_tokens
|
||||
else:
|
||||
return full_response
|
||||
|
||||
except Exception as exc:
|
||||
# 提取错误代码
|
||||
@ -221,8 +246,10 @@ def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1
|
||||
else:
|
||||
logger.error(f"查询 '{user_query}' 的所有 {max_retries + 1} 次尝试均失败(429 错误)。")
|
||||
break
|
||||
elif error_code == 400 and error_code_string in ['data_inspection_failed', 'ResponseTimeout',
|
||||
'DataInspectionFailed', 'response_timeout','RequestTimeOut','request_timeout']:
|
||||
elif error_code == 400 and error_code_string in [
|
||||
'data_inspection_failed', 'ResponseTimeout', 'DataInspectionFailed',
|
||||
'response_timeout', 'request_timeout', "RequestTimeOut"
|
||||
]:
|
||||
if attempt == 1: # 只重试一次
|
||||
logger.warning(f"错误代码为 400 - {error_code_string},将立即重试...")
|
||||
continue # 直接跳到下一次循环(即重试一次)
|
||||
@ -235,6 +262,9 @@ def qianwen_long_stream(file_id, user_query, max_retries = 2, backoff_factor = 1
|
||||
break
|
||||
|
||||
# 如果所有尝试都失败了,返回空字符串
|
||||
if need_extra:
|
||||
return "", 0
|
||||
else:
|
||||
return ""
|
||||
|
||||
@shared_rate_limit
|
||||
@ -276,8 +306,13 @@ if __name__ == "__main__":
|
||||
file_path = r"C:\Users\Administrator\Desktop\货物标\截取test\2-招标文件_before.pdf"
|
||||
file_id = upload_file(file_path)
|
||||
print(file_id)
|
||||
user_query1 = "该招标文件前附表中的项目名称是什么,请以json格式返回给我"
|
||||
# res1,res2=qianwen_long_stream(file_id,user_query1,2,1,True)
|
||||
res1,res2= qianwen_long_stream(file_id, user_query1, 2, 1,True)
|
||||
print(res1)
|
||||
print(res2)
|
||||
#
|
||||
#
|
||||
# user_query1 = "该招标文件前附表中的项目名称是什么,请以json格式返回给我"
|
||||
# user_query2 = ("请提供文件中关于资格审查的具体内容和标准。")
|
||||
# start_time=time.time()
|
||||
# # First query
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ import json
|
||||
import re
|
||||
from PyPDF2 import PdfReader
|
||||
import textwrap
|
||||
from flask_app.general.doubao import read_txt_to_string, pdf2txt
|
||||
from flask_app.general.doubao import read_txt_to_string, pdf2txt, get_total_tokens
|
||||
from flask_app.general.json_utils import combine_json_results, clean_json_string
|
||||
from flask_app.general.model_continue_query import continue_answer, process_continue_answers
|
||||
from flask_app.general.通义千问long import upload_file, qianwen_long_stream
|
||||
@ -303,7 +303,7 @@ def get_business_requirements(procurement_path, processed_filepath, model_type):
|
||||
future = executor.submit(doubao_model, busi_user_query)
|
||||
else:
|
||||
# 使用 qianwen_long_stream 并传入 file_id
|
||||
future = executor.submit(qianwen_long_stream, file_id, busi_user_query, 2, 1)
|
||||
future = executor.submit(qianwen_long_stream, file_id, busi_user_query, 2, 1,True)
|
||||
futures.append(future)
|
||||
future_to_query[future] = busi_user_query # 映射 future 到 busi_user_query
|
||||
|
||||
@ -313,24 +313,25 @@ def get_business_requirements(procurement_path, processed_filepath, model_type):
|
||||
future = executor.submit(doubao_model, tech_user_query)
|
||||
else:
|
||||
# 使用 qianwen_long_stream 并传入 file_id
|
||||
future = executor.submit(qianwen_long_stream, file_id, tech_user_query, 2, 1)
|
||||
future = executor.submit(qianwen_long_stream, file_id, tech_user_query, 2, 1,True)
|
||||
futures.append(future)
|
||||
future_to_query[future] = tech_user_query # 映射 future 到 tech_user_query
|
||||
# 收集需要继续回答的问题
|
||||
initial_results = {}
|
||||
max_tokens = 3900 if model_type == 1 else 5900
|
||||
# 获取结果
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
original_query = future_to_query[future] # 获取对应的 original_query
|
||||
try:
|
||||
result = future.result()
|
||||
if result: # 确保结果不为空
|
||||
parsed = clean_json_string(result)
|
||||
if isinstance(parsed, str): # flag为截断标记,如果不能解析且len(response)>5000,执行继续问答!
|
||||
questions_to_continue.append((original_query, parsed))
|
||||
elif isinstance(parsed, dict):
|
||||
initial_results.update(parsed)
|
||||
message = result[0]
|
||||
parsed = clean_json_string(message)
|
||||
total_tokens = result[1]
|
||||
if not parsed and total_tokens > max_tokens:
|
||||
questions_to_continue.append((original_query, message))
|
||||
else:
|
||||
print(f"Parsed result is not a dict or str: {parsed}")
|
||||
initial_results.update(parsed)
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
# 处理需要继续回答的问题
|
||||
|
@ -485,20 +485,23 @@ def get_technical_requirements(invalid_path,processed_filepath,model_type=1):
|
||||
modified_grouped_key, "")
|
||||
queries.append(new_query)
|
||||
if model_type:
|
||||
results = multi_threading(queries, "", "", 3) # 豆包
|
||||
results = multi_threading(queries, "", "", 3,True) # 豆包
|
||||
else:
|
||||
results = multi_threading(queries, "", file_id, 2) # 豆包
|
||||
results = multi_threading(queries, "", file_id, 2,True) # 豆包
|
||||
temp_final={}
|
||||
if not results:
|
||||
print("errror!未获得大模型的回答!")
|
||||
else:
|
||||
# 第一步:收集需要调用 `continue_answer` 的问题和解析结果
|
||||
questions_to_continue = [] # 存储需要调用 continue_answer 的 (question, parsed)
|
||||
max_tokens=3900 if model_type==1 else 5900
|
||||
for question, response in results:
|
||||
parsed=clean_json_string(response)
|
||||
if isinstance(parsed, str): #flag为截断标记,如果不能解析且len(response)>5000,执行继续问答!
|
||||
questions_to_continue.append((question, parsed))
|
||||
elif isinstance(parsed, dict):
|
||||
message=response[0]
|
||||
parsed = clean_json_string(message)
|
||||
total_tokens=response[1]
|
||||
if not parsed and total_tokens>max_tokens:
|
||||
questions_to_continue.append((question, message))
|
||||
else:
|
||||
temp_final.update(parsed)
|
||||
# 第二步:多线程处理需要调用 `continue_answer` 的问题
|
||||
if questions_to_continue:
|
||||
|
Loading…
x
Reference in New Issue
Block a user