Files
ChouJuGEO/modules/config_optimizer.py
T
刘国栋 8f7f082c3d feat: 重构项目结构并添加平台同步基础架构
- 重构项目目录结构,将功能模块移至 modules/ 目录
- 创建平台同步基础架构,包括发布器基类和 GitHub 发布器
- 新增 UI 状态管理模块 (modules/ui/state.py) 统一管理会话状态
- 更新依赖配置,添加平台同步所需依赖 (httpx, pyperclip)
- 整理文档结构,将所有文档分类移至 docs/ 目录
- 添加 .cursorrules 文件定义项目开发规范
- 清理根目录重复文件,保持项目结构整洁
2026-01-30 10:21:29 +08:00

419 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
配置优化助手模块
分析品牌名和优势是否 GEO 友好,提供优化建议
"""
from typing import Dict, List, Optional
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
import json
import re
class ConfigOptimizer:
"""配置优化器"""
def __init__(self):
self.optimization_prompt_template = """
你是GEO(生成式引擎优化)专家,专注于帮助品牌在AI模型中被优先、可信地提及。
【当前配置】
- 主品牌名称:{brand}
- 核心优势/卖点:{advantages}
- 竞品列表:{competitors}
【分析要求】
请从以下维度全面评估当前配置,并给出优化建议:
1. **品牌名独特性分析**
- 是否过于泛化(如"AI助手""智能系统"等通用词)?
- 是否容易被混淆或误认为是其他品牌?
- 是否具有搜索友好性(用户容易搜索到)?
- 是否在AI回答中容易被识别和提及?
2. **优势描述分析**
- 是否具体、可量化(避免"强大""优秀"等模糊词)?
- 是否具有差异化(与竞品有明显区别)?
- 是否包含E-E-A-T信号(专业性、经验性、权威性、可信度)?
- 是否便于AI提取和引用?
3. **竞品对比分析**
- 当前配置在竞品中是否具有明显优势?
- 哪些方面容易被竞品超越?
- 如何强化差异化定位?
4. **GEO友好度评估**
- 品牌名是否容易被AI优先提及?
- 优势描述是否符合GEO最佳实践?
- 整体配置是否有助于提升提及率?
【输出格式】
请严格按照以下格式输出,包含所有部分:
【评估总结】
(200-300字,总结当前配置的优势和不足)
【优化建议】
1. 品牌名优化建议:
- 问题:[指出当前品牌名的问题]
- 建议:[给出优化建议]
2. 优势描述优化建议:
- 问题:[指出当前优势描述的问题]
- 建议:[给出优化建议]
3. 差异化强化建议:
- 竞品对比:[与竞品的对比分析]
- 差异化策略:[如何强化差异化]
【推荐版本】
请提供3个优化后的配置版本(从保守到激进),严格按照以下格式输出,每个字段单独一行:
版本1(保守优化):
品牌名:基于当前品牌名进行保守优化,保持核心品牌名不变
优势描述:优化优势描述,使其更具体、可量化,用顿号分隔多个优势点
理由:说明为什么这样优化,50-100字
版本2(平衡优化):
品牌名:在品牌名中加入行业关键词,提升搜索友好性
优势描述:聚焦核心价值,突出差异化优势,用顿号分隔多个优势点
理由:说明为什么这样优化,50-100字
版本3(激进优化):
品牌名:完全重构品牌定位,突出核心特性,最大化GEO效果
优势描述:全面展示优势,包含多个维度,用顿号分隔多个优势点
理由:说明为什么这样优化,50-100字
格式要求(非常重要,必须严格遵守):
1. 必须严格按照上述格式,每个字段单独一行,使用"品牌名:""优势描述:""理由:"作为字段标识
2. 品牌名必须提供实际内容,不能使用占位符,必须基于当前品牌名"{brand}"进行优化
3. 优势描述必须提供实际内容,不能使用占位符,必须基于当前优势"{advantages}"进行优化
4. 每个版本都必须完整,不能省略任何字段
5. 不要使用方括号[]、不要使用占位符,必须提供针对当前配置的实际优化内容
6. 品牌名和优势描述必须是具体的、可用的内容,不能是说明性文字
【预期效果】
- 提及率提升预期:[预计提升幅度]
- GEO友好度提升:[预计提升幅度]
- 差异化优势:[预计强化效果]
【开始分析】
"""
def optimize_config(self, brand: str, advantages: str, competitors: List[str], llm_chain) -> Dict:
"""
优化配置
Args:
brand: 主品牌名称
advantages: 核心优势/卖点
competitors: 竞品列表
llm_chain: LLM调用链
Returns:
包含优化建议的字典
"""
competitors_str = "".join(competitors) if competitors else ""
prompt = PromptTemplate.from_template(self.optimization_prompt_template)
chain = prompt | llm_chain | StrOutputParser()
try:
result = chain.invoke({
"brand": brand,
"advantages": advantages,
"competitors": competitors_str
})
# 解析结果
parsed_result = self._parse_optimization_result(result)
parsed_result["raw_result"] = result
parsed_result["success"] = True
# 如果推荐版本为空,尝试备用解析方法
if not parsed_result.get("recommended_versions") or all(
not v.get("brand") and not v.get("advantages")
for v in parsed_result.get("recommended_versions", [])
):
# 尝试更宽松的解析
parsed_result = self._parse_optimization_result_fallback(result, parsed_result)
return parsed_result
except Exception as e:
return {
"success": False,
"error": str(e),
"raw_result": ""
}
def _parse_optimization_result(self, result: str) -> Dict:
"""解析优化结果"""
parsed = {
"summary": "",
"suggestions": {
"brand": {"problem": "", "suggestion": ""},
"advantages": {"problem": "", "suggestion": ""},
"differentiation": {"comparison": "", "strategy": ""}
},
"recommended_versions": [],
"expected_effects": {},
"parse_errors": [] # 记录解析过程中的错误
}
# 提取评估总结
if "【评估总结】" in result:
summary_section = result.split("【评估总结】")[1].split("")[0].strip()
parsed["summary"] = summary_section
# 提取优化建议
if "【优化建议】" in result:
suggestions_section = result.split("【优化建议】")[1].split("")[0]
# 品牌名优化建议 - 更健壮的解析
brand_patterns = ["品牌名优化建议", "1. 品牌名优化建议", "品牌名"]
for pattern in brand_patterns:
if pattern in suggestions_section:
brand_section = suggestions_section.split(pattern, 1)[1]
# 找到下一个建议的开始位置
next_patterns = ["2. 优势描述优化建议", "优势描述优化建议", "3. 差异化强化建议"]
for next_pattern in next_patterns:
if next_pattern in brand_section:
brand_section = brand_section.split(next_pattern)[0]
break
if "问题:" in brand_section or "问题" in brand_section:
problem_text = brand_section.split("问题:")[1] if "问题:" in brand_section else brand_section.split("问题")[1]
problem_text = problem_text.split("建议:")[0].split("建议")[0].strip()
if problem_text:
parsed["suggestions"]["brand"]["problem"] = problem_text
if "建议:" in brand_section or "建议" in brand_section:
suggestion_text = brand_section.split("建议:")[1] if "建议:" in brand_section else brand_section.split("建议", 1)[1]
suggestion_text = suggestion_text.split("2.")[0].split("3.")[0].strip()
if suggestion_text:
parsed["suggestions"]["brand"]["suggestion"] = suggestion_text
break
# 优势描述优化建议 - 更健壮的解析
adv_patterns = ["优势描述优化建议", "2. 优势描述优化建议", "优势描述"]
for pattern in adv_patterns:
if pattern in suggestions_section:
adv_section = suggestions_section.split(pattern, 1)[1]
# 找到下一个建议的开始位置
next_patterns = ["3. 差异化强化建议", "差异化强化建议"]
for next_pattern in next_patterns:
if next_pattern in adv_section:
adv_section = adv_section.split(next_pattern)[0]
break
if "问题:" in adv_section or "问题" in adv_section:
problem_text = adv_section.split("问题:")[1] if "问题:" in adv_section else adv_section.split("问题")[1]
problem_text = problem_text.split("建议:")[0].split("建议")[0].strip()
if problem_text:
parsed["suggestions"]["advantages"]["problem"] = problem_text
if "建议:" in adv_section or "建议" in adv_section:
suggestion_text = adv_section.split("建议:")[1] if "建议:" in adv_section else adv_section.split("建议", 1)[1]
suggestion_text = suggestion_text.split("3.")[0].strip()
if suggestion_text:
parsed["suggestions"]["advantages"]["suggestion"] = suggestion_text
break
# 提取推荐版本
if "【推荐版本】" in result:
versions_section = result.split("【推荐版本】")[1].split("")[0]
# 提取3个版本 - 使用更健壮的解析方式
for i in range(1, 4):
# 尝试多种匹配模式
version_patterns = [
f"版本{i}",
f"版本{i}",
f"版本{i}",
f"版本 {i}",
f"Version {i}",
]
version_text = None
for pattern in version_patterns:
if pattern in versions_section:
# 找到版本开始位置
start_idx = versions_section.find(pattern)
version_text = versions_section[start_idx + len(pattern):]
# 找到下一个版本或结束位置
next_patterns = [
f"版本{i+1}" if i < 3 else None,
f"版本{i+1}" if i < 3 else None,
f"版本{i+1}" if i < 3 else None,
"【预期效果】",
"",
]
end_idx = len(version_text)
for next_pattern in next_patterns:
if next_pattern and next_pattern in version_text:
end_idx = min(end_idx, version_text.find(next_pattern))
version_text = version_text[:end_idx].strip()
break
if not version_text:
continue
version_data = {
"version_name": f"版本{i}",
"brand": "",
"advantages": "",
"reason": ""
}
# 提取品牌名 - 支持多种格式,更健壮的解析
brand_patterns = ["品牌名:", "品牌名", "品牌:", "- 品牌名:", "品牌名"]
for pattern in brand_patterns:
if pattern in version_text:
brand_part = version_text.split(pattern, 1)[1]
# 提取到换行、下一个字段或下一个版本
brand = brand_part.split("\n")[0]
# 移除可能的下一个字段标识
for next_field in ["优势描述", "理由", "版本", "- 优势描述", "- 理由"]:
if next_field in brand:
brand = brand.split(next_field)[0]
brand = brand.strip()
# 移除可能的冒号、破折号等
brand = brand.lstrip("").lstrip(":").lstrip("-").lstrip("").strip()
if brand and len(brand) > 0:
version_data["brand"] = brand
break
# 提取优势描述 - 支持多种格式,更健壮的解析
adv_patterns = ["优势描述:", "优势描述", "优势:", "- 优势描述:"]
for pattern in adv_patterns:
if pattern in version_text:
adv_part = version_text.split(pattern, 1)[1]
# 提取到理由或下一个字段
advantages = adv_part.split("理由")[0].split("- 理由")[0].split("版本")[0]
# 处理多行内容
advantages_lines = []
for line in advantages.split("\n"):
line = line.strip()
# 如果遇到下一个字段标识,停止
if any(marker in line for marker in ["理由", "版本", "品牌名"]):
break
if line and not line.startswith("-") and not line.startswith(""):
advantages_lines.append(line)
advantages = " ".join(advantages_lines).strip()
# 移除可能的冒号、破折号等
advantages = advantages.lstrip("").lstrip(":").lstrip("-").lstrip("").strip()
if advantages and len(advantages) > 0:
version_data["advantages"] = advantages
break
# 提取理由 - 支持多种格式,更健壮的解析
reason_patterns = ["理由:", "理由", "- 理由:"]
for pattern in reason_patterns:
if pattern in version_text:
reason_part = version_text.split(pattern, 1)[1]
# 提取到下一个版本或结束
reason = reason_part.split("版本")[0]
# 处理多行内容
reason_lines = []
for line in reason.split("\n"):
line = line.strip()
# 如果遇到下一个版本标识,停止
if "版本" in line and any(str(i+1) in line for i in range(1, 4)):
break
if line and not line.startswith("-") and not line.startswith(""):
reason_lines.append(line)
reason = " ".join(reason_lines).strip()
# 移除可能的冒号、破折号等
reason = reason.lstrip("").lstrip(":").lstrip("-").lstrip("").strip()
if reason and len(reason) > 0:
version_data["reason"] = reason
break
# 只有当至少有一个字段有内容时才添加
if version_data["brand"] or version_data["advantages"]:
parsed["recommended_versions"].append(version_data)
else:
# 记录解析失败的版本
parsed["parse_errors"].append(f"版本{i}解析失败:未找到品牌名或优势描述")
# 提取预期效果
if "【预期效果】" in result:
effects_section = result.split("【预期效果】")[1].strip()
if "提及率提升预期:" in effects_section:
parsed["expected_effects"]["mention_rate"] = effects_section.split("提及率提升预期:")[1].split("\n")[0].strip()
if "GEO友好度提升:" in effects_section:
parsed["expected_effects"]["geo_friendliness"] = effects_section.split("GEO友好度提升:")[1].split("\n")[0].strip()
return parsed
def _parse_optimization_result_fallback(self, result: str, parsed: Dict) -> Dict:
"""备用解析方法,使用更宽松的规则和正则表达式"""
# 如果推荐版本部分存在但解析失败,尝试更宽松的解析
if "【推荐版本】" in result:
versions_section = result.split("【推荐版本】")[1].split("")[0]
# 使用正则表达式提取
import re
# 尝试提取版本1
version1_match = re.search(r'版本1[^版本]*?品牌名[:]\s*([^\n]+)', versions_section, re.DOTALL)
version1_adv_match = re.search(r'版本1[^版本]*?优势描述[:]\s*([^\n]+)', versions_section, re.DOTALL)
if version1_match or version1_adv_match:
v1 = {
"version_name": "版本1",
"brand": version1_match.group(1).strip() if version1_match else "",
"advantages": version1_adv_match.group(1).strip() if version1_adv_match else "",
"reason": ""
}
# 清理品牌名和优势描述
v1["brand"] = v1["brand"].split("优势描述")[0].split("理由")[0].strip()
v1["advantages"] = v1["advantages"].split("理由")[0].split("版本")[0].strip()
if v1["brand"] or v1["advantages"]:
if not parsed["recommended_versions"]:
parsed["recommended_versions"] = []
if len(parsed["recommended_versions"]) < 1:
parsed["recommended_versions"].append(v1)
# 尝试提取版本2
version2_match = re.search(r'版本2[^版本]*?品牌名[:]\s*([^\n]+)', versions_section, re.DOTALL)
version2_adv_match = re.search(r'版本2[^版本]*?优势描述[:]\s*([^\n]+)', versions_section, re.DOTALL)
if version2_match or version2_adv_match:
v2 = {
"version_name": "版本2",
"brand": version2_match.group(1).strip() if version2_match else "",
"advantages": version2_adv_match.group(1).strip() if version2_adv_match else "",
"reason": ""
}
# 清理品牌名和优势描述
v2["brand"] = v2["brand"].split("优势描述")[0].split("理由")[0].strip()
v2["advantages"] = v2["advantages"].split("理由")[0].split("版本")[0].strip()
if v2["brand"] or v2["advantages"]:
if len(parsed["recommended_versions"]) < 2:
parsed["recommended_versions"].append(v2)
# 尝试提取版本3
version3_match = re.search(r'版本3[^版本]*?品牌名[:]\s*([^\n]+)', versions_section, re.DOTALL)
version3_adv_match = re.search(r'版本3[^版本]*?优势描述[:]\s*([^\n]+)', versions_section, re.DOTALL)
if version3_match or version3_adv_match:
v3 = {
"version_name": "版本3",
"brand": version3_match.group(1).strip() if version3_match else "",
"advantages": version3_adv_match.group(1).strip() if version3_adv_match else "",
"reason": ""
}
# 清理品牌名和优势描述
v3["brand"] = v3["brand"].split("优势描述")[0].split("理由")[0].strip()
v3["advantages"] = v3["advantages"].split("理由")[0].split("版本")[0].strip()
if v3["brand"] or v3["advantages"]:
if len(parsed["recommended_versions"]) < 3:
parsed["recommended_versions"].append(v3)
return parsed