Files

419 lines
20 KiB
Python
Raw Permalink Normal View History

"""
配置优化助手模块
分析品牌名和优势是否 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