6.7 KiB
6.7 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | |||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 14-robustness-cost | 01 | execute | 1 |
|
true |
|
|
Purpose: 提高系统稳定性,避免 LLM 故障导致整个处理流程失败。 Output: 带重试和降级逻辑的 UnifiedSegmentationStrategy.segment() 方法。
<execution_context> @/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md @/home/starmen1265/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/phases/14-robustness-cost/14-CONTEXT.md @.planning/phases/14-robustness-cost/14-RESEARCH.md @.planning/phases/14-robustness-cost/14-VALIDATION.md @.planning/ROADMAP.md @.planning/REQUIREMENTS.md @.planning/STATE.md@kb_workflow/srt/semantic_engine.py @kb_workflow/srt/corrector.py @kb_workflow/deep_analyzer/__init__.py
From kb_workflow/srt/semantic_engine.py:
class UnifiedSegmentationStrategy:
def __init__(
self,
ai_client: Optional[AIClientProtocol] = None,
fallback_segmenter: Optional['SemanticSegmenter'] = None
):
# Lazy AI Client 初始化
if self.ai_client is None:
try:
from kb_workflow.deep_analyzer import SimpleAIClient
self.ai_client = SimpleAIClient()
if not self.ai_client.api_key:
logger.info("AI API key not configured")
self.ai_client = None
except Exception as e:
logger.warning(f"Failed to initialize AI client: {e}")
self.ai_client = None
def segment(
self,
segments: List,
metadata: dict
) -> List['VideoSegment']:
# AI 不可用,直接使用规则分段
if self.ai_client is None:
logger.info("AI client unavailable, using fallback segmenter")
paragraphs = self.fallback_segmenter.segment(segments)
return [
VideoSegment(title=None, content=para, start_index=0, end_index=0)
for para in paragraphs
]
# 调用 LLM
try:
llm_output = self.ai_client.generate(prompt, max_tokens=8000, disable_reasoning=True)
video_segments = self._parse_result(llm_output, fallback_segments=segments)
return video_segments
except Exception as e:
logger.error(f"LLM segmentation failed: {e}, using fallback")
paragraphs = self.fallback_segmenter.segment(segments)
return [VideoSegment(title=None, content=para, start_index=0, end_index=0) for para in paragraphs]
From kb_workflow/deep_analyzer/__init__.py (SimpleAIClient 重试模式):
- SimpleAIClient 已有内置重试逻辑 (max_retries=3)
- 使用 requests 库进行 HTTP 调用
- 可能抛出的异常: ConnectionError, Timeout, HTTPError
1. _is_recoverable_error() 静态方法:
- 导入 requests.exceptions (ConnectionError, Timeout, HTTPError)
- 判断异常类型和状态码
- 返回 bool
2. 修改 segment() 方法的 LLM 调用部分:
- 添加 for 循环 (max_attempts = 2)
- 在 try-except 中捕获异常
- 检查是否可恢复且还有重试机会
- 可恢复: logger.info 重试, continue
- 不可恢复或最后一次: logger.warning 降级原因, break
3. 改进日志记录:
- 重试: info 级别, "LLM call failed (attempt 1/2): {error}, retrying..."
- 降级: warning 级别, "{error_type}: {error_message}, 降级到规则分段"
遵守用户决策: 重试 1 次, 仅可恢复错误重试, 立即重试。
pytest tests/test_semantic_robustness.py::test_llm_failure_fallback -x
- _is_recoverable_error() 方法正确识别可恢复/不可恢复错误
- LLM 调用失败时重试 1 次(可恢复错误)或直接降级(不可恢复错误)
- 降级时记录具体的错误类型和消息 (warning 级别)
- AI 不可用时 (ai_client is None) 直接使用规则分段,无重试
## 整体验证标准
- 功能验证: LLM 调用失败时系统仍能返回分段结果(使用规则分段)
- 重试验证: 可恢复错误(网络错误、超时、限流)触发重试
- 降级验证: 不可恢复错误(API 错误、解析失败)直接降级,不重试
- 日志验证: 降级时记录具体原因,便于问题诊断
运行完整测试套件:
python3 -m pytest tests/test_semantic_robustness.py::test_llm_failure_fallback -v -x
<success_criteria>
- LLM 调用失败时自动降级到规则分段,不中断处理流程
- 可恢复错误(网络、超时、限流)重试 1 次后降级
- 不可恢复错误(API 错误、解析失败)直接降级,不浪费配额
- AI 客户端未配置时直接使用规则分段,无 LLM 调用
- 降级时记录 warning 级别日志,包含错误类型和原因
- 所有测试通过 </success_criteria>