fix(kb-deep-analyzer): 添加进度日志和超时追踪
- SimpleAIClient.generate(): 添加 AI 调用开始/结束日志 - _analyze_chunk(): 添加分片分析耗时日志 - _analyze_chunks_concurrent(): 添加批次进度日志和总耗时统计 - 便于排查卡住问题和监控进度
This commit is contained in:
@@ -238,7 +238,7 @@ class SimpleAIClient:
|
||||
self.max_retries = 3 # 最大重试次数
|
||||
self.max_concurrent = 3 # 最大并发数
|
||||
|
||||
def generate(self, prompt: str, max_tokens: int = 1000) -> str:
|
||||
def generate(self, prompt: str, max_tokens: int = 1000, task_info: str = None) -> str:
|
||||
"""生成文本,支持重试"""
|
||||
# 每次调用时重新读取环境变量,解决 exec 传递问题
|
||||
api_key = os.environ.get("AI_API_KEY", self.api_key)
|
||||
@@ -249,24 +249,35 @@ class SimpleAIClient:
|
||||
if not api_key:
|
||||
raise ValueError("AI_API_KEY 未设置,请配置环境变量")
|
||||
|
||||
task_desc = f"[{task_info}]" if task_info else ""
|
||||
|
||||
last_error = None
|
||||
for attempt in range(self.max_retries):
|
||||
try:
|
||||
import time
|
||||
start_time = time.time()
|
||||
print(f"[AI Client] {task_desc} 开始调用 AI...")
|
||||
|
||||
if provider == "openai":
|
||||
return self._call_openai(prompt, max_tokens, api_key, model, base_url)
|
||||
result = self._call_openai(prompt, max_tokens, api_key, model, base_url)
|
||||
elif provider == "zhipu":
|
||||
return self._call_zhipu(prompt, max_tokens, api_key, model, base_url)
|
||||
result = self._call_zhipu(prompt, max_tokens, api_key, model, base_url)
|
||||
elif provider == "minimax":
|
||||
return self._call_minimax(prompt, max_tokens, api_key, model, base_url)
|
||||
result = self._call_minimax(prompt, max_tokens, api_key, model, base_url)
|
||||
else:
|
||||
raise ValueError(f"不支持的 AI 提供商: {provider}")
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
print(f"[AI Client] {task_desc} AI 调用完成,耗时: {elapsed:.2f}秒")
|
||||
return result
|
||||
except Exception as e:
|
||||
elapsed = time.time() - start_time if 'start_time' in dir() else 0
|
||||
last_error = e
|
||||
if attempt < self.max_retries - 1:
|
||||
print(f"[AI Client] 第 {attempt + 1} 次调用失败,{self.max_retries - attempt - 1} 次重试剩余: {e}")
|
||||
print(f"[AI Client] {task_desc} 第 {attempt + 1} 次调用失败 ({elapsed:.2f}秒),{self.max_retries - attempt - 1} 次重试剩余: {e}")
|
||||
continue
|
||||
else:
|
||||
print(f"[AI Client] 调用失败,已重试 {self.max_retries} 次: {e}")
|
||||
print(f"[AI Client] {task_desc} 调用失败,已重试 {self.max_retries} 次: {e}")
|
||||
raise
|
||||
|
||||
def generate_json(self, prompt: str) -> Dict[str, Any]:
|
||||
@@ -745,6 +756,9 @@ class DeepAnalyzer:
|
||||
|
||||
print(f"[DeepAnalyzer] 分块: {num_chunks} 段,批次大小: {batch_size}")
|
||||
|
||||
import time
|
||||
total_start_time = time.time()
|
||||
|
||||
# 批处理执行
|
||||
batch_results = {} # 存储各批结果
|
||||
all_summaries = []
|
||||
@@ -756,7 +770,9 @@ class DeepAnalyzer:
|
||||
batch_chunks = chunks[batch_idx:batch_end]
|
||||
batch_times = chunk_times[batch_idx:batch_end]
|
||||
|
||||
print(f"[DeepAnalyzer] 批次 {batch_num}/{total_batches}: 段 {batch_idx+1}-{batch_end}")
|
||||
batch_start_time = time.time()
|
||||
print(f"[DeepAnalyzer] === 批次 {batch_num}/{total_batches} 开始 ===")
|
||||
print(f"[DeepAnalyzer] 段 {batch_idx+1}-{batch_end},预计 {len(batch_chunks)} 个并发调用")
|
||||
|
||||
# 并发执行当前批次
|
||||
batch_tasks = [(i, batch_chunks[j], batch_times[j][0], batch_times[j][1])
|
||||
@@ -766,8 +782,10 @@ class DeepAnalyzer:
|
||||
futures = {executor.submit(self._analyze_chunk, task[1], task[0] + 1, metadata): task[0]
|
||||
for task in batch_tasks}
|
||||
|
||||
completed_in_batch = 0
|
||||
for future in concurrent.futures.as_completed(futures):
|
||||
idx = futures[future]
|
||||
completed_in_batch += 1
|
||||
try:
|
||||
summary = future.result()
|
||||
batch_results[idx] = {
|
||||
@@ -776,7 +794,8 @@ class DeepAnalyzer:
|
||||
'end_time': chunk_times[idx][1],
|
||||
'summary': summary
|
||||
}
|
||||
print(f"[DeepAnalyzer] 段 {idx + 1}/{num_chunks} 完成")
|
||||
elapsed = time.time() - batch_start_time
|
||||
print(f"[DeepAnalyzer] 段 {idx + 1}/{num_chunks} 完成 ({completed_in_batch}/{len(batch_chunks)}), 批次耗时: {elapsed:.2f}秒")
|
||||
except Exception as e:
|
||||
print(f"[DeepAnalyzer] 段 {idx + 1} 失败: {e}")
|
||||
batch_results[idx] = {
|
||||
@@ -792,12 +811,23 @@ class DeepAnalyzer:
|
||||
on_segment_complete(batch_summaries)
|
||||
|
||||
all_summaries.extend(batch_summaries)
|
||||
|
||||
batch_elapsed = time.time() - batch_start_time
|
||||
print(f"[DeepAnalyzer] === 批次 {batch_num}/{total_batches} 完成,耗时: {batch_elapsed:.2f}秒 ===")
|
||||
|
||||
total_elapsed = time.time() - total_start_time
|
||||
print(f"[DeepAnalyzer] 所有分块分析完成,总耗时: {total_elapsed:.2f}秒")
|
||||
|
||||
# 按顺序整理结果
|
||||
all_summaries = [all_summaries[i] for i in range(len(all_summaries))]
|
||||
|
||||
# 合并结果
|
||||
print(f"[DeepAnalyzer] 开始合并各段摘要...")
|
||||
merge_start = time.time()
|
||||
result = self._merge_summaries(all_summaries, title)
|
||||
merge_elapsed = time.time() - merge_start
|
||||
print(f"[DeepAnalyzer] 摘要合并完成,耗时: {merge_elapsed:.2f}秒")
|
||||
|
||||
result.timeline = self._build_timeline_from_chunks(all_summaries)
|
||||
|
||||
return result
|
||||
@@ -884,7 +914,13 @@ class DeepAnalyzer:
|
||||
请用中文详细回答,包括核心主题、关键要点和重要细节。"""
|
||||
|
||||
try:
|
||||
return self.ai_client.generate(prompt, max_tokens=2000)
|
||||
import time
|
||||
start_time = time.time()
|
||||
print(f"[DeepAnalyzer] 开始分析分片 {chunk_index}...")
|
||||
result = self.ai_client.generate(prompt, max_tokens=2000, task_info=f"分片 {chunk_index}")
|
||||
elapsed = time.time() - start_time
|
||||
print(f"[DeepAnalyzer] 分片 {chunk_index} 分析完成,耗时: {elapsed:.2f}秒")
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"[DeepAnalyzer] 分片 {chunk_index} 分析失败: {e}")
|
||||
return f"第{chunk_index}段内容分析"
|
||||
|
||||
Reference in New Issue
Block a user