| 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") |
|
|
| |
| @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('Загрузка нейросети и сравнение векторов...'): |
| |
| 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 |
| |
| |
| 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 = [] |
| |
| for idx, scores in enumerate(cos_scores): |
| if scores.max() < 0.45: |
| missing_aspects.append(comp_sentences_flat[idx].strip()) |
| |
| |
| missing_aspects = list(set(missing_aspects))[:5] |
| |
| |
| 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" |
| ) |
|
|
|
|