File size: 7,945 Bytes
922fd01 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | import streamlit as st
import numpy as np
from sentence_transformers import SentenceTransformer, util
import openai
from datetime import datetime
# --- НАСТРОЙКИ СТРАНИЦЫ ---
st.set_page_config(layout="wide", page_title="SEO Intent Analyzer Pro")
# --- КЭШИРОВАНИЕ МОДЕЛИ (Чтобы не загружать 400мб каждый раз) ---
@st.cache_resource
def load_model():
return SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
try:
model = load_model()
except Exception as e:
st.error(f"Ошибка загрузки модели: {e}")
# --- ИНТЕРФЕЙС: БОКОВАЯ ПАНЕЛЬ ---
st.sidebar.title("⚙️ Настройки")
language = st.sidebar.selectbox(
"Язык анализа",
["English", "Hindi", "Spanish", "Bengali"]
)
api_key = st.sidebar.text_input("OpenAI API Key (для рекомендаций)", type="password")
target_keyword = st.sidebar.text_input("Целевой Интент / Ключ", "online casino guide")
st.sidebar.markdown("---")
st.sidebar.info("Загрузите тексты конкурентов и свой текст, затем нажмите 'Анализировать'.")
# --- ИНТЕРФЕЙС: ОСНОВНАЯ ЧАСТЬ ---
st.title("🚀 Анализатор Интента (SBERT + AI)")
col1, col2 = st.columns(2)
with col1:
st.subheader("📝 Ваш Текст")
user_text = st.text_area("Вставьте ваш контент сюда", height=400)
with col2:
st.subheader("🕵️ Конкуренты")
# Используем табы для конкурентов, чтобы не загромождать экран
tabs = st.tabs([f"Конкурент {i+1}" for i in range(5)])
competitors = []
for i, tab in enumerate(tabs):
with tab:
comp_text = st.text_area(f"Текст конкурента {i+1}", height=320, key=f"comp_{i}")
if len(comp_text) > 50:
competitors.append(comp_text)
# --- ЛОГИКА АНАЛИЗА ---
if st.button("🚀 ЗАПУСТИТЬ АНАЛИЗ", type="primary"):
if not user_text:
st.warning("Пожалуйста, введите ваш текст.")
elif not competitors:
st.warning("Пожалуйста, добавьте хотя бы одного конкурента.")
else:
with st.spinner('Загрузка нейросети и сравнение векторов...'):
# 1. Анализ SBERT
user_emb = model.encode(user_text, convert_to_tensor=True)
comp_embs = [model.encode(c, convert_to_tensor=True) for c in competitors]
# Средний вектор конкурентов
avg_comp_emb = np.mean([c.cpu().numpy() for c in comp_embs], axis=0)
# Сходство
similarity = util.cos_sim(user_emb, avg_comp_emb).item() * 100
# 2. Поиск упущенных аспектов (Gap Analysis)
user_sentences = user_text.split('.')
# Собираем все предложения конкурентов в кучу
comp_sentences_flat = []
for c in competitors:
comp_sentences_flat.extend([s for s in c.split('.') if len(s) > 30])
# Кодируем предложения
user_sent_embs = model.encode(user_sentences, convert_to_tensor=True)
comp_sent_embs = model.encode(comp_sentences_flat, convert_to_tensor=True)
# Матрица схожести
cos_scores = util.cos_sim(comp_sent_embs, user_sent_embs)
missing_aspects = []
# Если предложение конкурента не похоже ни на одно наше (score < 0.45)
for idx, scores in enumerate(cos_scores):
if scores.max() < 0.45:
missing_aspects.append(comp_sentences_flat[idx].strip())
# Убираем дубли и берем топ-5
missing_aspects = list(set(missing_aspects))[:5]
# 3. AI Рекомендации
recommendations = []
if api_key and missing_aspects:
openai.api_key = api_key
status_text = st.empty()
status_text.text("Генерация рекомендаций через GPT...")
for aspect in missing_aspects:
prompt = f"""
Role: Expert SEO Copywriter.
Language: {language}.
Task: My competitors mention: "{aspect}", but I missed it.
Action: Write a paragraph (HTML format) to insert into my article to cover this topic.
"""
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
max_tokens=300
)
recommendations.append(response.choices[0].message.content)
except Exception as e:
st.error(f"AI Error: {e}")
status_text.empty()
# --- ВЫВОД РЕЗУЛЬТАТОВ ---
st.divider()
st.header("📊 Результаты Анализа")
# Метрики
m1, m2, m3 = st.columns(3)
m1.metric("Сходство с Топом", f"{similarity:.1f}%")
m2.metric("Длина вашего текста", f"{len(user_text.split())} слов")
m3.metric("Среднее у конкурентов", f"{int(np.mean([len(c.split()) for c in competitors]))} слов")
# Визуализация прогресса
st.write("Шкала раскрытия интента:")
st.progress(min(int(similarity), 100))
# Таблица сравнения
col_res1, col_res2 = st.columns(2)
with col_res1:
st.subheader("⚠️ Упущенные аспекты (Gaps)")
if missing_aspects:
for gap in missing_aspects:
st.error(f"У конкурентов: \"{gap}\"")
else:
st.success("Явных пробелов в интенте не найдено!")
with col_res2:
st.subheader("💡 Рекомендации к внедрению")
if recommendations:
for rec in recommendations:
st.code(rec, language="html")
st.caption("Скопируйте код выше и вставьте в статью")
elif not api_key:
st.info("Введите API Key слева, чтобы получить готовый текст исправлений.")
else:
st.info("Рекомендации не требуются.")
# Экспорт
report_text = f"""
<h1>SEO Report - {target_keyword}</h1>
<p>Date: {datetime.now()}</p>
<p>Similarity: {similarity:.2f}%</p>
<h2>Missing Aspects:</h2>
<ul>{''.join([f'<li>{m}</li>' for m in missing_aspects])}</ul>
<h2>AI Recommendations:</h2>
{''.join(recommendations)}
"""
st.download_button(
label="📥 Скачать HTML отчет",
data=report_text,
file_name="seo_report.html",
mime="text/html"
)
|