fix(kb-deep-analyzer): 添加进度日志和超时追踪

- SimpleAIClient.generate(): 添加 AI 调用开始/结束日志
- _analyze_chunk(): 添加分片分析耗时日志
- _analyze_chunks_concurrent(): 添加批次进度日志和总耗时统计
- 便于排查卡住问题和监控进度
This commit is contained in:
2026-02-13 15:49:17 +08:00
parent c276df2d37
commit 99164f7ce6
2 changed files with 85 additions and 21 deletions
+45 -9
View File
@@ -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}段内容分析"