Compare commits

...

4 Commits

12 changed files with 311 additions and 59 deletions
+1
View File
@@ -10,3 +10,4 @@ data/excel/*.xlsx
rag2_0/demo/ProfessionalTermAnalyzer.py rag2_0/demo/ProfessionalTermAnalyzer.py
data/logs/* data/logs/*
rag2_0/dify/Test.py rag2_0/dify/Test.py
data/query_logs/*
+2
View File
@@ -11,10 +11,12 @@ dependencies = [
"flask>=3.1.1", "flask>=3.1.1",
"gevent>=25.5.1", "gevent>=25.5.1",
"gunicorn>=23.0.0", "gunicorn>=23.0.0",
"ijson>=3.4.0",
"jieba>=0.42.1", "jieba>=0.42.1",
"langchain>=0.3.25", "langchain>=0.3.25",
"langchain-community>=0.3.25", "langchain-community>=0.3.25",
"langchain-openai>=0.3.24", "langchain-openai>=0.3.24",
"langfuse==2.51.3",
"markdownify==0.13.1", "markdownify==0.13.1",
"openpyxl>=3.1.5", "openpyxl>=3.1.5",
"pandas>=2.3.0", "pandas>=2.3.0",
+40 -16
View File
@@ -499,7 +499,7 @@ class DialogueToWorkorder:
return workorder_list return workorder_list
def analyze_conversation_data(self, conversation_excel_path, product_detail_excel_path, max_workers=10): def analyze_conversation_data(self, conversation_excel_path, product_detail_excel_path, max_workers=10, start_date=None, end_date=None):
"""分析会话数据主流程,使用多线程并发处理""" """分析会话数据主流程,使用多线程并发处理"""
# 读取Excel文件 # 读取Excel文件
df = pd.read_excel(conversation_excel_path) df = pd.read_excel(conversation_excel_path)
@@ -511,21 +511,29 @@ class DialogueToWorkorder:
# 解析产品详情 # 解析产品详情
product_detail_dict = self.parse_product_detail_excel(product_detail_excel_path) product_detail_dict = self.parse_product_detail_excel(product_detail_excel_path)
# 如果指定了时间范围,则过滤数据
if start_date or end_date:
# 确保创建时间列为日期时间类型
if '创建时间' in df.columns:
df['创建时间'] = pd.to_datetime(df['创建时间'], errors='coerce')
# 按时间范围过滤
if start_date:
start_date = pd.to_datetime(start_date)
df = df[df['创建时间'] >= start_date]
logger.info(f"过滤开始时间 {start_date},剩余数据行数: {len(df)}")
if end_date:
end_date = pd.to_datetime(end_date)
df = df[df['创建时间'] <= end_date]
logger.info(f"过滤结束时间 {end_date},剩余数据行数: {len(df)}")
else:
logger.warning("数据中没有'创建时间'列,无法按时间范围过滤")
# 按会话ID分组 # 按会话ID分组
conversation_dict = self.group_conversations_by_id(df) conversation_dict = self.group_conversations_by_id(df)
# 限制处理的会话数量为前2000个 logger.info(f"会话总数为 {len(conversation_dict)},处理全部会话")
if len(conversation_dict) > 2000:
logger.info(f"会话总数为 {len(conversation_dict)},限制处理前2000个会话")
# 获取所有会话ID
conversation_ids = list(conversation_dict.keys())
# 只保留前2000个会话
limited_conversation_dict = {
conversation_id: conversation_dict[conversation_id]
for conversation_id in conversation_ids[:2000]
}
conversation_dict = limited_conversation_dict
else:
logger.info(f"会话总数为 {len(conversation_dict)},处理全部会话")
# 使用线程池处理每个会话 # 使用线程池处理每个会话
workorder_dict_list = [] workorder_dict_list = []
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
@@ -629,6 +637,10 @@ def parse_arguments():
help='产品详情Excel文件路径') help='产品详情Excel文件路径')
parser.add_argument('--max_workers', type=int, default=16, parser.add_argument('--max_workers', type=int, default=16,
help='并发处理线程数,默认为16') help='并发处理线程数,默认为16')
parser.add_argument('--start_date', type=str, required=False,
help='开始日期,格式为YYYY-MM-DD')
parser.add_argument('--end_date', type=str, required=False,
help='结束日期,格式为YYYY-MM-DD')
return parser.parse_args() return parser.parse_args()
@@ -649,9 +661,21 @@ def main():
workorder_dict_list = processor.analyze_conversation_data( workorder_dict_list = processor.analyze_conversation_data(
conversation_excel_path, conversation_excel_path,
product_detail_excel_path, product_detail_excel_path,
max_workers=args.max_workers max_workers=args.max_workers,
start_date=args.start_date,
end_date=args.end_date
) )
output_file = conversation_excel_path.replace('.xlsx', '_转工单.xlsx')
# 生成输出文件名
if args.start_date and args.end_date:
output_file = conversation_excel_path.replace('.xlsx', f'_{args.start_date}{args.end_date}_转工单.xlsx')
elif args.start_date:
output_file = conversation_excel_path.replace('.xlsx', f'_从{args.start_date}起_转工单.xlsx')
elif args.end_date:
output_file = conversation_excel_path.replace('.xlsx', f'_至{args.end_date}_转工单.xlsx')
else:
output_file = conversation_excel_path.replace('.xlsx', '_转工单.xlsx')
# 保存结果 # 保存结果
processor.save_results_to_excel(workorder_dict_list, output_file) processor.save_results_to_excel(workorder_dict_list, output_file)
+3 -2
View File
@@ -200,7 +200,8 @@ class QueryRewriteProcessor:
conversation_context=conversation_context, conversation_context=conversation_context,
chat_history=chat_history, chat_history=chat_history,
previous_slots=previous_slots, previous_slots=previous_slots,
enable_query_expansion=True)) enable_query_expansion=True,
use_jieba=True))
# 提取分类信息 # 提取分类信息
classification = result["classification"] classification = result["classification"]
@@ -440,7 +441,7 @@ def main():
for idx, query in enumerate(examples): for idx, query in enumerate(examples):
if query.strip() == "": if query.strip() == "":
continue continue
query="储能C1软件如何新建工程?" query="811619150828能看一下这个锁是16的马"
conversation_context="当前使用软件:配网计价通D3软件" conversation_context="当前使用软件:配网计价通D3软件"
# 在调试模式下使用完整的参数 # 在调试模式下使用完整的参数
print(json.dumps(processor.process_query( print(json.dumps(processor.process_query(
+4 -3
View File
@@ -84,17 +84,18 @@ async def health_check():
return {"status": "ok"} return {"status": "ok"}
@app.get("/query_type", summary="异步检索API") @app.get("/query_type", summary="异步检索API")
async def query_type(query: str, query_type: str): async def query_type(query: str, query_type: str, workflow_run_id:str):
try: try:
# 记录请求 # 记录请求
logger.info(f"接收到请求: {query}, 类型: {query_type}") logger.info(f"接收到请求: {query}, 类型: {query_type}, workflow_run_id: {workflow_run_id}")
# 保存 提问、问题类型、当前时间戳到json # 保存 提问、问题类型、当前时间戳到json
timestamp = datetime.datetime.now().isoformat() timestamp = datetime.datetime.now().isoformat()
query_data = { query_data = {
"query": query, "query": query,
"query_type": query_type, "query_type": query_type,
"timestamp": timestamp "timestamp": timestamp,
"workflow_run_id": workflow_run_id
} }
success = True success = True
try: try:
+2
View File
@@ -197,6 +197,8 @@ class DifyQueryRetrieval:
# 将去重后的文档转换为列表 # 将去重后的文档转换为列表
deduplicated_documents = list(unique_documents.values()) deduplicated_documents = list(unique_documents.values())
if len(deduplicated_documents) == 0:
return []
# 对所有检索出来的文档进行重排序 # 对所有检索出来的文档进行重排序
time_start = time.time() time_start = time.time()
processed_documents = await self.data_post_processor_async(original_query, deduplicated_documents, top_k) processed_documents = await self.data_post_processor_async(original_query, deduplicated_documents, top_k)
+26
View File
@@ -244,6 +244,29 @@ class PgSql:
raise Exception(f"Error while getting conversation_messages: {error}") raise Exception(f"Error while getting conversation_messages: {error}")
return rating return rating
def get_workflow_run_info(self, workflow_run_id):
"""
通过msg_id从message_feedbacks中找到对应的rating。
:param msg_id: 消息ID (UUID格式)
:return: rating 字符串
"""
with self.pg_sql_lock:
rating = None
try:
with self.connection.cursor() as cursor:
# 构建查询语句
cursor.execute("""
SELECT * FROM workflow_runs WHERE id=%s;
""",
(workflow_run_id,))
# 执行查询
result = cursor.fetchone()
if result:
colnames = [desc[0] for desc in cursor.description]
return dict(zip(colnames, result))
except (Exception, psycopg2.Error) as error:
raise Exception(f"Error while getting conversation_messages: {error}")
return None
class DifyTool: class DifyTool:
""" """
@@ -337,6 +360,9 @@ class DifyTool:
def get_message_rating(self, msg_id): def get_message_rating(self, msg_id):
return self.dify_pgsql.get_message_rating(msg_id) return self.dify_pgsql.get_message_rating(msg_id)
def get_workflow_run_info(self, workflow_run_id):
return self.dify_pgsql.get_workflow_run_info(workflow_run_id)
class BaseWorkflowChat: class BaseWorkflowChat:
""" """
工作流对话基类,封装了与Dify API交互的基本功能 工作流对话基类,封装了与Dify API交互的基本功能
+4 -4
View File
@@ -51,7 +51,7 @@ class QueryExpandResponse(BaseModel):
all: List[str] = Field(default_factory=list) all: List[str] = Field(default_factory=list)
step_back: Dict[str, Any] = Field(default_factory=Dict) step_back: Dict[str, Any] = Field(default_factory=Dict)
follow_up: Dict[str, Any] = Field(default_factory=Dict) follow_up: Dict[str, Any] = Field(default_factory=Dict)
hyde: Dict[str, Any] = Field(default_factory=Dict) # hyde: Dict[str, Any] = Field(default_factory=Dict)
multi_questions: Dict[str, Any] = Field(default_factory=Dict) multi_questions: Dict[str, Any] = Field(default_factory=Dict)
# 定义响应模型 # 定义响应模型
@@ -109,7 +109,7 @@ async def intent_recognize(request: IntentRecognizeRequest):
conversation_context=request.conversation_context, conversation_context=request.conversation_context,
chat_history=request.chat_history, chat_history=request.chat_history,
previous_slots=request.previous_slots, previous_slots=request.previous_slots,
use_jieba=False, use_jieba=True,
enable_query_expansion=True enable_query_expansion=True
) )
@@ -150,7 +150,7 @@ async def intent_recognize(request: IntentRecognizeRequest):
all=result["query_expand"]["all"], all=result["query_expand"]["all"],
step_back=result["query_expand"]["step_back"], step_back=result["query_expand"]["step_back"],
follow_up=result["query_expand"]["follow_up"], follow_up=result["query_expand"]["follow_up"],
hyde=result["query_expand"]["hyde"], # hyde=result["query_expand"]["hyde"],
multi_questions=result["query_expand"]["multi_questions"] multi_questions=result["query_expand"]["multi_questions"]
) )
) )
@@ -175,7 +175,7 @@ if __name__ == "__main__":
"rag2_0.dify.intent_recognition_api:app", "rag2_0.dify.intent_recognition_api:app",
host="0.0.0.0", host="0.0.0.0",
port=8001, port=8001,
reload=False, # 开发环境启用热重载 reload=True, # 开发环境启用热重载
workers=1 # 生产环境可以增加worker数量 workers=1 # 生产环境可以增加worker数量
) )
# 生产环境可以使用以下命令启动: # 生产环境可以使用以下命令启动:
+3 -4
View File
@@ -224,15 +224,13 @@ class DataProblemSlots(SlotBase):
# 3.1 后缀名咨询 # 3.1 后缀名咨询
class FileExtensionConsultingSlots(SlotBase): class FileExtensionConsultingSlots(SlotBase):
file_extension: str = Field(default="", description="文件后缀名") file_extension: str = Field(default="", description="文件后缀名")
operation_purpose: str = Field(default="", description="操作目的(了解对应软件,对应工程)") operation_purpose: Optional[str] = Field(default="", description="操作目的(了解对应软件,对应工程)")
def check_required_slots(self) -> Tuple[bool, Dict[str, str]]: def check_required_slots(self) -> Tuple[bool, Dict[str, str]]:
"""检查必填槽位是否都存在""" """检查必填槽位是否都存在"""
missing_slots = {} missing_slots = {}
if not self.file_extension: if not self.file_extension:
missing_slots["file_extension"] = FileExtensionConsultingSlots.model_fields["file_extension"].description missing_slots["file_extension"] = FileExtensionConsultingSlots.model_fields["file_extension"].description
if not self.operation_purpose:
missing_slots["operation_purpose"] = FileExtensionConsultingSlots.model_fields["operation_purpose"].description
return len(missing_slots) == 0, missing_slots return len(missing_slots) == 0, missing_slots
# 3.2 软件锁类 # 3.2 软件锁类
@@ -311,7 +309,8 @@ class IntentAndSlotResult(BaseModel):
class StepBackPrompt(BaseModel): class StepBackPrompt(BaseModel):
"""后退提示数据模型""" """后退提示数据模型"""
original_query: str = Field(description="原始查询") original_query: str = Field(description="原始查询")
step_back_query: str = Field(description="后退提示生成的抽象查询") can_use_back_prompt: bool = Field(description="原始查询是否可以进行后退提示(True/False),如果原始查询没有限定词或其他限定词语,则不能进行后退提示")
step_back_query: List[str] = Field(description="后退提示生成的抽象查询(多个)")
class FollowUpQuestions(BaseModel): class FollowUpQuestions(BaseModel):
"""后续问题数据模型""" """后续问题数据模型"""
+57 -22
View File
@@ -155,7 +155,9 @@ class AsyncIntentRecognizer:
logging.info(f"异步意图分类耗时统计 - 总耗时: {classification_time:.2f}") logging.info(f"异步意图分类耗时统计 - 总耗时: {classification_time:.2f}")
# 尝试直接解析JSON响应 # 尝试直接解析JSON响应
parsed_output = classification_parser.parse(response.content.strip()) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = classification_parser.parse(clean_output)
return parsed_output return parsed_output
except Exception as e: except Exception as e:
raise RuntimeError(f"解析分类结果时出错: {e}") from e raise RuntimeError(f"解析分类结果时出错: {e}") from e
@@ -216,7 +218,9 @@ class AsyncIntentRecognizer:
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
# 尝试使用Pydantic解析器解析TermList # 尝试使用Pydantic解析器解析TermList
parsed_output = terms_list_parser.parse(response.content) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = terms_list_parser.parse(clean_output)
return parsed_output.terms return parsed_output.terms
@@ -344,9 +348,9 @@ class AsyncIntentRecognizer:
try: try:
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
response.content = response.content.strip()
# 尝试直接解析JSON响应 clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = query_rewrite_parser.parse(response.content) parsed_output = query_rewrite_parser.parse(clean_output)
rewrite_end_time = time.time() rewrite_end_time = time.time()
rewrite_time = rewrite_end_time - rewrite_start_time rewrite_time = rewrite_end_time - rewrite_start_time
logging.info(f"异步问题改写耗时统计 - 总耗时: {rewrite_time:.2f}") logging.info(f"异步问题改写耗时统计 - 总耗时: {rewrite_time:.2f}")
@@ -374,6 +378,18 @@ class AsyncIntentRecognizer:
return bool(matched_suffixes), matched_suffixes return bool(matched_suffixes), matched_suffixes
def _process_lock_related_query(self, query: str) -> str:
"""
特殊处理锁相关咨询
"""
pattern = r'(?<!\d)(?:8116(?:\s*\d){8}|\d{2}\s*-\s*\d{6})(?!\d)'
matches = re.findall(pattern, query)
if not matches:
return query
lock_number = "".join(matches)
return f"通过博微软件助手查询软件锁信息,锁注册号为{lock_number}"
async def process_query_async(self, query: str, conversation_context: str = "", async def process_query_async(self, query: str, conversation_context: str = "",
chat_history: List[Dict[str, str]] = None, chat_history: List[Dict[str, str]] = None,
previous_slots: Dict[str, Any] = None, previous_slots: Dict[str, Any] = None,
@@ -410,7 +426,7 @@ class AsyncIntentRecognizer:
asyncio.create_task(self._generate_follow_up_questions_async(query, chat_history, conversation_context)), asyncio.create_task(self._generate_follow_up_questions_async(query, chat_history, conversation_context)),
# 5.3: HyDE # 5.3: HyDE
asyncio.create_task(self._generate_hypothetical_document_async(query, chat_history, conversation_context)), # asyncio.create_task(self._generate_hypothetical_document_async(query, chat_history, conversation_context)),
# 5.4: 多问题查询 # 5.4: 多问题查询
asyncio.create_task(self._generate_multi_questions_async(query, chat_history, conversation_context)) asyncio.create_task(self._generate_multi_questions_async(query, chat_history, conversation_context))
@@ -438,11 +454,18 @@ class AsyncIntentRecognizer:
classification_task = self._classify_intent_async(rewrite.rewrite, conversation_context, chat_history, previous_slots) classification_task = self._classify_intent_async(rewrite.rewrite, conversation_context, chat_history, previous_slots)
classification = await classification_task classification = await classification_task
# 特殊处理 锁相关咨询
if classification.vertical_classification == "安装下载注册" and classification.sub_classification == "软件锁类":
process_lock_start_time = time.time()
rewrite.rewrite = self._process_lock_related_query(rewrite.rewrite)
process_lock_end_time = time.time()
process_lock_time = process_lock_end_time - process_lock_start_time
logging.info(f"锁相关咨询正则匹配 - 总耗时: {process_lock_time:.2f}")
# 步骤4: 进行槽位填充 # 步骤4: 进行槽位填充
# 如果是有效分类,进行槽位填充 # 如果是有效分类,进行槽位填充
slot_filling_result = {} slot_filling_result = {}
if classification.vertical_classification not in ["其他", "闲聊"] and classification.sub_classification not in ["其他", "闲聊"]: # if classification.vertical_classification not in ["其他", "闲聊"] and classification.sub_classification not in ["其他", "闲聊"]:
slot_filling_result = await self._fill_slots_async(rewrite.rewrite, classification, conversation_context, chat_history, previous_slots) # slot_filling_result = await self._fill_slots_async(rewrite.rewrite, classification, conversation_context, chat_history, previous_slots)
if not enable_query_expansion: if not enable_query_expansion:
return { return {
@@ -460,23 +483,24 @@ class AsyncIntentRecognizer:
logging.info(f"异步问题扩展环节耗时统计 - 总耗时: {end_time - start_time:.2f}") logging.info(f"异步问题扩展环节耗时统计 - 总耗时: {end_time - start_time:.2f}")
# 收集结果 # 收集结果
step_back_result = query_expand_results[0] if query_expand_results[0] else StepBackPrompt(original_query=query, step_back_query=query) step_back_result = query_expand_results[0] if query_expand_results[0] else StepBackPrompt(original_query=query, can_use_back_prompt=False, step_back_query=[query])
follow_up_result = query_expand_results[1] if query_expand_results[1] else FollowUpQuestions(original_query=query, follow_up_query=query) follow_up_result = query_expand_results[1] if query_expand_results[1] else FollowUpQuestions(original_query=query, follow_up_query=query)
hyde_result = query_expand_results[2] if query_expand_results[2] else HypotheticalDocument(original_query=query, hypothetical_answer="") # hyde_result = query_expand_results[2] if query_expand_results[2] else HypotheticalDocument(original_query=query, hypothetical_answer="")
multi_questions_result = query_expand_results[3] if query_expand_results[3] else MultiQuestions(original_query=query, sub_questions=[query]) multi_questions_result = query_expand_results[2] if query_expand_results[2] else MultiQuestions(original_query=query, sub_questions=[query])
all_questions = multi_questions_result.sub_questions all_questions = multi_questions_result.sub_questions
all_questions.append(query) all_questions.append(query)
all_questions.append(step_back_result.step_back_query) all_questions.append(rewrite.rewrite)
all_questions.extend(step_back_result.step_back_query)
all_questions.append(follow_up_result.follow_up_query) all_questions.append(follow_up_result.follow_up_query)
all_questions.append(hyde_result.hypothetical_answer) # all_questions.append(hyde_result.hypothetical_answer)
all_questions = list(set(all_questions)) all_questions = list(set(all_questions))
query_expand = { query_expand = {
"all": all_questions, "all": all_questions,
"step_back": step_back_result.model_dump(), "step_back": step_back_result.model_dump(),
"follow_up": follow_up_result.model_dump(), "follow_up": follow_up_result.model_dump(),
"hyde": hyde_result.model_dump(), # "hyde": hyde_result.model_dump(),
"multi_questions": multi_questions_result.model_dump() "multi_questions": multi_questions_result.model_dump()
} }
@@ -597,9 +621,10 @@ class AsyncIntentRecognizer:
try: try:
# 异步调用LLM # 异步调用LLM
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
# 尝试解析LLM响应 # 尝试解析LLM响应
parsed_output = slot_parser.parse(response.content) parsed_output = slot_parser.parse(clean_output)
return parsed_output return parsed_output
except Exception as e: except Exception as e:
# 如果解析失败,创建一个空的模型实例 # 如果解析失败,创建一个空的模型实例
@@ -633,7 +658,9 @@ class AsyncIntentRecognizer:
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
# 解析输出 # 解析输出
parsed_output = step_back_parser.parse(response.content) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = step_back_parser.parse(clean_output)
step_back_end_time = time.time() step_back_end_time = time.time()
step_back_time = step_back_end_time - step_back_start_time step_back_time = step_back_end_time - step_back_start_time
logging.debug(f"异步后退提示生成耗时统计 - 总耗时: {step_back_time:.2f}") logging.debug(f"异步后退提示生成耗时统计 - 总耗时: {step_back_time:.2f}")
@@ -641,7 +668,7 @@ class AsyncIntentRecognizer:
except Exception as e: except Exception as e:
# 如果解析失败,返回原始查询作为后退提示 # 如果解析失败,返回原始查询作为后退提示
logging.error(f"异步后退提示生成失败: {e}", exc_info=True) logging.error(f"异步后退提示生成失败: {e}", exc_info=True)
return StepBackPrompt(original_query=query, step_back_query=query) return StepBackPrompt(original_query=query, can_use_back_prompt=False, step_back_query=[query])
async def _generate_follow_up_questions_async(self, query: str, chat_history: List[Dict[str, str]] = None, conversation_context: str = "") -> FollowUpQuestions: async def _generate_follow_up_questions_async(self, query: str, chat_history: List[Dict[str, str]] = None, conversation_context: str = "") -> FollowUpQuestions:
""" """
@@ -670,7 +697,9 @@ class AsyncIntentRecognizer:
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
# 解析输出 # 解析输出
parsed_output = follow_up_parser.parse(response.content) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = follow_up_parser.parse(clean_output)
follow_up_end_time = time.time() follow_up_end_time = time.time()
follow_up_time = follow_up_end_time - follow_up_start_time follow_up_time = follow_up_end_time - follow_up_start_time
logging.debug(f"异步后续问题生成耗时统计 - 总耗时: {follow_up_time:.2f}") logging.debug(f"异步后续问题生成耗时统计 - 总耗时: {follow_up_time:.2f}")
@@ -707,7 +736,9 @@ class AsyncIntentRecognizer:
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
# 解析输出 # 解析输出
parsed_output = hyde_parser.parse(response.content) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = hyde_parser.parse(clean_output)
hyde_end_time = time.time() hyde_end_time = time.time()
hyde_time = hyde_end_time - hyde_start_time hyde_time = hyde_end_time - hyde_start_time
logging.debug(f"异步假设性文档生成耗时统计 - 总耗时: {hyde_time:.2f}") logging.debug(f"异步假设性文档生成耗时统计 - 总耗时: {hyde_time:.2f}")
@@ -744,7 +775,9 @@ class AsyncIntentRecognizer:
response = await self._llm.invoke_async(formatted_prompt, False) response = await self._llm.invoke_async(formatted_prompt, False)
# 解析输出 # 解析输出
parsed_output = multi_questions_parser.parse(response.content) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
parsed_output = multi_questions_parser.parse(clean_output)
multi_questions_end_time = time.time() multi_questions_end_time = time.time()
multi_questions_time = multi_questions_end_time - multi_questions_start_time multi_questions_time = multi_questions_end_time - multi_questions_start_time
logging.debug(f"异步多角度问题生成耗时统计 - 总耗时: {multi_questions_time:.2f}") logging.debug(f"异步多角度问题生成耗时统计 - 总耗时: {multi_questions_time:.2f}")
@@ -799,7 +832,9 @@ class AsyncIntentRecognizer:
try: try:
# 解析LLM响应为JSON # 解析LLM响应为JSON
result_json = parser.parse(response.content) response.content = response.content.strip()
clean_output = re.sub(r'<think>.*?</think>', '', response.content, flags=re.DOTALL)
result_json = parser.parse(clean_output)
classification = result_json.classification classification = result_json.classification
slot_filling = result_json.slots slot_filling = result_json.slots
is_complete, missing_slots = slot_filling.check_required_slots() is_complete, missing_slots = slot_filling.check_required_slots()
+27 -8
View File
@@ -31,7 +31,8 @@ classification_info="""【垂直领域分类】:
1. 软件问题 -- 指涉及软件使用、功能询问、软件故障排查等方面的提问或请求。 1. 软件问题 -- 指涉及软件使用、功能询问、软件故障排查等方面的提问或请求。
2. 业务问题 -- 指涉及电力造价领域专业知识、造价费用计算等电力造价业务知识 2. 业务问题 -- 指涉及电力造价领域专业知识、造价费用计算等电力造价业务知识
3. 安装下载注册 -- 指涉及软件(或插件)安装下载、注册、激活等操作类问题。 3. 安装下载注册 -- 指涉及软件(或插件)安装下载、注册、激活等操作类问题。
4. 其他 -- 指与软件或电力造价专业无关的日常对话、问候、感慨、情绪表达等。 4. 固定话术类 -- 指涉及需要固定话术回答的问题,如:规费咨询
5. 其他 -- 指与软件或电力造价专业无关的日常对话、问候、感慨、情绪表达等。
【软件问题包括以下两类】: 【软件问题包括以下两类】:
1. 软件功能:询问软件功能的使用、功能操作(调整)、功能位置、如何设置、如何转换等 1. 软件功能:询问软件功能的使用、功能操作(调整)、功能位置、如何设置、如何转换等
@@ -49,11 +50,19 @@ classification_info="""【垂直领域分类】:
"用哪个软件打开.BDY3文件?", "用哪个软件打开.BDY3文件?",
"BDD3是什么" "BDD3是什么"
2. 软件锁类:询问软件锁信息、锁注册号查询、许可证查询、锁激活问题等软件锁相关问题 2. 软件锁类:询问软件锁信息、锁注册号查询、许可证查询、锁激活问题等软件锁相关问题
形如: 8116 开头连续的12位数字 或者 形如 xx-xxxxxx 的数字格式 的内容为锁的注册号,提问出现对应内容时,归类为软件锁类
3. 安装下载类:安装下载咨询、组件(插件)选择、环境配置、安装包下载、政策文件(规范文件)下载等 3. 安装下载类:安装下载咨询、组件(插件)选择、环境配置、安装包下载、政策文件(规范文件)下载等
4. 问题排查类:软件安装下载失败、报错,系统兼容性问题等 4. 问题排查类:软件安装下载失败、报错,系统兼容性问题等
【固定话术类包括以下一类】:
1. 规费咨询:所有涉及规费咨询等问题(规费、社保费、公积金费等)
【其他】: 【其他】:
1. 其他""" 1. 其他
分类优先级:
固定话术类 > 软件问题 、 业务问题 、 安装下载注册 > 其他
"""
classification_prompt=""" classification_prompt="""
用户正在使用电力造价软件或想询问电力造价领域相关知识,你需要根据用户的输入内容集合历史对话(如果存在),将其归类为以下垂直领域之一: 用户正在使用电力造价软件或想询问电力造价领域相关知识,你需要根据用户的输入内容集合历史对话(如果存在),将其归类为以下垂直领域之一:
@@ -211,13 +220,12 @@ step_back_prompt = """
## 任务说明 ## 任务说明
1. 分析用户的原始问题,理解其核心意图和需求 1. 分析用户的原始问题,理解其核心意图和需求
2. 考虑历史对话和会话背景,理解用户当前问题的上下文 2. 考虑历史对话和会话背景,理解用户当前问题的上下文
3. 生成一个更抽象、更高层次的问题,称为"后退问题" 3. 生成更抽象、更高层次的问题,称为"后退问题",后退问题可以生成多个,依次后退到更抽象、更高层次的问题
4. 后退问题应该: 4. 后退问题应该:
- 更加通用和抽象 - 更加通用和抽象,不应包含原始问题的具体细节(包括场景限定、界面限定等其他限定词语)
- 涵盖原始问题的核心主题 - 涵盖原始问题的核心主题
- 去除过于具体的限制条件(如时间、地点、特定版本等) - 去除过于具体的限制条件(如时间、地点、特定版本、特定工程等)
- 保持在同一领域和主题范围内 - 保持在同一领域和主题范围内
- 考虑历史对话中的相关信息
## 输入 ## 输入
用户原始问题: {query} 用户原始问题: {query}
@@ -229,10 +237,21 @@ step_back_prompt = """
## 示例 ## 示例
原始问题: "配网D3软件2023版本如何在Windows 11系统上导入单位工程量清单?" 原始问题: "配网D3软件2023版本如何在Windows 11系统上导入单位工程量清单?"
后退问题: "配网D3软件如何导入工程量清单?" 后退问题:
{{
"original_query": "配网D3软件2023版本如何在Windows 11系统上导入单位工程量清单?",
"can_use_back_prompt": True,
"step_back_query": ["配网D3软件如何导入工程量清单?", "如何导入单位工程量清单?"]
}}
原始问题: "技改T1软件中的某个设备更换后,如何在系统中更新对应的定额?" 原始问题: "技改T1软件中的某个设备更换后,如何在系统中更新对应的定额?"
后退问题: "技改T1软件中如何更新设备对应的定额?" 后退问题:
{{
"original_query": "技改T1软件中的某个设备更换后,如何在系统中更新对应的定额?",
"can_use_back_prompt": True,
"step_back_query": ["技改T1软件中如何更新设备对应的定额?", "如何更新设备对应的定额?"]
}}
""" """
follow_up_questions_prompt = """ follow_up_questions_prompt = """
Generated
+142
View File
@@ -129,6 +129,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" },
] ]
[[package]]
name = "backoff"
version = "2.2.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/47/d7/5bbeb12c44d7c4f2fb5b56abce497eb5ed9f34d85701de869acedd602619/backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", size = 17001, upload-time = "2022-10-05T19:19:32.061Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148, upload-time = "2022-10-05T19:19:30.546Z" },
]
[[package]] [[package]]
name = "beautifulsoup4" name = "beautifulsoup4"
version = "4.13.4" version = "4.13.4"
@@ -600,6 +609,64 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
] ]
[[package]]
name = "ijson"
version = "3.4.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a3/4f/1cfeada63f5fce87536651268ddf5cca79b8b4bbb457aee4e45777964a0a/ijson-3.4.0.tar.gz", hash = "sha256:5f74dcbad9d592c428d3ca3957f7115a42689ee7ee941458860900236ae9bb13", size = 65782, upload-time = "2025-05-08T02:37:20.135Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1a/0d/3e2998f4d7b7d2db2d511e4f0cf9127b6e2140c325c3cb77be46ae46ff1d/ijson-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e369bf5a173ca51846c243002ad8025d32032532523b06510881ecc8723ee54", size = 87643, upload-time = "2025-05-08T02:35:35.693Z" },
{ url = "https://files.pythonhosted.org/packages/e9/7b/afef2b08af2fee5ead65fcd972fadc3e31f9ae2b517fe2c378d50a9bf79b/ijson-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26e7da0a3cd2a56a1fde1b34231867693f21c528b683856f6691e95f9f39caec", size = 59260, upload-time = "2025-05-08T02:35:37.166Z" },
{ url = "https://files.pythonhosted.org/packages/da/4a/39f583a2a13096f5063028bb767622f09cafc9ec254c193deee6c80af59f/ijson-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1c28c7f604729be22aa453e604e9617b665fa0c24cd25f9f47a970e8130c571a", size = 59311, upload-time = "2025-05-08T02:35:38.538Z" },
{ url = "https://files.pythonhosted.org/packages/3c/58/5b80efd54b093e479c98d14b31d7794267281f6a8729f2c94fbfab661029/ijson-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bed8bcb84d3468940f97869da323ba09ae3e6b950df11dea9b62e2b231ca1e3", size = 136125, upload-time = "2025-05-08T02:35:39.976Z" },
{ url = "https://files.pythonhosted.org/packages/e5/f5/f37659b1647ecc3992216277cd8a45e2194e84e8818178f77c99e1d18463/ijson-3.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:296bc824f4088f2af814aaf973b0435bc887ce3d9f517b1577cc4e7d1afb1cb7", size = 130699, upload-time = "2025-05-08T02:35:41.483Z" },
{ url = "https://files.pythonhosted.org/packages/ee/2f/4c580ac4bb5eda059b672ad0a05e4bafdae5182a6ec6ab43546763dafa91/ijson-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8145f8f40617b6a8aa24e28559d0adc8b889e56a203725226a8a60fa3501073f", size = 134963, upload-time = "2025-05-08T02:35:43.017Z" },
{ url = "https://files.pythonhosted.org/packages/6d/9e/64ec39718609faab6ed6e1ceb44f9c35d71210ad9c87fff477c03503e8f8/ijson-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b674a97bd503ea21bc85103e06b6493b1b2a12da3372950f53e1c664566a33a4", size = 137405, upload-time = "2025-05-08T02:35:44.618Z" },
{ url = "https://files.pythonhosted.org/packages/71/b2/f0bf0e4a0962845597996de6de59c0078bc03a1f899e03908220039f4cf6/ijson-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8bc731cf1c3282b021d3407a601a5a327613da9ad3c4cecb1123232623ae1826", size = 131861, upload-time = "2025-05-08T02:35:46.22Z" },
{ url = "https://files.pythonhosted.org/packages/17/83/4a2e3611e2b4842b413ec84d2e54adea55ab52e4408ea0f1b1b927e19536/ijson-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42ace5e940e0cf58c9de72f688d6829ddd815096d07927ee7e77df2648006365", size = 134297, upload-time = "2025-05-08T02:35:47.401Z" },
{ url = "https://files.pythonhosted.org/packages/38/75/2d332911ac765b44cd7da0cb2b06143521ad5e31dfcc8d8587e6e6168bc8/ijson-3.4.0-cp311-cp311-win32.whl", hash = "sha256:5be39a0df4cd3f02b304382ea8885391900ac62e95888af47525a287c50005e9", size = 51161, upload-time = "2025-05-08T02:35:49.164Z" },
{ url = "https://files.pythonhosted.org/packages/7d/ba/4ad571f9f7fcf5906b26e757b130c1713c5f0198a1e59568f05d53a0816c/ijson-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:0b1be1781792291e70d2e177acf564ec672a7907ba74f313583bdf39fe81f9b7", size = 53710, upload-time = "2025-05-08T02:35:50.323Z" },
{ url = "https://files.pythonhosted.org/packages/f8/ec/317ee5b2d13e50448833ead3aa906659a32b376191f6abc2a7c6112d2b27/ijson-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:956b148f88259a80a9027ffbe2d91705fae0c004fbfba3e5a24028fbe72311a9", size = 87212, upload-time = "2025-05-08T02:35:51.835Z" },
{ url = "https://files.pythonhosted.org/packages/f8/43/b06c96ced30cacecc5d518f89b0fd1c98c294a30ff88848b70ed7b7f72a1/ijson-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:06b89960f5c721106394c7fba5760b3f67c515b8eb7d80f612388f5eca2f4621", size = 59175, upload-time = "2025-05-08T02:35:52.988Z" },
{ url = "https://files.pythonhosted.org/packages/e9/df/b4aeafb7ecde463130840ee9be36130823ec94a00525049bf700883378b8/ijson-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9a0bb591cf250dd7e9dfab69d634745a7f3272d31cfe879f9156e0a081fd97ee", size = 59011, upload-time = "2025-05-08T02:35:54.394Z" },
{ url = "https://files.pythonhosted.org/packages/e3/7c/a80b8e361641609507f62022089626d4b8067f0826f51e1c09e4ba86eba8/ijson-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72e92de999977f4c6b660ffcf2b8d59604ccd531edcbfde05b642baf283e0de8", size = 146094, upload-time = "2025-05-08T02:35:55.601Z" },
{ url = "https://files.pythonhosted.org/packages/01/44/fa416347b9a802e3646c6ff377fc3278bd7d6106e17beb339514b6a3184e/ijson-3.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e9602157a5b869d44b6896e64f502c712a312fcde044c2e586fccb85d3e316e", size = 137903, upload-time = "2025-05-08T02:35:56.814Z" },
{ url = "https://files.pythonhosted.org/packages/24/c6/41a9ad4d42df50ff6e70fdce79b034f09b914802737ebbdc141153d8d791/ijson-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e83660edb931a425b7ff662eb49db1f10d30ca6d4d350e5630edbed098bc01", size = 148339, upload-time = "2025-05-08T02:35:58.595Z" },
{ url = "https://files.pythonhosted.org/packages/5f/6f/7d01efda415b8502dce67e067ed9e8a124f53e763002c02207e542e1a2f1/ijson-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:49bf8eac1c7b7913073865a859c215488461f7591b4fa6a33c14b51cb73659d0", size = 149383, upload-time = "2025-05-08T02:36:00.197Z" },
{ url = "https://files.pythonhosted.org/packages/95/6c/0d67024b9ecb57916c5e5ab0350251c9fe2f86dc9c8ca2b605c194bdad6a/ijson-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:160b09273cb42019f1811469508b0a057d19f26434d44752bde6f281da6d3f32", size = 141580, upload-time = "2025-05-08T02:36:01.998Z" },
{ url = "https://files.pythonhosted.org/packages/06/43/e10edcc1c6a3b619294de835e7678bfb3a1b8a75955f3689fd66a1e9e7b4/ijson-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2019ff4e6f354aa00c76c8591bd450899111c61f2354ad55cc127e2ce2492c44", size = 150280, upload-time = "2025-05-08T02:36:03.926Z" },
{ url = "https://files.pythonhosted.org/packages/07/84/1cbeee8e8190a1ebe6926569a92cf1fa80ddb380c129beb6f86559e1bb24/ijson-3.4.0-cp312-cp312-win32.whl", hash = "sha256:931c007bf6bb8330705429989b2deed6838c22b63358a330bf362b6e458ba0bf", size = 51512, upload-time = "2025-05-08T02:36:05.595Z" },
{ url = "https://files.pythonhosted.org/packages/66/13/530802bc391c95be6fe9f96e9aa427d94067e7c0b7da7a9092344dc44c4b/ijson-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:71523f2b64cb856a820223e94d23e88369f193017ecc789bb4de198cc9d349eb", size = 54081, upload-time = "2025-05-08T02:36:07.099Z" },
{ url = "https://files.pythonhosted.org/packages/77/b3/b1d2eb2745e5204ec7a25365a6deb7868576214feb5e109bce368fb692c9/ijson-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e8d96f88d75196a61c9d9443de2b72c2d4a7ba9456ff117b57ae3bba23a54256", size = 87216, upload-time = "2025-05-08T02:36:08.414Z" },
{ url = "https://files.pythonhosted.org/packages/b1/cd/cd6d340087617f8cc9bedbb21d974542fe2f160ed0126b8288d3499a469b/ijson-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c45906ce2c1d3b62f15645476fc3a6ca279549127f01662a39ca5ed334a00cf9", size = 59170, upload-time = "2025-05-08T02:36:09.604Z" },
{ url = "https://files.pythonhosted.org/packages/3e/4d/32d3a9903b488d3306e3c8288f6ee4217d2eea82728261db03a1045eb5d1/ijson-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4ab4bc2119b35c4363ea49f29563612237cae9413d2fbe54b223be098b97bc9e", size = 59013, upload-time = "2025-05-08T02:36:10.696Z" },
{ url = "https://files.pythonhosted.org/packages/d5/c8/db15465ab4b0b477cee5964c8bfc94bf8c45af8e27a23e1ad78d1926e587/ijson-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97b0a9b5a15e61dfb1f14921ea4e0dba39f3a650df6d8f444ddbc2b19b479ff1", size = 146564, upload-time = "2025-05-08T02:36:11.916Z" },
{ url = "https://files.pythonhosted.org/packages/c4/d8/0755545bc122473a9a434ab90e0f378780e603d75495b1ca3872de757873/ijson-3.4.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3047bb994dabedf11de11076ed1147a307924b6e5e2df6784fb2599c4ad8c60", size = 137917, upload-time = "2025-05-08T02:36:13.532Z" },
{ url = "https://files.pythonhosted.org/packages/d0/c6/aeb89c8939ebe3f534af26c8c88000c5e870dbb6ae33644c21a4531f87d2/ijson-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68c83161b052e9f5dc8191acbc862bb1e63f8a35344cb5cd0db1afd3afd487a6", size = 148897, upload-time = "2025-05-08T02:36:14.813Z" },
{ url = "https://files.pythonhosted.org/packages/be/0e/7ef6e9b372106f2682a4a32b3c65bf86bb471a1670e4dac242faee4a7d3f/ijson-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1eebd9b6c20eb1dffde0ae1f0fbb4aeacec2eb7b89adb5c7c0449fc9fd742760", size = 149711, upload-time = "2025-05-08T02:36:16.476Z" },
{ url = "https://files.pythonhosted.org/packages/d1/5d/9841c3ed75bcdabf19b3202de5f862a9c9c86ce5c7c9d95fa32347fdbf5f/ijson-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:13fb6d5c35192c541421f3ee81239d91fc15a8d8f26c869250f941f4b346a86c", size = 141691, upload-time = "2025-05-08T02:36:18.044Z" },
{ url = "https://files.pythonhosted.org/packages/d5/d2/ce74e17218dba292e9be10a44ed0c75439f7958cdd263adb0b5b92d012d5/ijson-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:28b7196ff7b37c4897c547a28fa4876919696739fc91c1f347651c9736877c69", size = 150738, upload-time = "2025-05-08T02:36:19.483Z" },
{ url = "https://files.pythonhosted.org/packages/4e/43/dcc480f94453b1075c9911d4755b823f3ace275761bb37b40139f22109ca/ijson-3.4.0-cp313-cp313-win32.whl", hash = "sha256:3c2691d2da42629522140f77b99587d6f5010440d58d36616f33bc7bdc830cc3", size = 51512, upload-time = "2025-05-08T02:36:20.99Z" },
{ url = "https://files.pythonhosted.org/packages/35/dd/d8c5f15efd85ba51e6e11451ebe23d779361a9ec0d192064c2a8c3cdfcb8/ijson-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:c4554718c275a044c47eb3874f78f2c939f300215d9031e785a6711cc51b83fc", size = 54074, upload-time = "2025-05-08T02:36:22.075Z" },
{ url = "https://files.pythonhosted.org/packages/79/73/24ad8cd106203419c4d22bed627e02e281d66b83e91bc206a371893d0486/ijson-3.4.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:915a65e3f3c0eee2ea937bc62aaedb6c14cc1e8f0bb9f3f4fb5a9e2bbfa4b480", size = 91694, upload-time = "2025-05-08T02:36:23.289Z" },
{ url = "https://files.pythonhosted.org/packages/17/2d/f7f680984bcb7324a46a4c2df3bd73cf70faef0acfeb85a3f811abdfd590/ijson-3.4.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:afbe9748707684b6c5adc295c4fdcf27765b300aec4d484e14a13dca4e5c0afa", size = 61390, upload-time = "2025-05-08T02:36:24.42Z" },
{ url = "https://files.pythonhosted.org/packages/09/a1/f3ca7bab86f95bdb82494739e71d271410dfefce4590785d511669127145/ijson-3.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d823f8f321b4d8d5fa020d0a84f089fec5d52b7c0762430476d9f8bf95bbc1a9", size = 61140, upload-time = "2025-05-08T02:36:26.708Z" },
{ url = "https://files.pythonhosted.org/packages/51/79/dd340df3d4fc7771c95df29997956b92ed0570fe7b616d1792fea9ad93f2/ijson-3.4.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8a0a2c54f3becf76881188beefd98b484b1d3bd005769a740d5b433b089fa23", size = 214739, upload-time = "2025-05-08T02:36:27.973Z" },
{ url = "https://files.pythonhosted.org/packages/59/f0/85380b7f51d1f5fb7065d76a7b623e02feca920cc678d329b2eccc0011e0/ijson-3.4.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ced19a83ab09afa16257a0b15bc1aa888dbc555cb754be09d375c7f8d41051f2", size = 198338, upload-time = "2025-05-08T02:36:29.496Z" },
{ url = "https://files.pythonhosted.org/packages/a5/cd/313264cf2ec42e0f01d198c49deb7b6fadeb793b3685e20e738eb6b3fa13/ijson-3.4.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8100f9885eff1f38d35cef80ef759a1bbf5fc946349afa681bd7d0e681b7f1a0", size = 207515, upload-time = "2025-05-08T02:36:30.981Z" },
{ url = "https://files.pythonhosted.org/packages/12/94/bf14457aa87ea32641f2db577c9188ef4e4ae373478afef422b31fc7f309/ijson-3.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d7bcc3f7f21b0f703031ecd15209b1284ea51b2a329d66074b5261de3916c1eb", size = 210081, upload-time = "2025-05-08T02:36:32.403Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b4/eaee39e290e40e52d665db9bd1492cfdce86bd1e47948e0440db209c6023/ijson-3.4.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2dcb190227b09dd171bdcbfe4720fddd574933c66314818dfb3960c8a6246a77", size = 199253, upload-time = "2025-05-08T02:36:33.861Z" },
{ url = "https://files.pythonhosted.org/packages/c5/9c/e09c7b9ac720a703ab115b221b819f149ed54c974edfff623c1e925e57da/ijson-3.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:eda4cfb1d49c6073a901735aaa62e39cb7ab47f3ad7bb184862562f776f1fa8a", size = 203816, upload-time = "2025-05-08T02:36:35.348Z" },
{ url = "https://files.pythonhosted.org/packages/7c/14/acd304f412e32d16a2c12182b9d78206bb0ae35354d35664f45db05c1b3b/ijson-3.4.0-cp313-cp313t-win32.whl", hash = "sha256:0772638efa1f3b72b51736833404f1cbd2f5beeb9c1a3d392e7d385b9160cba7", size = 53760, upload-time = "2025-05-08T02:36:36.608Z" },
{ url = "https://files.pythonhosted.org/packages/2f/24/93dd0a467191590a5ed1fc2b35842bca9d09900d001e00b0b497c0208ef6/ijson-3.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3d8a0d67f36e4fb97c61a724456ef0791504b16ce6f74917a31c2e92309bbeb9", size = 56948, upload-time = "2025-05-08T02:36:37.849Z" },
{ url = "https://files.pythonhosted.org/packages/a3/9b/0bc0594d357600c03c3b5a3a34043d764fc3ad3f0757d2f3aae5b28f6c1c/ijson-3.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cdc8c5ca0eec789ed99db29c68012dda05027af0860bb360afd28d825238d69d", size = 56483, upload-time = "2025-05-08T02:37:03.274Z" },
{ url = "https://files.pythonhosted.org/packages/00/1f/506cf2574673da1adcc8a794ebb85bf857cabe6294523978637e646814de/ijson-3.4.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8e6b44b6ec45d5b1a0ee9d97e0e65ab7f62258727004cbbe202bf5f198bc21f7", size = 55957, upload-time = "2025-05-08T02:37:04.865Z" },
{ url = "https://files.pythonhosted.org/packages/dc/3d/a7cd8d8a6de0f3084fe4d457a8f76176e11b013867d1cad16c67d25e8bec/ijson-3.4.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b51e239e4cb537929796e840d349fc731fdc0d58b1a0683ce5465ad725321e0f", size = 69394, upload-time = "2025-05-08T02:37:06.142Z" },
{ url = "https://files.pythonhosted.org/packages/32/51/aa30abc02aabfc41c95887acf5f1f88da569642d7197fbe5aa105545226d/ijson-3.4.0-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed05d43ec02be8ddb1ab59579761f6656b25d241a77fd74f4f0f7ec09074318a", size = 70377, upload-time = "2025-05-08T02:37:07.353Z" },
{ url = "https://files.pythonhosted.org/packages/c7/37/7773659b8d8d98b34234e1237352f6b446a3c12941619686c7d4a8a5c69c/ijson-3.4.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfeca1aaa59d93fd0a3718cbe5f7ef0effff85cf837e0bceb71831a47f39cc14", size = 67767, upload-time = "2025-05-08T02:37:08.587Z" },
{ url = "https://files.pythonhosted.org/packages/cd/1f/dd52a84ed140e31a5d226cd47d98d21aa559aead35ef7bae479eab4c494c/ijson-3.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:7ca72ca12e9a1dd4252c97d952be34282907f263f7e28fcdff3a01b83981e837", size = 53864, upload-time = "2025-05-08T02:37:10.044Z" },
]
[[package]] [[package]]
name = "itsdangerous" name = "itsdangerous"
version = "2.2.0" version = "2.2.0"
@@ -793,6 +860,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/8b/a3/3696ff2444658053c01b6b7443e761f28bb71217d82bb89137a978c5f66f/langchain_text_splitters-0.3.8-py3-none-any.whl", hash = "sha256:e75cc0f4ae58dcf07d9f18776400cf8ade27fadd4ff6d264df6278bb302f6f02", size = 32440, upload-time = "2025-04-04T14:03:50.6Z" }, { url = "https://files.pythonhosted.org/packages/8b/a3/3696ff2444658053c01b6b7443e761f28bb71217d82bb89137a978c5f66f/langchain_text_splitters-0.3.8-py3-none-any.whl", hash = "sha256:e75cc0f4ae58dcf07d9f18776400cf8ade27fadd4ff6d264df6278bb302f6f02", size = 32440, upload-time = "2025-04-04T14:03:50.6Z" },
] ]
[[package]]
name = "langfuse"
version = "2.51.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "backoff" },
{ name = "httpx" },
{ name = "idna" },
{ name = "packaging" },
{ name = "pydantic" },
{ name = "wrapt" },
]
sdist = { url = "https://files.pythonhosted.org/packages/f8/36/5e9fdba36908ca7757d876de1163e857bf6a4e56b860e9dc501c8cb33236/langfuse-2.51.3.tar.gz", hash = "sha256:ccd2109556ee232db717abfb751ee8a3139f074db7d3e06a4f1a756c349fc5ba", size = 117431, upload-time = "2024-10-03T08:19:33.814Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5c/23/8eb8f84f15e9fcd26e8e8404deb0579e681ef87835287a4238c2d24aaee2/langfuse-2.51.3-py3-none-any.whl", hash = "sha256:32aba050123656ec0c165583e1d33243cc7a14e7b8498ed3c9de808aa90306f1", size = 214137, upload-time = "2024-10-03T08:19:31.687Z" },
]
[[package]] [[package]]
name = "langsmith" name = "langsmith"
version = "0.3.45" version = "0.3.45"
@@ -1440,10 +1525,12 @@ dependencies = [
{ name = "flask" }, { name = "flask" },
{ name = "gevent" }, { name = "gevent" },
{ name = "gunicorn" }, { name = "gunicorn" },
{ name = "ijson" },
{ name = "jieba" }, { name = "jieba" },
{ name = "langchain" }, { name = "langchain" },
{ name = "langchain-community" }, { name = "langchain-community" },
{ name = "langchain-openai" }, { name = "langchain-openai" },
{ name = "langfuse" },
{ name = "markdownify" }, { name = "markdownify" },
{ name = "openpyxl" }, { name = "openpyxl" },
{ name = "pandas" }, { name = "pandas" },
@@ -1466,10 +1553,12 @@ requires-dist = [
{ name = "flask", specifier = ">=3.1.1" }, { name = "flask", specifier = ">=3.1.1" },
{ name = "gevent", specifier = ">=25.5.1" }, { name = "gevent", specifier = ">=25.5.1" },
{ name = "gunicorn", specifier = ">=23.0.0" }, { name = "gunicorn", specifier = ">=23.0.0" },
{ name = "ijson", specifier = ">=3.4.0" },
{ name = "jieba", specifier = ">=0.42.1" }, { name = "jieba", specifier = ">=0.42.1" },
{ name = "langchain", specifier = ">=0.3.25" }, { name = "langchain", specifier = ">=0.3.25" },
{ name = "langchain-community", specifier = ">=0.3.25" }, { name = "langchain-community", specifier = ">=0.3.25" },
{ name = "langchain-openai", specifier = ">=0.3.24" }, { name = "langchain-openai", specifier = ">=0.3.24" },
{ name = "langfuse", specifier = "==2.51.3" },
{ name = "markdownify", specifier = "==0.13.1" }, { name = "markdownify", specifier = "==0.13.1" },
{ name = "openpyxl", specifier = ">=3.1.5" }, { name = "openpyxl", specifier = ">=3.1.5" },
{ name = "pandas", specifier = ">=2.3.0" }, { name = "pandas", specifier = ">=2.3.0" },
@@ -1777,6 +1866,59 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" }, { url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498, upload-time = "2024-11-08T15:52:16.132Z" },
] ]
[[package]]
name = "wrapt"
version = "1.17.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531, upload-time = "2025-01-14T10:35:45.465Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cd/f7/a2aab2cbc7a665efab072344a8949a71081eed1d2f451f7f7d2b966594a2/wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58", size = 53308, upload-time = "2025-01-14T10:33:33.992Z" },
{ url = "https://files.pythonhosted.org/packages/50/ff/149aba8365fdacef52b31a258c4dc1c57c79759c335eff0b3316a2664a64/wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", size = 38488, upload-time = "2025-01-14T10:33:35.264Z" },
{ url = "https://files.pythonhosted.org/packages/65/46/5a917ce85b5c3b490d35c02bf71aedaa9f2f63f2d15d9949cc4ba56e8ba9/wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", size = 38776, upload-time = "2025-01-14T10:33:38.28Z" },
{ url = "https://files.pythonhosted.org/packages/ca/74/336c918d2915a4943501c77566db41d1bd6e9f4dbc317f356b9a244dfe83/wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", size = 83776, upload-time = "2025-01-14T10:33:40.678Z" },
{ url = "https://files.pythonhosted.org/packages/09/99/c0c844a5ccde0fe5761d4305485297f91d67cf2a1a824c5f282e661ec7ff/wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", size = 75420, upload-time = "2025-01-14T10:33:41.868Z" },
{ url = "https://files.pythonhosted.org/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", size = 83199, upload-time = "2025-01-14T10:33:43.598Z" },
{ url = "https://files.pythonhosted.org/packages/9d/4b/71996e62d543b0a0bd95dda485219856def3347e3e9380cc0d6cf10cfb2f/wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", size = 82307, upload-time = "2025-01-14T10:33:48.499Z" },
{ url = "https://files.pythonhosted.org/packages/39/35/0282c0d8789c0dc9bcc738911776c762a701f95cfe113fb8f0b40e45c2b9/wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", size = 75025, upload-time = "2025-01-14T10:33:51.191Z" },
{ url = "https://files.pythonhosted.org/packages/4f/6d/90c9fd2c3c6fee181feecb620d95105370198b6b98a0770cba090441a828/wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", size = 81879, upload-time = "2025-01-14T10:33:52.328Z" },
{ url = "https://files.pythonhosted.org/packages/8f/fa/9fb6e594f2ce03ef03eddbdb5f4f90acb1452221a5351116c7c4708ac865/wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", size = 36419, upload-time = "2025-01-14T10:33:53.551Z" },
{ url = "https://files.pythonhosted.org/packages/47/f8/fb1773491a253cbc123c5d5dc15c86041f746ed30416535f2a8df1f4a392/wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", size = 38773, upload-time = "2025-01-14T10:33:56.323Z" },
{ url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799, upload-time = "2025-01-14T10:33:57.4Z" },
{ url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821, upload-time = "2025-01-14T10:33:59.334Z" },
{ url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919, upload-time = "2025-01-14T10:34:04.093Z" },
{ url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721, upload-time = "2025-01-14T10:34:07.163Z" },
{ url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899, upload-time = "2025-01-14T10:34:09.82Z" },
{ url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222, upload-time = "2025-01-14T10:34:11.258Z" },
{ url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707, upload-time = "2025-01-14T10:34:12.49Z" },
{ url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685, upload-time = "2025-01-14T10:34:15.043Z" },
{ url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567, upload-time = "2025-01-14T10:34:16.563Z" },
{ url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672, upload-time = "2025-01-14T10:34:17.727Z" },
{ url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865, upload-time = "2025-01-14T10:34:19.577Z" },
{ url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800, upload-time = "2025-01-14T10:34:21.571Z" },
{ url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824, upload-time = "2025-01-14T10:34:22.999Z" },
{ url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920, upload-time = "2025-01-14T10:34:25.386Z" },
{ url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690, upload-time = "2025-01-14T10:34:28.058Z" },
{ url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861, upload-time = "2025-01-14T10:34:29.167Z" },
{ url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174, upload-time = "2025-01-14T10:34:31.702Z" },
{ url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721, upload-time = "2025-01-14T10:34:32.91Z" },
{ url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763, upload-time = "2025-01-14T10:34:34.903Z" },
{ url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585, upload-time = "2025-01-14T10:34:36.13Z" },
{ url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676, upload-time = "2025-01-14T10:34:37.962Z" },
{ url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871, upload-time = "2025-01-14T10:34:39.13Z" },
{ url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312, upload-time = "2025-01-14T10:34:40.604Z" },
{ url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062, upload-time = "2025-01-14T10:34:45.011Z" },
{ url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155, upload-time = "2025-01-14T10:34:47.25Z" },
{ url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471, upload-time = "2025-01-14T10:34:50.934Z" },
{ url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208, upload-time = "2025-01-14T10:34:52.297Z" },
{ url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339, upload-time = "2025-01-14T10:34:53.489Z" },
{ url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232, upload-time = "2025-01-14T10:34:55.327Z" },
{ url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476, upload-time = "2025-01-14T10:34:58.055Z" },
{ url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377, upload-time = "2025-01-14T10:34:59.3Z" },
{ url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986, upload-time = "2025-01-14T10:35:00.498Z" },
{ url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750, upload-time = "2025-01-14T10:35:03.378Z" },
{ url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594, upload-time = "2025-01-14T10:35:44.018Z" },
]
[[package]] [[package]]
name = "xlsxwriter" name = "xlsxwriter"
version = "3.2.5" version = "3.2.5"