Files
ChouJuGEO/docs/analysis/TAB1_CODE_REVIEW.md
T

529 lines
16 KiB
Markdown
Raw Normal View History

# Tab 1:关键词蒸馏 - 代码逻辑与 AI 提示词全面检查报告
> **检查日期**2026-01-28
> **检查范围**:Tab 1 完整代码逻辑、AI 提示词、错误处理、边界条件
> **检查维度**:逻辑正确性、提示词质量、错误处理、性能、用户体验
---
## 📋 目录
1. [代码逻辑检查](#代码逻辑检查)
2. [AI 提示词检查](#ai-提示词检查)
3. [错误处理检查](#错误处理检查)
4. [边界条件检查](#边界条件检查)
5. [性能问题检查](#性能问题检查)
6. [用户体验问题检查](#用户体验问题检查)
7. [修复建议清单](#修复建议清单)
---
## 代码逻辑检查
### ✅ 正常逻辑
#### 1. 模式选择逻辑
- **位置**:第 932-940 行
- **状态**:✅ 正常
- **说明**:正确使用 `st.radio``st.session_state` 管理模式状态
#### 2. 词库初始化逻辑
- **位置**:第 944-952 行
- **状态**:✅ 正常
- **说明**:正确检查 `wordbanks` 是否为 None 并初始化
#### 3. 组合模式选择逻辑
- **位置**:第 954-981 行
- **状态**:✅ 正常
- **说明**:正确处理多选和默认值
#### 4. 词库编辑逻辑
- **位置**:第 993-1043 行
- **状态**:✅ 正常
- **说明**:横向展示、单列更新、批量更新逻辑正确
### ⚠️ 潜在问题
#### 1. 词库编辑 - 状态同步问题
- **位置**:第 1000-1026 行
- **问题**`edited_wordbanks` 在循环中收集,但如果在循环中点击"更新"按钮,可能导致状态不一致
- **影响**:中等
- **建议**:在循环外统一处理更新逻辑
#### 2. 生成控制 - 禁用条件判断
- **位置**:第 1098-1105 行
- **问题**:托词工具模式的禁用条件检查了 `selected_patterns`,但如果用户刚切换模式,可能还未初始化
- **影响**:低
- **建议**:确保在检查前已初始化
#### 3. 混合模式 - 空关键词处理
- **位置**:第 1270-1286 行
- **问题**:如果 `raw_keywords` 为空,直接赋值给 `keywords`,但后续清理逻辑可能有问题
- **影响**:低
- **建议**:添加空值检查
#### 4. 语义扩展 - 状态管理
- **位置**:第 1452-1496 行
- **问题**:扩展后直接修改 `st.session_state.keywords`,但未检查扩展前是否有扩展关键词
- **影响**:中等
- **建议**:在扩展前保存原始关键词列表
#### 5. 话题集群 - 重复实例化
- **位置**:第 1586 行
- **问题**:每次点击都创建新的 `TopicCluster()` 实例,可能浪费资源
- **影响**:低
- **建议**:考虑缓存实例
#### 6. 智能挖掘 - 重复实例化
- **位置**:第 1852 行
- **问题**:每次展开都创建新的 `KeywordMining()` 实例
- **影响**:低
- **建议**:考虑缓存实例
---
## AI 提示词检查
### 1. AI 生成模式提示词
**位置**:第 1152-1169 行
**当前提示词**
```
你是AI领域GEO专家,目标是提升品牌在大模型自然回答中的提及率。
【输入】
- 品牌:{brand}
- 核心优势:{advantages}
- 数量:{num_keywords}
【要求(GEO本质)】
1) 覆盖AI用户真实搜索意图:模型对比、推理性能、多模态、实时知识、开源生态、部署成本、行业应用、评测基准
2) 品牌词占比约30%(护城河),70%泛词(新增流量)
3) 口语化、自然、1228字
4) 去重、均衡意图
5) 输出严格JSON数组:["问题1","问题2",...]
【开始输出JSON数组】
```
**问题分析**
1.**硬编码行业示例**
- 问题:要求中硬编码了"模型对比、推理性能、多模态"等 AI 领域示例
- 影响:如果用户是其他行业(如外贸ERP),这些示例不适用
- 建议:根据 `advantages` 动态生成示例,或使用更通用的描述
2. ⚠️ **输出格式不够明确**
- 问题:只说"严格JSON数组",但未说明如何处理解析失败
- 影响:代码中已有 fallback`extract_json_array`),但提示词未说明
- 建议:明确说明输出格式,并说明如果格式错误会如何处理
3.**其他要求清晰**
- 品牌词占比、长度、口语化等要求明确
**改进建议**
```python
keyword_prompt = PromptTemplate.from_template(
"""
你是GEOGenerative Engine Optimization)专家,目标是提升品牌在大模型自然回答中的提及率。
【输入】
- 品牌:{brand}
- 核心优势:{advantages}
- 数量:{num_keywords}
【GEO核心要求】
1) 覆盖用户真实搜索意图:
- 根据品牌和优势,识别用户可能的搜索场景(对比、评测、使用、购买、问题等)
- 关键词应反映用户真实需求,而非营销术语
2) 品牌词占比策略:
- 约30%包含品牌词(建立护城河,提升品牌提及率)
- 约70%为泛词(扩大覆盖面,获取新流量)
- 品牌词应自然融入,避免生硬拼接
3) 表达要求:
- 口语化、自然、符合用户搜索习惯
- 长度控制在 12-28 字
- 避免过于正式或营销化
4) 多样性要求:
- 去重:避免生成相同或过于相似的关键词
- 均衡意图:覆盖不同搜索意图(对比、评测、使用、购买、问题等)
- 多样化表达:使用不同的表达方式
【输出格式】
请严格按照以下 JSON 数组格式输出,不要添加任何其他内容:
["关键词1", "关键词2", "关键词3", ...]
如果无法生成 JSON 格式,请每行输出一个关键词(纯文本格式)。
【开始生成】
"""
)
```
---
### 2. 语义扩展提示词
**位置**`modules/semantic_expander.py` 第 18-95 行
**当前提示词**:✅ 质量较高
**优点**
- 结构清晰,分层次说明
- 包含具体示例
- 输出格式明确(JSON
- 扩展策略详细
**潜在问题**
1. ⚠️ **扩展数量控制**
- 问题:提示词中要求扩展 `{expansion_count}` 个,但实际可能生成更多或更少
- 影响:需要代码层面控制数量
- 建议:在提示词中明确说明"至少生成 N 个,可以生成更多"
2.**其他方面良好**
---
### 3. 话题集群提示词
**位置**`modules/topic_cluster.py` 第 20-89 行
**当前提示词**:✅ 质量较高
**优点**
- 聚类要求明确
- 输出格式详细
- 包含统计信息要求
**潜在问题**
1. ⚠️ **聚类数量控制**
- 问题:要求生成 `{cluster_count}` 个集群,但实际可能生成不同数量
- 影响:需要代码层面验证
- 建议:在提示词中说明"尽量生成 N 个,如果关键词不足以支撑 N 个集群,可以生成更少"
---
### 4. 关键词挖掘提示词
**位置**`modules/keyword_mining.py` 第 51-89 行
**当前提示词**:✅ 质量较高
**优点**
- 任务说明清晰
- 输出格式明确
- 包含示例
**潜在问题**
1. ⚠️ **行业通用性**
- 问题:提示词中使用了 `{industry}` 变量,但示例中硬编码了"软件"
- 影响:对于非软件行业可能不适用
- 建议:使用更通用的示例或动态生成
---
### 5. 混合模式润色提示词
**位置**`modules/keyword_tool.py` 第 159-173 行
**当前提示词**
```
你是关键词优化专家。请将以下关键词润色为更自然、更符合用户搜索习惯的表达。
{"品牌:" + brand if brand else ""}
原始关键词列表:
{json.dumps(keywords_to_polish, ensure_ascii=False, indent=2)}
要求:
1) 保持原意,但表达更自然、口语化
2) 长度控制在 12-28 字
3) 去除生硬拼接感
4) 输出 JSON 数组格式:["润色后的关键词1", "润色后的关键词2", ...]
只输出 JSON 数组,不要其他内容。
```
**问题分析**
1. ⚠️ **品牌信息格式不一致**
- 问题:使用 `{"品牌:" + brand if brand else ""}` 这种 Python 表达式,但实际在模板中可能无法正确解析
- 影响:品牌信息可能无法正确传递
- 建议:使用模板变量 `{brand}` 并在调用时处理
2.**其他要求清晰**
**改进建议**
```python
polish_prompt = f"""你是关键词优化专家。请将以下关键词润色为更自然、更符合用户搜索习惯的表达。
{f'品牌:{brand}' if brand else ''}
原始关键词列表:
{json.dumps(keywords_to_polish, ensure_ascii=False, indent=2)}
要求:
1) 保持原意,但表达更自然、口语化
2) 长度控制在 12-28 字
3) 去除生硬拼接感
4) 输出 JSON 数组格式:["润色后的关键词1", "润色后的关键词2", ...]
只输出 JSON 数组,不要其他内容。
"""
```
---
## 错误处理检查
### ✅ 已处理的错误
1. **AI 生成模式 - JSON 解析失败**
- **位置**:第 1185-1196 行
- **处理**:使用 `try-except` 捕获,fallback 到文本解析
- **状态**:✅ 良好
2. **词库导入 - JSON 解析失败**
- **位置**:第 1066-1074 行
- **处理**:使用 `try-except` 捕获并显示错误
- **状态**:✅ 良好
3. **数据库保存失败**
- **位置**:第 1325-1328 行
- **处理**:使用 `try-except` 捕获,显示警告但不阻止流程
- **状态**:✅ 良好
### ⚠️ 缺失的错误处理
1. **词库编辑 - 空词库检查**
- **位置**:第 1008 行
- **问题**:如果 `wordbanks.get(bank_type, [])` 返回空列表,text_area 会显示空,但未提示用户
- **建议**:添加空词库提示
2. **语义扩展 - LLM 调用失败**
- **位置**:第 1458-1496 行
- **问题**:虽然有 `try-except`,但错误信息不够详细
- **建议**:区分不同类型的错误(网络错误、API 错误、解析错误等)
3. **话题集群 - 可视化失败**
- **位置**:第 1664-1748 行
- **问题**:虽然有 `try-except`,但错误信息不够详细
- **建议**:提供更详细的错误信息
4. **智能挖掘 - 空结果处理**
- **位置**:第 1878-1896 行
- **问题**:如果 `mined_keywords` 为空,只显示警告,但未说明原因
- **建议**:提供更详细的失败原因
---
## 边界条件检查
### ✅ 已处理的边界条件
1. **空关键词列表**
- **位置**:第 1414 行
- **处理**:使用 `if st.session_state.keywords:` 检查
- **状态**:✅ 良好
2. **空词库检查**
- **位置**:第 1216-1222 行、第 1252-1258 行
- **处理**:在生成前检查空词库
- **状态**:✅ 良好
3. **空组合模式检查**
- **位置**:第 1100-1103 行、第 1363-1371 行
- **处理**:检查 `selected_patterns` 是否为空
- **状态**:✅ 良好
### ⚠️ 未处理的边界条件
1. **关键词数量为 0**
- **位置**:第 1310 行
- **问题**:如果 `cleaned` 为空列表,会进入错误处理,但未检查 `st.session_state.kw_last_num` 是否为 0
- **建议**:添加数量为 0 的检查
2. **扩展数量超过关键词数量**
- **位置**:第 1423-1430 行
- **问题**:如果 `expansion_count` 大于现有关键词数量,可能导致扩展效果不佳
- **建议**:添加合理性检查
3. **话题集群数量大于关键词数量**
- **位置**:第 1567-1574 行
- **问题**:如果 `cluster_count` 大于关键词数量,可能导致聚类失败
- **建议**:添加合理性检查
4. **搜索词为空字符串**
- **位置**:第 1797-1798 行
- **问题**:如果 `search_term` 为空字符串(非 None),会匹配所有关键词
- **建议**:添加空字符串检查
---
## 性能问题检查
### ⚠️ 潜在性能问题
1. **词库编辑 - 每次渲染都处理**
- **位置**:第 1002-1018 行
- **问题**:在循环中每次都处理 `edited_wordbanks`,即使未点击更新
- **影响**:低(但可以优化)
- **建议**:只在点击更新时处理
2. **话题集群 - 重复创建实例**
- **位置**:第 1586 行
- **问题**:每次点击都创建新实例
- **影响**:低
- **建议**:考虑缓存实例
3. **智能挖掘 - 重复创建实例**
- **位置**:第 1852 行
- **问题**:每次展开都创建新实例
- **影响**:低
- **建议**:考虑缓存实例
4. **语义扩展 - 重复创建实例**
- **位置**:第 1459 行、第 1529 行
- **问题**:每次调用都创建新实例
- **影响**:低
- **建议**:考虑缓存实例
5. **关键词列表 - 分页计算**
- **位置**:第 1804-1815 行
- **问题**:每次渲染都计算分页,但可以优化
- **影响**:极低
- **建议**:可以接受
---
## 用户体验问题检查
### ✅ 良好的用户体验
1. **进度条和状态提示**
- **位置**:第 1176-1202 行、第 1206-1238 行、第 1242-1293 行
- **状态**:✅ 良好
2. **错误提示详细**
- **位置**:第 1331-1412 行
- **状态**:✅ 良好
3. **搜索和筛选功能**
- **位置**:第 1788-1801 行
- **状态**:✅ 良好
### ⚠️ 可改进的用户体验
1. **词库编辑 - 缺少保存提示**
- **位置**:第 1021-1026 行
- **问题**:点击"更新"后只显示成功提示,但未提示用户需要重新生成关键词
- **建议**:添加提示"词库已更新,建议重新生成关键词以应用新词库"
2. **语义扩展 - 缺少撤销功能**
- **位置**:第 1476-1492 行
- **问题**:扩展后直接修改关键词列表,无法撤销
- **建议**:添加撤销功能或确认对话框
3. **话题集群 - 缺少重新生成选项**
- **位置**:第 1585-1624 行
- **问题**:如果用户不满意结果,需要手动清空后重新生成
- **建议**:添加"重新生成"按钮
4. **智能挖掘 - 缺少批量添加**
- **位置**:第 1912-1917 行
- **问题**:只能逐个添加关键词,效率低
- **建议**:添加"全选"和"批量添加"功能
---
## 修复建议清单
### 🔴 P0 - 必须修复(逻辑错误/严重问题)
1. **AI 生成提示词 - 硬编码行业示例**
- **位置**:第 1162 行
- **修复**:移除硬编码示例,使用通用描述或动态生成
- **优先级**:高
2. **混合模式润色提示词 - 品牌信息格式**
- **位置**`modules/keyword_tool.py` 第 161 行
- **修复**:使用正确的模板变量格式
- **优先级**:高
3. **搜索词空字符串检查**
- **位置**:第 1797-1798 行
- **修复**:添加空字符串检查
- **优先级**:中
### 🟡 P1 - 建议修复(体验优化)
4. **词库编辑 - 状态同步优化**
- **位置**:第 1000-1026 行
- **修复**:优化更新逻辑,避免状态不一致
- **优先级**:中
5. **语义扩展 - 保存原始关键词**
- **位置**:第 1458-1496 行
- **修复**:在扩展前保存原始关键词列表
- **优先级**:中
6. **错误处理 - 更详细的错误信息**
- **位置**:多处
- **修复**:区分不同类型的错误,提供更详细的错误信息
- **优先级**:中
7. **边界条件 - 数量合理性检查**
- **位置**:第 1423-1430 行、第 1567-1574 行
- **修复**:添加扩展数量和集群数量的合理性检查
- **优先级**:低
### 🟢 P2 - 可选优化(性能/体验)
8. **实例缓存优化**
- **位置**:第 1459 行、第 1529 行、第 1586 行、第 1852 行
- **修复**:考虑缓存实例,避免重复创建
- **优先级**:低
9. **用户体验优化**
- **位置**:多处
- **修复**:添加撤销功能、批量操作、重新生成选项等
- **优先级**:低
---
## 总结
### 整体评价
**代码质量**:⭐⭐⭐⭐☆(4/5
- 逻辑清晰,结构合理
- 错误处理基本完善
- 用户体验良好
**提示词质量**:⭐⭐⭐⭐☆(4/5
- 大部分提示词质量较高
- 部分提示词需要优化(硬编码、格式问题)
**需要优先修复的问题**
1. AI 生成提示词的硬编码行业示例
2. 混合模式润色提示词的品牌信息格式
3. 搜索词空字符串检查
**建议优化方向**
1. 提升错误处理的详细程度
2. 添加更多边界条件检查
3. 优化用户体验(撤销、批量操作等)
---
**报告版本**v1.0
**最后更新**2026-01-28
**下一步**:根据优先级修复 P0 和 P1 问题