diff --git a/.planning/debug/resolved/deep-analyzer-wrong-output.md b/.planning/debug/resolved/deep-analyzer-wrong-output.md new file mode 100644 index 0000000..5000c02 --- /dev/null +++ b/.planning/debug/resolved/deep-analyzer-wrong-output.md @@ -0,0 +1,146 @@ +--- +status: awaiting_human_verify +trigger: "DeepAnalyzer: (1) 禁用思考模式后准确性下降(鲜合器→银河系),(2) 摘要部分只是重复开头文字需移除,(3) 元数据 title/author 仍不正确" +created: 2026-03-20T00:00:00Z +updated: 2026-03-21T02:45:00Z +--- + +## Current Focus + +hypothesis: | + **修复已完成,单元测试通过,等待用户端到端验证** + + 修复1: 移除 thinking.type="disabled" 参数 + - 文件:kb_workflow/deep_analyzer/__init__.py (第91-122行) + - 修改:移除 `"thinking": {"type": "disabled"}` 参数 + - 效果:AI 将使用默认思考模式,提高 ASR 纠错准确性 + + 修复2: SRTProcessor metadata 扁平化 + - 文件:kb_workflow/pipeline/processors/srt.py (第162-195行) + - 修改:添加扁平化逻辑,处理嵌套结构 {metadata: {...}} + - 效果:正确提取 title/author 等元数据字段 + + 修复3: 移除 SRTProcessor 摘要部分 + - 文件:kb_workflow/pipeline/processors/srt.py (第195-230行) + - 修改:移除摘要部分生成代码 + - 效果:不再生成低质量的摘要部分 + + 修复4: duration 字段类型处理 + - 文件:kb_workflow/pipeline/processors/srt.py (第276-284行) + - 修改:添加类型检查,支持字符串和整数格式 + - 效果:正确处理 "05:42" 字符串格式的时长 + +test: | + 单元测试通过: + - ✅ metadata 扁平化逻辑正确 + - ✅ frontmatter 生成正确(title, author, bvid 都正确) + - ✅ duration 字段类型处理正确 + + 等待端到端测试: + 1. 重新运行 Bilibili pipeline 处理 BV1MiPSz2ErY + 2. 检查生成的 analysis.md 文件 +expecting: | + 1. ASR纠错准确性提高("银河系"不应被误写为"鲜合器") + 2. 输出不再包含摘要部分 + 3. 元数据正确显示标题:"新研究表明,银心的能量来源可能是暗物质,而非黑洞,【科学快报】第263期" + 4. 元数据正确显示作者:"科学透镜" +next_action: | + 等待用户重新运行 pipeline 并验证结果 + +## Symptoms +expected: | + 1. ASR纠错准确(如"银河系"不会被误写为"鲜合器") + 2. 摘要是真正的总结提炼,不是重复开头文字(或直接移除摘要部分) + 3. 元数据正确显示标题、作者等 +actual: | + 1. 第18行显示"我们的鲜合器其实是被吸引进了一个明天数千万光年..." - 识别错误 + 2. 第8-10行摘要只是重复视频开头文字,非真正总结 + 3. 第2-4行显示 title: "未命名", author: "未知" +errors: | + - ASR纠错准确性下降 + - 摘要质量问题 + - 元数据未正确填充 +reproduction: | + 参考:~/work/zq/30.资源/AI分析/bilibili/20260321_BV1MiPSz2ErY_analysis.md +started: 2026-03-21,用户验证修复后报告新问题 + +## Eliminated + +## Evidence + +[... previous evidence ...] + +- timestamp: 2026-03-21T02:45:00Z + checked: 单元测试结果 + found: | + 1. ✅ metadata 扁平化逻辑正确 + 2. ✅ frontmatter 生成正确 + 3. ✅ title: "新研究表明,银心的能量来源可能是暗物质,而非黑洞,【科学快报】第263期" + 4. ✅ author: "科学透镜" + 5. ✅ bvid: "BV1MiPSz2ErY" + 6. ✅ duration: "05:42" + implication: | + **修复验证:** + 1. metadata 扁平化逻辑正确处理嵌套结构 + 2. frontmatter 生成正确包含所有字段 + 3. duration 类型处理正确(字符串和整数都支持) + +## Resolution + +root_cause: | + 1. **thinking.type=disabled 导致ASR纠错准确性下降** + - SimpleAIClient._call_zhipu() 禁用思考模式 + - 影响 ASRCorrector 纠错质量 + + 2. **SRTProcessor 未扁平化嵌套 metadata 结构** + - metadata.json: {metadata: {title: "xxx", author: "xxx"}} + - SRTProcessor._generate_frontmatter() 直接访问 metadata.get('title') + - 返回 None,使用默认值"未命名" + + 3. **SRTProcessor 自动生成低质量摘要** + - 第219-226行简单复制第一段开头200字符 + - 用户要求移除摘要部分 + + 4. **duration 字段类型处理不当** + - metadata 中 duration 是字符串 "05:42" + - _format_duration 期望整数秒数 + - 导致 TypeError + +fix: | + 1. **kb_workflow/deep_analyzer/__init__.py (第91-122行)** + - 修改 _call_zhipu() 方法 + - 移除 `"thinking": {"type": "disabled"}` 参数 + - 让AI使用默认思考模式以提高准确性 + - 同时处理 reasoning_content 字段作为后备 + + 2. **kb_workflow/pipeline/processors/srt.py (第162-195行)** + - 修改 _load_metadata() 方法 + - 添加扁平化逻辑,与 AnalyzeProcessor._normalize_metadata() 一致 + - 处理嵌套结构 {metadata: {...}} + + 3. **kb_workflow/pipeline/processors/srt.py (第195-230行)** + - 修改 _generate_markdown() 方法 + - 移除摘要部分生成代码(原第219-226行) + + 4. **kb_workflow/pipeline/processors/srt.py (第276-284行)** + - 修改 _generate_frontmatter() 方法 + - 添加 duration 类型检查 + - 支持字符串和整数格式 + +verification: | + 单元验证完成: + 1. ✅ metadata 扁平化逻辑正确 + 2. ✅ frontmatter 生成正确 + 3. ✅ duration 类型处理正确 + 4. ✅ title/author/bvid 都正确显示 + + 等待用户端到端验证: + 1. 重新运行 Bilibili pipeline 处理 BV1MiPSz2ErY + 2. 检查生成的 analysis.md 文件 + 3. 验证 title/author 是否正确显示 + 4. 验证是否不再包含摘要部分 + 5. 验证 ASR 纠错准确性("银河系"不应被误写为"鲜合器") + +files_changed: +- kb_workflow/deep_analyzer/__init__.py (修改 _call_zhipu 方法) +- kb_workflow/pipeline/processors/srt.py (修改 _load_metadata, _generate_markdown, _generate_frontmatter 方法) diff --git a/kb_workflow/deep_analyzer/__init__.py b/kb_workflow/deep_analyzer/__init__.py index 4b06248..974d077 100644 --- a/kb_workflow/deep_analyzer/__init__.py +++ b/kb_workflow/deep_analyzer/__init__.py @@ -95,28 +95,30 @@ class SimpleAIClient: base_url = base_url or "https://open.bigmodel.cn/api/coding/paas/v4" url = f"{base_url}/chat/completions" headers = {"Authorization": f"Bearer {api_key}"} - # GLM-4.5/4.6/4.7/5 默认启用thinking mode,使用 thinking.type 参数禁用 + # GLM-4.5/4.6/4.7/5 默认启用thinking mode + # 移除 thinking.type="disabled",让AI使用默认思考模式以提高准确性 payload = { "model": model, "messages": [{"role": "user", "content": prompt}], - "max_tokens": max_tokens, - "thinking": { - "type": "disabled" # 禁用思考模式,获取直接响应 - } + "max_tokens": max_tokens } response = requests.post(url, headers=headers, json=payload, timeout=600) response.raise_for_status() data = response.json() message = data.get('choices', [{}])[0].get('message', {}) + + # 优先返回 content 字段 content = message.get('content', '') + # 如果 content 为空但有 reasoning_content,使用 reasoning_content if not content: - # 如果仍然为空,检查是否有reasoning_content(用于调试) reasoning = message.get('reasoning_content', '') if reasoning: - print(f"[DEBUG] Zhipu API返回空的content,但有reasoning_content。", file=sys.stderr) - print(f"[DEBUG] 这可能表示thinking.type参数未生效或模型不支持。", file=sys.stderr) + print(f"[DEBUG] Zhipu API返回空的content,使用reasoning_content。", file=sys.stderr) print(f"[DEBUG] reasoning_content前200字符: {reasoning[:200]}", file=sys.stderr) + content = reasoning + + if not content: raise ValueError(f"Zhipu API返回空内容。请检查API配置和模型参数。响应数据: {data}") return content diff --git a/kb_workflow/pipeline/processors/srt.py b/kb_workflow/pipeline/processors/srt.py index 2723e38..ecf7f7a 100644 --- a/kb_workflow/pipeline/processors/srt.py +++ b/kb_workflow/pipeline/processors/srt.py @@ -166,7 +166,7 @@ class SRTProcessor(BaseProcessor): metadata_file: 元数据文件路径 Returns: - 元数据字典 + 元数据字典(扁平化后的) """ path = Path(metadata_file) if not path.exists(): @@ -174,7 +174,21 @@ class SRTProcessor(BaseProcessor): return {} with open(path, 'r', encoding='utf-8') as f: - return json.load(f) + raw_metadata = json.load(f) + + # 扁平化嵌套结构(与 AnalyzeProcessor._normalize_metadata 一致) + if not raw_metadata: + return {} + + # 如果已经是扁平结构(顶层有 title) + if 'title' in raw_metadata: + return raw_metadata + + # 处理嵌套结构 {metadata: {...}, stats: {...}} + if 'metadata' in raw_metadata: + return raw_metadata['metadata'].copy() + + return raw_metadata def _extract_tags(self, paragraphs: List[str]) -> List[str]: """从段落中提取标签 @@ -216,16 +230,7 @@ class SRTProcessor(BaseProcessor): # 构建内容 content_parts = [frontmatter, ""] - # 添加摘要(可选) - if paragraphs: - content_parts.append("## 摘要") - content_parts.append("") - # 使用第一段作为简单摘要 - first_para = paragraphs[0][:200] if len(paragraphs[0]) > 200 else paragraphs[0] - content_parts.append(first_para + ("..." if len(paragraphs[0]) > 200 else "")) - content_parts.append("") - - # 添加内容 + # 直接添加内容,不生成摘要部分 content_parts.append("## 内容") content_parts.append("") for para in paragraphs: @@ -271,7 +276,12 @@ class SRTProcessor(BaseProcessor): # 时长(视频) duration = metadata.get('duration', 0) if duration: - duration_str = self._format_duration(duration) + # 如果 duration 已经是字符串格式(如 "05:42"),直接使用 + # 否则(整数秒数)调用 _format_duration 转换 + if isinstance(duration, str): + duration_str = duration + else: + duration_str = self._format_duration(duration) lines.append(f'duration: {duration_str}') # BVID